summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/code-assembler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler/code-assembler.cc')
-rw-r--r--deps/v8/src/compiler/code-assembler.cc201
1 files changed, 186 insertions, 15 deletions
diff --git a/deps/v8/src/compiler/code-assembler.cc b/deps/v8/src/compiler/code-assembler.cc
index 1ace7dae5e..1bde4c6a4c 100644
--- a/deps/v8/src/compiler/code-assembler.cc
+++ b/deps/v8/src/compiler/code-assembler.cc
@@ -31,6 +31,11 @@
#define REPEAT_1_TO_7(V, T) REPEAT_1_TO_6(V, T) V(T, T, T, T, T, T, T)
#define REPEAT_1_TO_8(V, T) REPEAT_1_TO_7(V, T) V(T, T, T, T, T, T, T, T)
#define REPEAT_1_TO_9(V, T) REPEAT_1_TO_8(V, T) V(T, T, T, T, T, T, T, T, T)
+#define REPEAT_1_TO_10(V, T) REPEAT_1_TO_9(V, T) V(T, T, T, T, T, T, T, T, T, T)
+#define REPEAT_1_TO_11(V, T) \
+ REPEAT_1_TO_10(V, T) V(T, T, T, T, T, T, T, T, T, T, T)
+#define REPEAT_1_TO_12(V, T) \
+ REPEAT_1_TO_11(V, T) V(T, T, T, T, T, T, T, T, T, T, T, T)
namespace v8 {
namespace internal {
@@ -79,6 +84,21 @@ int CodeAssemblerState::parameter_count() const {
CodeAssembler::~CodeAssembler() {}
+#if DEBUG
+void CodeAssemblerState::PrintCurrentBlock(std::ostream& os) {
+ raw_assembler_->PrintCurrentBlock(os);
+}
+#endif
+
+void CodeAssemblerState::SetInitialDebugInformation(const char* msg,
+ const char* file,
+ int line) {
+#if DEBUG
+ AssemblerDebugInfo debug_info = {msg, file, line};
+ raw_assembler_->SetInitialDebugInformation(debug_info);
+#endif // DEBUG
+}
+
class BreakOnNodeDecorator final : public GraphDecorator {
public:
explicit BreakOnNodeDecorator(NodeId node_id) : node_id_(node_id) {}
@@ -160,6 +180,19 @@ bool CodeAssembler::IsFloat64RoundTruncateSupported() const {
return raw_assembler()->machine()->Float64RoundTruncate().IsSupported();
}
+bool CodeAssembler::IsInt32AbsWithOverflowSupported() const {
+ return raw_assembler()->machine()->Int32AbsWithOverflow().IsSupported();
+}
+
+bool CodeAssembler::IsInt64AbsWithOverflowSupported() const {
+ return raw_assembler()->machine()->Int64AbsWithOverflow().IsSupported();
+}
+
+bool CodeAssembler::IsIntPtrAbsWithOverflowSupported() const {
+ return Is64() ? IsInt64AbsWithOverflowSupported()
+ : IsInt32AbsWithOverflowSupported();
+}
+
Node* CodeAssembler::Int32Constant(int32_t value) {
return raw_assembler()->Int32Constant(value);
}
@@ -277,6 +310,14 @@ void CodeAssembler::PopAndReturn(Node* pop, Node* value) {
return raw_assembler()->PopAndReturn(pop, value);
}
+void CodeAssembler::ReturnIf(Node* condition, Node* value) {
+ Label if_return(this), if_continue(this);
+ Branch(condition, &if_return, &if_continue);
+ Bind(&if_return);
+ Return(value);
+ Bind(&if_continue);
+}
+
void CodeAssembler::DebugBreak() { raw_assembler()->DebugBreak(); }
void CodeAssembler::Unreachable() {
@@ -306,6 +347,12 @@ void CodeAssembler::Comment(const char* format, ...) {
void CodeAssembler::Bind(Label* label) { return label->Bind(); }
+#if DEBUG
+void CodeAssembler::Bind(Label* label, AssemblerDebugInfo debug_info) {
+ return label->Bind(debug_info);
+}
+#endif // DEBUG
+
Node* CodeAssembler::LoadFramePointer() {
return raw_assembler()->LoadFramePointer();
}
@@ -391,6 +438,13 @@ Node* CodeAssembler::ChangeInt32ToIntPtr(Node* value) {
return value;
}
+Node* CodeAssembler::ChangeFloat64ToUintPtr(Node* value) {
+ if (raw_assembler()->machine()->Is64()) {
+ return raw_assembler()->ChangeFloat64ToUint64(value);
+ }
+ return raw_assembler()->ChangeFloat64ToUint32(value);
+}
+
Node* CodeAssembler::RoundIntPtrToFloat64(Node* value) {
if (raw_assembler()->machine()->Is64()) {
return raw_assembler()->RoundInt64ToFloat64(value);
@@ -462,6 +516,26 @@ Node* CodeAssembler::AtomicStore(MachineRepresentation rep, Node* base,
return raw_assembler()->AtomicStore(rep, base, offset, value);
}
+#define ATOMIC_FUNCTION(name) \
+ Node* CodeAssembler::Atomic##name(MachineType type, Node* base, \
+ Node* offset, Node* value) { \
+ return raw_assembler()->Atomic##name(type, base, offset, value); \
+ }
+ATOMIC_FUNCTION(Exchange);
+ATOMIC_FUNCTION(Add);
+ATOMIC_FUNCTION(Sub);
+ATOMIC_FUNCTION(And);
+ATOMIC_FUNCTION(Or);
+ATOMIC_FUNCTION(Xor);
+#undef ATOMIC_FUNCTION
+
+Node* CodeAssembler::AtomicCompareExchange(MachineType type, Node* base,
+ Node* offset, Node* old_value,
+ Node* new_value) {
+ return raw_assembler()->AtomicCompareExchange(type, base, offset, old_value,
+ new_value);
+}
+
Node* CodeAssembler::StoreRoot(Heap::RootListIndex root_index, Node* value) {
DCHECK(Heap::RootCanBeWrittenAfterInitialization(root_index));
Node* roots_array_start =
@@ -520,7 +594,7 @@ Node* CodeAssembler::CallRuntime(Runtime::FunctionId function, Node* context,
return return_value;
}
-// Instantiate CallRuntime() with up to 6 arguments.
+// Instantiate CallRuntime() for argument counts used by CSA-generated code
#define INSTANTIATE(...) \
template V8_EXPORT_PRIVATE Node* CodeAssembler::CallRuntime( \
Runtime::FunctionId, __VA_ARGS__);
@@ -546,7 +620,7 @@ Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function,
return raw_assembler()->TailCallN(desc, arraysize(nodes), nodes);
}
-// Instantiate TailCallRuntime() with up to 6 arguments.
+// Instantiate TailCallRuntime() for argument counts used by CSA-generated code
#define INSTANTIATE(...) \
template V8_EXPORT_PRIVATE Node* CodeAssembler::TailCallRuntime( \
Runtime::FunctionId, __VA_ARGS__);
@@ -561,11 +635,11 @@ Node* CodeAssembler::CallStubR(const CallInterfaceDescriptor& descriptor,
return CallStubN(descriptor, result_size, arraysize(nodes), nodes);
}
-// Instantiate CallStubR() with up to 6 arguments.
+// Instantiate CallStubR() for argument counts used by CSA-generated code.
#define INSTANTIATE(...) \
template V8_EXPORT_PRIVATE Node* CodeAssembler::CallStubR( \
const CallInterfaceDescriptor& descriptor, size_t, Node*, __VA_ARGS__);
-REPEAT_1_TO_7(INSTANTIATE, Node*)
+REPEAT_1_TO_8(INSTANTIATE, Node*)
#undef INSTANTIATE
Node* CodeAssembler::CallStubN(const CallInterfaceDescriptor& descriptor,
@@ -600,15 +674,15 @@ Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
MachineType::AnyTagged(), result_size);
Node* nodes[] = {target, args..., context};
-
+ CHECK_EQ(descriptor.GetParameterCount() + 2, arraysize(nodes));
return raw_assembler()->TailCallN(desc, arraysize(nodes), nodes);
}
-// Instantiate TailCallStub() with up to 6 arguments.
+// Instantiate TailCallStub() for argument counts used by CSA-generated code
#define INSTANTIATE(...) \
template V8_EXPORT_PRIVATE Node* CodeAssembler::TailCallStub( \
const CallInterfaceDescriptor& descriptor, Node*, __VA_ARGS__);
-REPEAT_1_TO_7(INSTANTIATE, Node*)
+REPEAT_1_TO_12(INSTANTIATE, Node*)
#undef INSTANTIATE
template <class... TArgs>
@@ -619,10 +693,12 @@ Node* CodeAssembler::TailCallBytecodeDispatch(
isolate(), zone(), descriptor, descriptor.GetStackParameterCount());
Node* nodes[] = {target, args...};
+ CHECK_EQ(descriptor.GetParameterCount() + 1, arraysize(nodes));
return raw_assembler()->TailCallN(desc, arraysize(nodes), nodes);
}
-// Instantiate TailCallBytecodeDispatch() with 4 arguments.
+// Instantiate TailCallBytecodeDispatch() for argument counts used by
+// CSA-generated code
template V8_EXPORT_PRIVATE Node* CodeAssembler::TailCallBytecodeDispatch(
const CallInterfaceDescriptor& descriptor, Node* target, Node*, Node*,
Node*, Node*);
@@ -690,6 +766,17 @@ void CodeAssembler::Switch(Node* index, Label* default_label,
labels, case_count);
}
+bool CodeAssembler::UnalignedLoadSupported(const MachineType& machineType,
+ uint8_t alignment) const {
+ return raw_assembler()->machine()->UnalignedLoadSupported(machineType,
+ alignment);
+}
+bool CodeAssembler::UnalignedStoreSupported(const MachineType& machineType,
+ uint8_t alignment) const {
+ return raw_assembler()->machine()->UnalignedStoreSupported(machineType,
+ alignment);
+}
+
// RawMachineAssembler delegate helpers:
Isolate* CodeAssembler::isolate() const { return raw_assembler()->isolate(); }
@@ -707,7 +794,23 @@ RawMachineAssembler* CodeAssembler::raw_assembler() const {
// properly be verified.
class CodeAssemblerVariable::Impl : public ZoneObject {
public:
- explicit Impl(MachineRepresentation rep) : value_(nullptr), rep_(rep) {}
+ explicit Impl(MachineRepresentation rep)
+ :
+#if DEBUG
+ debug_info_(AssemblerDebugInfo(nullptr, nullptr, -1)),
+#endif
+ value_(nullptr),
+ rep_(rep) {
+ }
+
+#if DEBUG
+ AssemblerDebugInfo debug_info() const { return debug_info_; }
+ void set_debug_info(AssemblerDebugInfo debug_info) {
+ debug_info_ = debug_info;
+ }
+
+ AssemblerDebugInfo debug_info_;
+#endif // DEBUG
Node* value_;
MachineRepresentation rep_;
};
@@ -725,6 +828,25 @@ CodeAssemblerVariable::CodeAssemblerVariable(CodeAssembler* assembler,
Bind(initial_value);
}
+#if DEBUG
+CodeAssemblerVariable::CodeAssemblerVariable(CodeAssembler* assembler,
+ AssemblerDebugInfo debug_info,
+ MachineRepresentation rep)
+ : impl_(new (assembler->zone()) Impl(rep)), state_(assembler->state()) {
+ impl_->set_debug_info(debug_info);
+ state_->variables_.insert(impl_);
+}
+
+CodeAssemblerVariable::CodeAssemblerVariable(CodeAssembler* assembler,
+ AssemblerDebugInfo debug_info,
+ MachineRepresentation rep,
+ Node* initial_value)
+ : CodeAssemblerVariable(assembler, debug_info, rep) {
+ impl_->set_debug_info(debug_info);
+ Bind(initial_value);
+}
+#endif // DEBUG
+
CodeAssemblerVariable::~CodeAssemblerVariable() {
state_->variables_.erase(impl_);
}
@@ -732,7 +854,18 @@ CodeAssemblerVariable::~CodeAssemblerVariable() {
void CodeAssemblerVariable::Bind(Node* value) { impl_->value_ = value; }
Node* CodeAssemblerVariable::value() const {
- DCHECK_NOT_NULL(impl_->value_);
+#if DEBUG
+ if (!IsBound()) {
+ std::stringstream str;
+ str << "#Use of unbound variable:"
+ << "#\n Variable: " << *this;
+ if (state_) {
+ str << "#\n Current Block: ";
+ state_->PrintCurrentBlock(str);
+ }
+ FATAL(str.str().c_str());
+ }
+#endif // DEBUG
return impl_->value_;
}
@@ -740,9 +873,24 @@ MachineRepresentation CodeAssemblerVariable::rep() const { return impl_->rep_; }
bool CodeAssemblerVariable::IsBound() const { return impl_->value_ != nullptr; }
+std::ostream& operator<<(std::ostream& os,
+ const CodeAssemblerVariable::Impl& impl) {
+#if DEBUG
+ AssemblerDebugInfo info = impl.debug_info();
+ if (info.name) os << "V" << info;
+#endif // DEBUG
+ return os;
+}
+
+std::ostream& operator<<(std::ostream& os,
+ const CodeAssemblerVariable& variable) {
+ os << *variable.impl_;
+ return os;
+}
+
CodeAssemblerLabel::CodeAssemblerLabel(CodeAssembler* assembler,
size_t vars_count,
- CodeAssemblerVariable** vars,
+ CodeAssemblerVariable* const* vars,
CodeAssemblerLabel::Type type)
: bound_(false),
merge_count_(0),
@@ -761,7 +909,7 @@ CodeAssemblerLabel::~CodeAssemblerLabel() { label_->~RawMachineLabel(); }
void CodeAssemblerLabel::MergeVariables() {
++merge_count_;
- for (auto var : state_->variables_) {
+ for (CodeAssemblerVariable::Impl* var : state_->variables_) {
size_t count = 0;
Node* node = var->value_;
if (node != nullptr) {
@@ -796,19 +944,42 @@ void CodeAssemblerLabel::MergeVariables() {
// the variable after the label bind (it's not possible to add phis to
// the bound label after the fact, just make sure to list the variable
// in the label's constructor's list of merged variables).
- DCHECK(find_if(i->second.begin(), i->second.end(),
- [node](Node* e) -> bool { return node != e; }) ==
- i->second.end());
+#if DEBUG
+ if (find_if(i->second.begin(), i->second.end(),
+ [node](Node* e) -> bool { return node != e; }) !=
+ i->second.end()) {
+ std::stringstream str;
+ str << "Unmerged variable found when jumping to block. \n"
+ << "# Variable: " << *var;
+ if (bound_) {
+ str << "\n# Target block: " << *label_->block();
+ }
+ str << "\n# Current Block: ";
+ state_->PrintCurrentBlock(str);
+ FATAL(str.str().c_str());
+ }
+#endif // DEBUG
}
}
}
}
}
+#if DEBUG
+void CodeAssemblerLabel::Bind(AssemblerDebugInfo debug_info) {
+ DCHECK(!bound_);
+ state_->raw_assembler_->Bind(label_, debug_info);
+ UpdateVariablesAfterBind();
+}
+#endif // DEBUG
+
void CodeAssemblerLabel::Bind() {
DCHECK(!bound_);
state_->raw_assembler_->Bind(label_);
+ UpdateVariablesAfterBind();
+}
+void CodeAssemblerLabel::UpdateVariablesAfterBind() {
// Make sure that all variables that have changed along any path up to this
// point are marked as merge variables.
for (auto var : state_->variables_) {