5 #include "src/compiler/code-assembler.h" 9 #include "src/code-factory.h" 10 #include "src/compiler/backend/instruction-selector.h" 11 #include "src/compiler/graph.h" 12 #include "src/compiler/linkage.h" 13 #include "src/compiler/node-matchers.h" 14 #include "src/compiler/pipeline.h" 15 #include "src/compiler/raw-machine-assembler.h" 16 #include "src/compiler/schedule.h" 17 #include "src/frames.h" 18 #include "src/interface-descriptors.h" 19 #include "src/interpreter/bytecodes.h" 21 #include "src/machine-type.h" 22 #include "src/macro-assembler.h" 23 #include "src/objects-inl.h" 24 #include "src/objects/smi.h" 25 #include "src/utils.h" 26 #include "src/zone/zone.h" 31 constexpr MachineType MachineTypeOf<Smi>::value;
32 constexpr MachineType MachineTypeOf<Object>::value;
36 static_assert(std::is_convertible<TNode<Number>, TNode<Object>>::value,
38 static_assert(std::is_convertible<TNode<UnionT<Smi, HeapNumber>>,
39 TNode<UnionT<Smi, HeapObject>>>::value,
42 !std::is_convertible<TNode<UnionT<Smi, HeapObject>>, TNode<Number>>::value,
45 CodeAssemblerState::CodeAssemblerState(
46 Isolate* isolate, Zone* zone,
const CallInterfaceDescriptor& descriptor,
47 Code::Kind kind,
const char* name, PoisoningMitigationLevel poisoning_level,
48 uint32_t stub_key, int32_t builtin_index)
53 Linkage::GetStubCallDescriptor(
54 zone, descriptor, descriptor.GetStackParameterCount(),
55 CallDescriptor::kNoFlags, Operator::kNoProperties),
56 kind, name, poisoning_level, stub_key, builtin_index) {}
58 CodeAssemblerState::CodeAssemblerState(Isolate* isolate, Zone* zone,
59 int parameter_count, Code::Kind kind,
61 PoisoningMitigationLevel poisoning_level,
62 int32_t builtin_index)
65 Linkage::GetJSCallDescriptor(
66 zone, false, parameter_count,
67 (kind == Code::BUILTIN ? CallDescriptor::kPushArgumentCount
68 : CallDescriptor::kNoFlags) |
69 CallDescriptor::kCanUseRoots),
70 kind, name, poisoning_level, 0, builtin_index) {}
72 CodeAssemblerState::CodeAssemblerState(Isolate* isolate, Zone* zone,
73 CallDescriptor* call_descriptor,
74 Code::Kind kind,
const char* name,
75 PoisoningMitigationLevel poisoning_level,
76 uint32_t stub_key, int32_t builtin_index)
77 : raw_assembler_(new RawMachineAssembler(
78 isolate, new (zone) Graph(zone), call_descriptor,
79 MachineType::PointerRepresentation(),
80 InstructionSelector::SupportedMachineOperatorFlags(),
81 InstructionSelector::AlignmentRequirements(), poisoning_level)),
85 builtin_index_(builtin_index),
86 code_generated_(false),
89 CodeAssemblerState::~CodeAssemblerState() =
default;
91 int CodeAssemblerState::parameter_count()
const {
92 return static_cast<int>(raw_assembler_->call_descriptor()->ParameterCount());
95 CodeAssembler::~CodeAssembler() =
default;
98 void CodeAssemblerState::PrintCurrentBlock(std::ostream& os) {
99 raw_assembler_->PrintCurrentBlock(os);
103 bool CodeAssemblerState::InsideBlock() {
return raw_assembler_->InsideBlock(); }
105 void CodeAssemblerState::SetInitialDebugInformation(
const char* msg,
109 AssemblerDebugInfo debug_info = {msg, file, line};
110 raw_assembler_->SetInitialDebugInformation(debug_info);
118 void Decorate(
Node* node)
final {
119 if (node->id() == node_id_) {
120 base::OS::DebugBreak();
128 void CodeAssembler::BreakOnNode(
int node_id) {
129 Graph* graph = raw_assembler()->graph();
130 Zone* zone = graph->zone();
133 graph->AddDecorator(decorator);
136 void CodeAssembler::RegisterCallGenerationCallbacks(
137 const CodeAssemblerCallback& call_prologue,
138 const CodeAssemblerCallback& call_epilogue) {
140 DCHECK(!state_->call_prologue_);
141 DCHECK(!state_->call_epilogue_);
142 state_->call_prologue_ = call_prologue;
143 state_->call_epilogue_ = call_epilogue;
146 void CodeAssembler::UnregisterCallGenerationCallbacks() {
147 state_->call_prologue_ =
nullptr;
148 state_->call_epilogue_ =
nullptr;
151 void CodeAssembler::CallPrologue() {
152 if (state_->call_prologue_) {
153 state_->call_prologue_();
157 void CodeAssembler::CallEpilogue() {
158 if (state_->call_epilogue_) {
159 state_->call_epilogue_();
163 bool CodeAssembler::Word32ShiftIsSafe()
const {
164 return raw_assembler()->machine()->Word32ShiftIsSafe();
167 PoisoningMitigationLevel CodeAssembler::poisoning_level()
const {
168 return raw_assembler()->poisoning_level();
172 Handle<Code> CodeAssembler::GenerateCode(CodeAssemblerState* state,
173 const AssemblerOptions& options) {
174 DCHECK(!state->code_generated_);
176 RawMachineAssembler* rasm = state->raw_assembler_.get();
179 if (FLAG_optimize_csa) {
181 DCHECK(!FLAG_turbo_rewrite_far_jumps);
182 Graph* graph = rasm->ExportForOptimization();
184 code = Pipeline::GenerateCodeForCodeStub(
185 rasm->isolate(), rasm->call_descriptor(), graph,
nullptr,
186 state->kind_, state->name_, state->stub_key_,
187 state->builtin_index_,
nullptr, rasm->poisoning_level(), options)
190 Schedule* schedule = rasm->Export();
192 JumpOptimizationInfo jump_opt;
193 bool should_optimize_jumps =
194 rasm->isolate()->serializer_enabled() && FLAG_turbo_rewrite_far_jumps;
197 Pipeline::GenerateCodeForCodeStub(
198 rasm->isolate(), rasm->call_descriptor(), rasm->graph(), schedule,
199 state->kind_, state->name_, state->stub_key_, state->builtin_index_,
200 should_optimize_jumps ? &jump_opt :
nullptr,
201 rasm->poisoning_level(), options)
204 if (jump_opt.is_optimizable()) {
205 jump_opt.set_optimizing();
208 code = Pipeline::GenerateCodeForCodeStub(
209 rasm->isolate(), rasm->call_descriptor(), rasm->graph(),
210 schedule, state->kind_, state->name_, state->stub_key_,
211 state->builtin_index_, &jump_opt, rasm->poisoning_level(),
217 state->code_generated_ =
true;
221 bool CodeAssembler::Is64()
const {
return raw_assembler()->machine()->Is64(); }
223 bool CodeAssembler::IsFloat64RoundUpSupported()
const {
224 return raw_assembler()->machine()->Float64RoundUp().IsSupported();
227 bool CodeAssembler::IsFloat64RoundDownSupported()
const {
228 return raw_assembler()->machine()->Float64RoundDown().IsSupported();
231 bool CodeAssembler::IsFloat64RoundTiesEvenSupported()
const {
232 return raw_assembler()->machine()->Float64RoundTiesEven().IsSupported();
235 bool CodeAssembler::IsFloat64RoundTruncateSupported()
const {
236 return raw_assembler()->machine()->Float64RoundTruncate().IsSupported();
239 bool CodeAssembler::IsInt32AbsWithOverflowSupported()
const {
240 return raw_assembler()->machine()->Int32AbsWithOverflow().IsSupported();
243 bool CodeAssembler::IsInt64AbsWithOverflowSupported()
const {
244 return raw_assembler()->machine()->Int64AbsWithOverflow().IsSupported();
247 bool CodeAssembler::IsIntPtrAbsWithOverflowSupported()
const {
248 return Is64() ? IsInt64AbsWithOverflowSupported()
249 : IsInt32AbsWithOverflowSupported();
253 void CodeAssembler::GenerateCheckMaybeObjectIsObject(Node* node,
254 const char* location) {
256 GotoIf(WordNotEqual(WordAnd(BitcastMaybeObjectToWord(node),
257 IntPtrConstant(kHeapObjectTagMask)),
258 IntPtrConstant(kWeakHeapObjectTag)),
260 Node* message_node = StringConstant(location);
261 DebugAbort(message_node);
267 TNode<Int32T> CodeAssembler::Int32Constant(int32_t value) {
268 return UncheckedCast<Int32T>(raw_assembler()->Int32Constant(value));
271 TNode<Int64T> CodeAssembler::Int64Constant(
int64_t value) {
272 return UncheckedCast<Int64T>(raw_assembler()->Int64Constant(value));
275 TNode<IntPtrT> CodeAssembler::IntPtrConstant(intptr_t value) {
276 return UncheckedCast<IntPtrT>(raw_assembler()->IntPtrConstant(value));
279 TNode<Number> CodeAssembler::NumberConstant(
double value) {
281 if (DoubleToSmiInteger(value, &smi_value)) {
282 return UncheckedCast<Number>(SmiConstant(smi_value));
288 return UncheckedCast<Number>(
289 HeapConstant(isolate()->factory()->NewHeapNumber(value, TENURED)));
293 TNode<Smi> CodeAssembler::SmiConstant(Smi value) {
294 return UncheckedCast<Smi>(BitcastWordToTaggedSigned(
295 IntPtrConstant(static_cast<intptr_t>(value.ptr()))));
298 TNode<Smi> CodeAssembler::SmiConstant(
int value) {
299 return SmiConstant(Smi::FromInt(value));
302 TNode<HeapObject> CodeAssembler::UntypedHeapConstant(
303 Handle<HeapObject>
object) {
304 return UncheckedCast<HeapObject>(raw_assembler()->HeapConstant(
object));
307 TNode<String> CodeAssembler::StringConstant(
const char* str) {
308 Handle<String> internalized_string =
309 factory()->InternalizeOneByteString(OneByteVector(str));
310 return UncheckedCast<String>(HeapConstant(internalized_string));
313 TNode<Oddball> CodeAssembler::BooleanConstant(
bool value) {
314 Handle<Object>
object = isolate()->factory()->ToBoolean(value);
315 return UncheckedCast<Oddball>(
316 raw_assembler()->HeapConstant(Handle<HeapObject>::cast(
object)));
319 TNode<ExternalReference> CodeAssembler::ExternalConstant(
320 ExternalReference address) {
321 return UncheckedCast<ExternalReference>(
322 raw_assembler()->ExternalConstant(address));
325 TNode<Float64T> CodeAssembler::Float64Constant(
double value) {
326 return UncheckedCast<Float64T>(raw_assembler()->Float64Constant(value));
329 TNode<HeapNumber> CodeAssembler::NaNConstant() {
330 return UncheckedCast<HeapNumber>(LoadRoot(RootIndex::kNanValue));
333 bool CodeAssembler::ToInt32Constant(Node* node, int32_t& out_value) {
335 Int64Matcher m(node);
336 if (m.HasValue() && m.IsInRange(std::numeric_limits<int32_t>::min(),
337 std::numeric_limits<int32_t>::max())) {
338 out_value =
static_cast<int32_t
>(m.Value());
344 Int32Matcher m(node);
346 out_value = m.Value();
354 bool CodeAssembler::ToInt64Constant(Node* node,
int64_t& out_value) {
355 Int64Matcher m(node);
356 if (m.HasValue()) out_value = m.Value();
360 bool CodeAssembler::ToSmiConstant(Node* node, Smi* out_value) {
361 if (node->opcode() == IrOpcode::kBitcastWordToTaggedSigned) {
362 node = node->InputAt(0);
364 IntPtrMatcher m(node);
366 intptr_t value = m.Value();
368 CHECK_EQ(0, value & ((static_cast<intptr_t>(1) << kSmiShiftSize) - 1));
369 *out_value = Smi(static_cast<Address>(value));
375 bool CodeAssembler::ToIntPtrConstant(Node* node, intptr_t& out_value) {
376 if (node->opcode() == IrOpcode::kBitcastWordToTaggedSigned ||
377 node->opcode() == IrOpcode::kBitcastWordToTagged) {
378 node = node->InputAt(0);
380 IntPtrMatcher m(node);
381 if (m.HasValue()) out_value = m.Value();
385 bool CodeAssembler::IsUndefinedConstant(TNode<Object> node) {
386 compiler::HeapObjectMatcher m(node);
387 return m.Is(isolate()->factory()->undefined_value());
390 bool CodeAssembler::IsNullConstant(TNode<Object> node) {
391 compiler::HeapObjectMatcher m(node);
392 return m.Is(isolate()->factory()->null_value());
395 Node* CodeAssembler::Parameter(
int index) {
396 if (index == kTargetParameterIndex)
return raw_assembler()->TargetParameter();
397 return raw_assembler()->Parameter(index);
400 bool CodeAssembler::IsJSFunctionCall()
const {
401 auto call_descriptor = raw_assembler()->call_descriptor();
402 return call_descriptor->IsJSFunctionCall();
405 TNode<Context> CodeAssembler::GetJSContextParameter() {
406 auto call_descriptor = raw_assembler()->call_descriptor();
407 DCHECK(call_descriptor->IsJSFunctionCall());
408 return CAST(Parameter(Linkage::GetJSCallContextParamIndex(
409 static_cast<int>(call_descriptor->JSParameterCount()))));
412 void CodeAssembler::Return(SloppyTNode<Object> value) {
413 return raw_assembler()->Return(value);
416 void CodeAssembler::Return(SloppyTNode<Object> value1,
417 SloppyTNode<Object> value2) {
418 return raw_assembler()->Return(value1, value2);
421 void CodeAssembler::Return(SloppyTNode<Object> value1,
422 SloppyTNode<Object> value2,
423 SloppyTNode<Object> value3) {
424 return raw_assembler()->Return(value1, value2, value3);
427 void CodeAssembler::PopAndReturn(Node* pop, Node* value) {
428 return raw_assembler()->PopAndReturn(pop, value);
431 void CodeAssembler::ReturnIf(Node* condition, Node* value) {
432 Label if_return(
this), if_continue(
this);
433 Branch(condition, &if_return, &if_continue);
439 void CodeAssembler::ReturnRaw(Node* value) {
440 return raw_assembler()->Return(value);
443 void CodeAssembler::DebugAbort(Node* message) {
444 raw_assembler()->DebugAbort(message);
447 void CodeAssembler::DebugBreak() { raw_assembler()->DebugBreak(); }
449 void CodeAssembler::Unreachable() {
451 raw_assembler()->Unreachable();
454 void CodeAssembler::Comment(
const char* format, ...) {
455 if (!FLAG_code_comments)
return;
457 StringBuilder builder(buffer, arraysize(buffer));
459 va_start(arguments, format);
460 builder.AddFormattedList(format, arguments);
465 const int prefix_len = 2;
466 int length = builder.position() + 1;
467 char* copy =
reinterpret_cast<char*
>(malloc(length + prefix_len));
468 LSAN_IGNORE_OBJECT(copy);
469 MemCopy(copy + prefix_len, builder.Finalize(), length);
472 raw_assembler()->Comment(copy);
475 void CodeAssembler::Bind(Label* label) {
return label->Bind(); }
478 void CodeAssembler::Bind(Label* label, AssemblerDebugInfo debug_info) {
479 return label->Bind(debug_info);
483 Node* CodeAssembler::LoadFramePointer() {
484 return raw_assembler()->LoadFramePointer();
487 Node* CodeAssembler::LoadParentFramePointer() {
488 return raw_assembler()->LoadParentFramePointer();
491 Node* CodeAssembler::LoadStackPointer() {
492 return raw_assembler()->LoadStackPointer();
495 TNode<Object> CodeAssembler::TaggedPoisonOnSpeculation(
496 SloppyTNode<Object> value) {
497 return UncheckedCast<Object>(
498 raw_assembler()->TaggedPoisonOnSpeculation(value));
501 TNode<WordT> CodeAssembler::WordPoisonOnSpeculation(SloppyTNode<WordT> value) {
502 return UncheckedCast<WordT>(raw_assembler()->WordPoisonOnSpeculation(value));
505 #define DEFINE_CODE_ASSEMBLER_BINARY_OP(name, ResType, Arg1Type, Arg2Type) \ 506 TNode<ResType> CodeAssembler::name(SloppyTNode<Arg1Type> a, \ 507 SloppyTNode<Arg2Type> b) { \ 508 return UncheckedCast<ResType>(raw_assembler()->name(a, b)); \ 510 CODE_ASSEMBLER_BINARY_OP_LIST(DEFINE_CODE_ASSEMBLER_BINARY_OP)
511 #undef DEFINE_CODE_ASSEMBLER_BINARY_OP 513 TNode<WordT> CodeAssembler::IntPtrAdd(SloppyTNode<WordT> left,
514 SloppyTNode<WordT> right) {
515 intptr_t left_constant;
516 bool is_left_constant = ToIntPtrConstant(left, left_constant);
517 intptr_t right_constant;
518 bool is_right_constant = ToIntPtrConstant(right, right_constant);
519 if (is_left_constant) {
520 if (is_right_constant) {
521 return IntPtrConstant(left_constant + right_constant);
523 if (left_constant == 0) {
526 }
else if (is_right_constant) {
527 if (right_constant == 0) {
531 return UncheckedCast<WordT>(raw_assembler()->IntPtrAdd(left, right));
534 TNode<IntPtrT> CodeAssembler::IntPtrDiv(TNode<IntPtrT> left,
535 TNode<IntPtrT> right) {
536 intptr_t left_constant;
537 bool is_left_constant = ToIntPtrConstant(left, left_constant);
538 intptr_t right_constant;
539 bool is_right_constant = ToIntPtrConstant(right, right_constant);
540 if (is_right_constant) {
541 if (is_left_constant) {
542 return IntPtrConstant(left_constant / right_constant);
544 if (base::bits::IsPowerOfTwo(right_constant)) {
545 return WordSar(left, WhichPowerOf2(right_constant));
548 return UncheckedCast<IntPtrT>(raw_assembler()->IntPtrDiv(left, right));
551 TNode<WordT> CodeAssembler::IntPtrSub(SloppyTNode<WordT> left,
552 SloppyTNode<WordT> right) {
553 intptr_t left_constant;
554 bool is_left_constant = ToIntPtrConstant(left, left_constant);
555 intptr_t right_constant;
556 bool is_right_constant = ToIntPtrConstant(right, right_constant);
557 if (is_left_constant) {
558 if (is_right_constant) {
559 return IntPtrConstant(left_constant - right_constant);
561 }
else if (is_right_constant) {
562 if (right_constant == 0) {
566 return UncheckedCast<IntPtrT>(raw_assembler()->IntPtrSub(left, right));
569 TNode<WordT> CodeAssembler::IntPtrMul(SloppyTNode<WordT> left,
570 SloppyTNode<WordT> right) {
571 intptr_t left_constant;
572 bool is_left_constant = ToIntPtrConstant(left, left_constant);
573 intptr_t right_constant;
574 bool is_right_constant = ToIntPtrConstant(right, right_constant);
575 if (is_left_constant) {
576 if (is_right_constant) {
577 return IntPtrConstant(left_constant * right_constant);
579 if (base::bits::IsPowerOfTwo(left_constant)) {
580 return WordShl(right, WhichPowerOf2(left_constant));
582 }
else if (is_right_constant) {
583 if (base::bits::IsPowerOfTwo(right_constant)) {
584 return WordShl(left, WhichPowerOf2(right_constant));
587 return UncheckedCast<IntPtrT>(raw_assembler()->IntPtrMul(left, right));
590 TNode<WordT> CodeAssembler::WordShl(SloppyTNode<WordT> value,
int shift) {
591 return (shift != 0) ? WordShl(value, IntPtrConstant(shift)) : value;
594 TNode<WordT> CodeAssembler::WordShr(SloppyTNode<WordT> value,
int shift) {
595 return (shift != 0) ? WordShr(value, IntPtrConstant(shift)) : value;
598 TNode<WordT> CodeAssembler::WordSar(SloppyTNode<WordT> value,
int shift) {
599 return (shift != 0) ? WordSar(value, IntPtrConstant(shift)) : value;
602 TNode<Word32T> CodeAssembler::Word32Shr(SloppyTNode<Word32T> value,
int shift) {
603 return (shift != 0) ? Word32Shr(value, Int32Constant(shift)) : value;
606 TNode<WordT> CodeAssembler::WordOr(SloppyTNode<WordT> left,
607 SloppyTNode<WordT> right) {
608 intptr_t left_constant;
609 bool is_left_constant = ToIntPtrConstant(left, left_constant);
610 intptr_t right_constant;
611 bool is_right_constant = ToIntPtrConstant(right, right_constant);
612 if (is_left_constant) {
613 if (is_right_constant) {
614 return IntPtrConstant(left_constant | right_constant);
616 if (left_constant == 0) {
619 }
else if (is_right_constant) {
620 if (right_constant == 0) {
624 return UncheckedCast<WordT>(raw_assembler()->WordOr(left, right));
627 TNode<WordT> CodeAssembler::WordAnd(SloppyTNode<WordT> left,
628 SloppyTNode<WordT> right) {
629 intptr_t left_constant;
630 bool is_left_constant = ToIntPtrConstant(left, left_constant);
631 intptr_t right_constant;
632 bool is_right_constant = ToIntPtrConstant(right, right_constant);
633 if (is_left_constant) {
634 if (is_right_constant) {
635 return IntPtrConstant(left_constant & right_constant);
638 return UncheckedCast<WordT>(raw_assembler()->WordAnd(left, right));
641 TNode<WordT> CodeAssembler::WordXor(SloppyTNode<WordT> left,
642 SloppyTNode<WordT> right) {
643 intptr_t left_constant;
644 bool is_left_constant = ToIntPtrConstant(left, left_constant);
645 intptr_t right_constant;
646 bool is_right_constant = ToIntPtrConstant(right, right_constant);
647 if (is_left_constant) {
648 if (is_right_constant) {
649 return IntPtrConstant(left_constant ^ right_constant);
652 return UncheckedCast<WordT>(raw_assembler()->WordXor(left, right));
655 TNode<WordT> CodeAssembler::WordShl(SloppyTNode<WordT> left,
656 SloppyTNode<IntegralT> right) {
657 intptr_t left_constant;
658 bool is_left_constant = ToIntPtrConstant(left, left_constant);
659 intptr_t right_constant;
660 bool is_right_constant = ToIntPtrConstant(right, right_constant);
661 if (is_left_constant) {
662 if (is_right_constant) {
663 return IntPtrConstant(left_constant << right_constant);
665 }
else if (is_right_constant) {
666 if (right_constant == 0) {
670 return UncheckedCast<WordT>(raw_assembler()->WordShl(left, right));
673 TNode<WordT> CodeAssembler::WordShr(SloppyTNode<WordT> left,
674 SloppyTNode<IntegralT> right) {
675 intptr_t left_constant;
676 bool is_left_constant = ToIntPtrConstant(left, left_constant);
677 intptr_t right_constant;
678 bool is_right_constant = ToIntPtrConstant(right, right_constant);
679 if (is_left_constant) {
680 if (is_right_constant) {
681 return IntPtrConstant(static_cast<uintptr_t>(left_constant) >>
684 }
else if (is_right_constant) {
685 if (right_constant == 0) {
689 return UncheckedCast<WordT>(raw_assembler()->WordShr(left, right));
692 TNode<WordT> CodeAssembler::WordSar(SloppyTNode<WordT> left,
693 SloppyTNode<IntegralT> right) {
694 intptr_t left_constant;
695 bool is_left_constant = ToIntPtrConstant(left, left_constant);
696 intptr_t right_constant;
697 bool is_right_constant = ToIntPtrConstant(right, right_constant);
698 if (is_left_constant) {
699 if (is_right_constant) {
700 return IntPtrConstant(left_constant >> right_constant);
702 }
else if (is_right_constant) {
703 if (right_constant == 0) {
707 return UncheckedCast<WordT>(raw_assembler()->WordSar(left, right));
710 TNode<Word32T> CodeAssembler::Word32Or(SloppyTNode<Word32T> left,
711 SloppyTNode<Word32T> right) {
712 int32_t left_constant;
713 bool is_left_constant = ToInt32Constant(left, left_constant);
714 int32_t right_constant;
715 bool is_right_constant = ToInt32Constant(right, right_constant);
716 if (is_left_constant) {
717 if (is_right_constant) {
718 return Int32Constant(left_constant | right_constant);
720 if (left_constant == 0) {
723 }
else if (is_right_constant) {
724 if (right_constant == 0) {
728 return UncheckedCast<Word32T>(raw_assembler()->Word32Or(left, right));
731 TNode<Word32T> CodeAssembler::Word32And(SloppyTNode<Word32T> left,
732 SloppyTNode<Word32T> right) {
733 int32_t left_constant;
734 bool is_left_constant = ToInt32Constant(left, left_constant);
735 int32_t right_constant;
736 bool is_right_constant = ToInt32Constant(right, right_constant);
737 if (is_left_constant) {
738 if (is_right_constant) {
739 return Int32Constant(left_constant & right_constant);
742 return UncheckedCast<Word32T>(raw_assembler()->Word32And(left, right));
745 TNode<Word32T> CodeAssembler::Word32Xor(SloppyTNode<Word32T> left,
746 SloppyTNode<Word32T> right) {
747 int32_t left_constant;
748 bool is_left_constant = ToInt32Constant(left, left_constant);
749 int32_t right_constant;
750 bool is_right_constant = ToInt32Constant(right, right_constant);
751 if (is_left_constant) {
752 if (is_right_constant) {
753 return Int32Constant(left_constant ^ right_constant);
756 return UncheckedCast<Word32T>(raw_assembler()->Word32Xor(left, right));
759 TNode<Word32T> CodeAssembler::Word32Shl(SloppyTNode<Word32T> left,
760 SloppyTNode<Word32T> right) {
761 int32_t left_constant;
762 bool is_left_constant = ToInt32Constant(left, left_constant);
763 int32_t right_constant;
764 bool is_right_constant = ToInt32Constant(right, right_constant);
765 if (is_left_constant) {
766 if (is_right_constant) {
767 return Int32Constant(left_constant << right_constant);
769 }
else if (is_right_constant) {
770 if (right_constant == 0) {
774 return UncheckedCast<Word32T>(raw_assembler()->Word32Shl(left, right));
777 TNode<Word32T> CodeAssembler::Word32Shr(SloppyTNode<Word32T> left,
778 SloppyTNode<Word32T> right) {
779 int32_t left_constant;
780 bool is_left_constant = ToInt32Constant(left, left_constant);
781 int32_t right_constant;
782 bool is_right_constant = ToInt32Constant(right, right_constant);
783 if (is_left_constant) {
784 if (is_right_constant) {
785 return Int32Constant(static_cast<uint32_t>(left_constant) >>
788 }
else if (is_right_constant) {
789 if (right_constant == 0) {
793 return UncheckedCast<Word32T>(raw_assembler()->Word32Shr(left, right));
796 TNode<Word32T> CodeAssembler::Word32Sar(SloppyTNode<Word32T> left,
797 SloppyTNode<Word32T> right) {
798 int32_t left_constant;
799 bool is_left_constant = ToInt32Constant(left, left_constant);
800 int32_t right_constant;
801 bool is_right_constant = ToInt32Constant(right, right_constant);
802 if (is_left_constant) {
803 if (is_right_constant) {
804 return Int32Constant(left_constant >> right_constant);
806 }
else if (is_right_constant) {
807 if (right_constant == 0) {
811 return UncheckedCast<Word32T>(raw_assembler()->Word32Sar(left, right));
814 TNode<Word64T> CodeAssembler::Word64Or(SloppyTNode<Word64T> left,
815 SloppyTNode<Word64T> right) {
817 bool is_left_constant = ToInt64Constant(left, left_constant);
819 bool is_right_constant = ToInt64Constant(right, right_constant);
820 if (is_left_constant) {
821 if (is_right_constant) {
822 return Int64Constant(left_constant | right_constant);
824 if (left_constant == 0) {
827 }
else if (is_right_constant) {
828 if (right_constant == 0) {
832 return UncheckedCast<Word64T>(raw_assembler()->Word64Or(left, right));
835 TNode<Word64T> CodeAssembler::Word64And(SloppyTNode<Word64T> left,
836 SloppyTNode<Word64T> right) {
838 bool is_left_constant = ToInt64Constant(left, left_constant);
840 bool is_right_constant = ToInt64Constant(right, right_constant);
841 if (is_left_constant) {
842 if (is_right_constant) {
843 return Int64Constant(left_constant & right_constant);
846 return UncheckedCast<Word64T>(raw_assembler()->Word64And(left, right));
849 TNode<Word64T> CodeAssembler::Word64Xor(SloppyTNode<Word64T> left,
850 SloppyTNode<Word64T> right) {
852 bool is_left_constant = ToInt64Constant(left, left_constant);
854 bool is_right_constant = ToInt64Constant(right, right_constant);
855 if (is_left_constant) {
856 if (is_right_constant) {
857 return Int64Constant(left_constant ^ right_constant);
860 return UncheckedCast<Word64T>(raw_assembler()->Word64Xor(left, right));
863 TNode<Word64T> CodeAssembler::Word64Shl(SloppyTNode<Word64T> left,
864 SloppyTNode<Word64T> right) {
866 bool is_left_constant = ToInt64Constant(left, left_constant);
868 bool is_right_constant = ToInt64Constant(right, right_constant);
869 if (is_left_constant) {
870 if (is_right_constant) {
871 return Int64Constant(left_constant << right_constant);
873 }
else if (is_right_constant) {
874 if (right_constant == 0) {
878 return UncheckedCast<Word64T>(raw_assembler()->Word64Shl(left, right));
881 TNode<Word64T> CodeAssembler::Word64Shr(SloppyTNode<Word64T> left,
882 SloppyTNode<Word64T> right) {
884 bool is_left_constant = ToInt64Constant(left, left_constant);
886 bool is_right_constant = ToInt64Constant(right, right_constant);
887 if (is_left_constant) {
888 if (is_right_constant) {
889 return Int64Constant(static_cast<uint64_t>(left_constant) >>
892 }
else if (is_right_constant) {
893 if (right_constant == 0) {
897 return UncheckedCast<Word64T>(raw_assembler()->Word64Shr(left, right));
900 TNode<Word64T> CodeAssembler::Word64Sar(SloppyTNode<Word64T> left,
901 SloppyTNode<Word64T> right) {
903 bool is_left_constant = ToInt64Constant(left, left_constant);
905 bool is_right_constant = ToInt64Constant(right, right_constant);
906 if (is_left_constant) {
907 if (is_right_constant) {
908 return Int64Constant(left_constant >> right_constant);
910 }
else if (is_right_constant) {
911 if (right_constant == 0) {
915 return UncheckedCast<Word64T>(raw_assembler()->Word64Sar(left, right));
918 #define CODE_ASSEMBLER_COMPARE(Name, ArgT, VarT, ToConstant, op) \ 919 TNode<BoolT> CodeAssembler::Name(SloppyTNode<ArgT> left, \ 920 SloppyTNode<ArgT> right) { \ 922 if (ToConstant(left, lhs) && ToConstant(right, rhs)) { \ 923 return BoolConstant(lhs op rhs); \ 925 return UncheckedCast<BoolT>(raw_assembler()->Name(left, right)); \ 928 CODE_ASSEMBLER_COMPARE(IntPtrEqual, WordT, intptr_t, ToIntPtrConstant, ==)
929 CODE_ASSEMBLER_COMPARE(WordEqual, WordT, intptr_t, ToIntPtrConstant, ==)
930 CODE_ASSEMBLER_COMPARE(WordNotEqual, WordT, intptr_t, ToIntPtrConstant, !=)
931 CODE_ASSEMBLER_COMPARE(Word32Equal, Word32T, int32_t, ToInt32Constant, ==)
932 CODE_ASSEMBLER_COMPARE(Word32NotEqual, Word32T, int32_t, ToInt32Constant, !=)
933 CODE_ASSEMBLER_COMPARE(Word64Equal, Word64T,
int64_t, ToInt64Constant, ==)
934 CODE_ASSEMBLER_COMPARE(Word64NotEqual, Word64T,
int64_t, ToInt64Constant, !=)
935 #undef CODE_ASSEMBLER_COMPARE 937 TNode<UintPtrT> CodeAssembler::ChangeUint32ToWord(SloppyTNode<Word32T> value) {
938 if (raw_assembler()->machine()->Is64()) {
939 return UncheckedCast<UintPtrT>(
940 raw_assembler()->ChangeUint32ToUint64(value));
942 return ReinterpretCast<UintPtrT>(value);
945 TNode<IntPtrT> CodeAssembler::ChangeInt32ToIntPtr(SloppyTNode<Word32T> value) {
946 if (raw_assembler()->machine()->Is64()) {
947 return ReinterpretCast<IntPtrT>(raw_assembler()->ChangeInt32ToInt64(value));
949 return ReinterpretCast<IntPtrT>(value);
952 TNode<UintPtrT> CodeAssembler::ChangeFloat64ToUintPtr(
953 SloppyTNode<Float64T> value) {
954 if (raw_assembler()->machine()->Is64()) {
955 return ReinterpretCast<UintPtrT>(
956 raw_assembler()->ChangeFloat64ToUint64(value));
958 return ReinterpretCast<UintPtrT>(
959 raw_assembler()->ChangeFloat64ToUint32(value));
962 TNode<Float64T> CodeAssembler::ChangeUintPtrToFloat64(TNode<UintPtrT> value) {
963 if (raw_assembler()->machine()->Is64()) {
966 return ReinterpretCast<Float64T>(
967 raw_assembler()->RoundUint64ToFloat64(value));
969 return ReinterpretCast<Float64T>(
970 raw_assembler()->ChangeUint32ToFloat64(value));
973 Node* CodeAssembler::RoundIntPtrToFloat64(Node* value) {
974 if (raw_assembler()->machine()->Is64()) {
975 return raw_assembler()->RoundInt64ToFloat64(value);
977 return raw_assembler()->ChangeInt32ToFloat64(value);
980 #define DEFINE_CODE_ASSEMBLER_UNARY_OP(name, ResType, ArgType) \ 981 TNode<ResType> CodeAssembler::name(SloppyTNode<ArgType> a) { \ 982 return UncheckedCast<ResType>(raw_assembler()->name(a)); \ 984 CODE_ASSEMBLER_UNARY_OP_LIST(DEFINE_CODE_ASSEMBLER_UNARY_OP)
985 #undef DEFINE_CODE_ASSEMBLER_UNARY_OP 987 Node* CodeAssembler::Load(MachineType rep, Node* base,
988 LoadSensitivity needs_poisoning) {
989 return raw_assembler()->Load(rep, base, needs_poisoning);
992 Node* CodeAssembler::Load(MachineType rep, Node* base, Node* offset,
993 LoadSensitivity needs_poisoning) {
994 return raw_assembler()->Load(rep, base, offset, needs_poisoning);
997 Node* CodeAssembler::AtomicLoad(MachineType rep, Node* base, Node* offset) {
998 return raw_assembler()->AtomicLoad(rep, base, offset);
1001 TNode<Object> CodeAssembler::LoadRoot(RootIndex root_index) {
1002 if (RootsTable::IsImmortalImmovable(root_index)) {
1003 Handle<Object> root = isolate()->root_handle(root_index);
1004 if (root->IsSmi()) {
1005 return SmiConstant(Smi::cast(*root));
1007 return HeapConstant(Handle<HeapObject>::cast(root));
1014 Node* isolate_root =
1015 ExternalConstant(ExternalReference::isolate_root(isolate()));
1016 int offset = IsolateData::root_slot_offset(root_index);
1017 return UncheckedCast<Object>(
1018 Load(MachineType::AnyTagged(), isolate_root, IntPtrConstant(offset)));
1021 Node* CodeAssembler::Store(Node* base, Node* value) {
1022 return raw_assembler()->Store(MachineRepresentation::kTagged, base, value,
1026 Node* CodeAssembler::Store(Node* base, Node* offset, Node* value) {
1027 return raw_assembler()->Store(MachineRepresentation::kTagged, base, offset,
1028 value, kFullWriteBarrier);
1031 Node* CodeAssembler::StoreWithMapWriteBarrier(Node* base, Node* offset,
1033 return raw_assembler()->Store(MachineRepresentation::kTagged, base, offset,
1034 value, kMapWriteBarrier);
1037 Node* CodeAssembler::StoreNoWriteBarrier(MachineRepresentation rep, Node* base,
1039 return raw_assembler()->Store(rep, base, value, kNoWriteBarrier);
1042 Node* CodeAssembler::StoreNoWriteBarrier(MachineRepresentation rep, Node* base,
1043 Node* offset, Node* value) {
1044 return raw_assembler()->Store(rep, base, offset, value, kNoWriteBarrier);
1047 Node* CodeAssembler::AtomicStore(MachineRepresentation rep, Node* base,
1048 Node* offset, Node* value, Node* value_high) {
1049 return raw_assembler()->AtomicStore(rep, base, offset, value, value_high);
1052 #define ATOMIC_FUNCTION(name) \ 1053 Node* CodeAssembler::Atomic##name(MachineType type, Node* base, \ 1054 Node* offset, Node* value, \ 1055 Node* value_high) { \ 1056 return raw_assembler()->Atomic##name(type, base, offset, value, \ 1059 ATOMIC_FUNCTION(Exchange);
1060 ATOMIC_FUNCTION(Add);
1061 ATOMIC_FUNCTION(Sub);
1062 ATOMIC_FUNCTION(And);
1063 ATOMIC_FUNCTION(Or);
1064 ATOMIC_FUNCTION(Xor);
1065 #undef ATOMIC_FUNCTION 1067 Node* CodeAssembler::AtomicCompareExchange(MachineType type, Node* base,
1068 Node* offset, Node* old_value,
1070 Node* old_value_high,
1071 Node* new_value_high) {
1072 return raw_assembler()->AtomicCompareExchange(
1073 type, base, offset, old_value, old_value_high, new_value, new_value_high);
1076 Node* CodeAssembler::StoreRoot(RootIndex root_index, Node* value) {
1077 DCHECK(!RootsTable::IsImmortalImmovable(root_index));
1078 Node* isolate_root =
1079 ExternalConstant(ExternalReference::isolate_root(isolate()));
1080 int offset = IsolateData::root_slot_offset(root_index);
1081 return StoreNoWriteBarrier(MachineRepresentation::kTagged, isolate_root,
1082 IntPtrConstant(offset), value);
1085 Node* CodeAssembler::Retain(Node* value) {
1086 return raw_assembler()->Retain(value);
1089 Node* CodeAssembler::Projection(
int index, Node* value) {
1090 DCHECK(index < value->op()->ValueOutputCount());
1091 return raw_assembler()->Projection(index, value);
1094 void CodeAssembler::GotoIfException(Node* node, Label* if_exception,
1095 Variable* exception_var) {
1096 if (if_exception ==
nullptr) {
1102 DCHECK_EQ(state()->exception_handler_labels_.size(), 0);
1103 DCHECK(!node->op()->HasProperty(Operator::kNoThrow));
1105 Label success(
this), exception(
this, Label::kDeferred);
1106 success.MergeVariables();
1107 exception.MergeVariables();
1109 raw_assembler()->Continuations(node, success.label_, exception.label_);
1112 const Operator* op = raw_assembler()->common()->IfException();
1113 Node* exception_value = raw_assembler()->AddNode(op, node, node);
1114 if (exception_var !=
nullptr) {
1115 exception_var->Bind(exception_value);
1120 raw_assembler()->AddNode(raw_assembler()->common()->IfSuccess(), node);
1123 void CodeAssembler::HandleException(Node* node) {
1124 if (state_->exception_handler_labels_.size() == 0)
return;
1125 CodeAssemblerExceptionHandlerLabel* label =
1126 state_->exception_handler_labels_.back();
1128 if (node->op()->HasProperty(Operator::kNoThrow)) {
1132 Label success(
this), exception(
this, Label::kDeferred);
1133 success.MergeVariables();
1134 exception.MergeVariables();
1136 raw_assembler()->Continuations(node, success.label_, exception.label_);
1139 const Operator* op = raw_assembler()->common()->IfException();
1140 Node* exception_value = raw_assembler()->AddNode(op, node, node);
1141 label->AddInputs({UncheckedCast<Object>(exception_value)});
1142 Goto(label->plain_label());
1145 raw_assembler()->AddNode(raw_assembler()->common()->IfSuccess(), node);
1149 template <
size_t kMaxSize>
1152 void Add(Node* node) {
1153 DCHECK_GT(kMaxSize, size());
1157 Node*
const* data()
const {
return arr_; }
1158 int size()
const {
return static_cast<int>(ptr_ - arr_); }
1161 Node* arr_[kMaxSize];
1166 TNode<Object> CodeAssembler::CallRuntimeImpl(
1167 Runtime::FunctionId
function, TNode<Object> context,
1168 std::initializer_list<TNode<Object>> args) {
1169 int result_size = Runtime::FunctionForId(
function)->result_size;
1170 TNode<Code> centry =
1171 HeapConstant(CodeFactory::RuntimeCEntry(isolate(), result_size));
1172 return CallRuntimeWithCEntryImpl(
function, centry, context, args);
1175 TNode<Object> CodeAssembler::CallRuntimeWithCEntryImpl(
1176 Runtime::FunctionId
function, TNode<Code> centry, TNode<Object> context,
1177 std::initializer_list<TNode<Object>> args) {
1178 constexpr
size_t kMaxNumArgs = 6;
1179 DCHECK_GE(kMaxNumArgs, args.size());
1180 int argc =
static_cast<int>(args.size());
1181 auto call_descriptor = Linkage::GetRuntimeCallDescriptor(
1182 zone(),
function, argc, Operator::kNoProperties,
1183 CallDescriptor::kNoFlags);
1185 Node* ref = ExternalConstant(ExternalReference::Create(
function));
1186 Node* arity = Int32Constant(argc);
1188 NodeArray<kMaxNumArgs + 4> inputs;
1190 for (
auto arg : args) inputs.Add(arg);
1193 inputs.Add(context);
1196 Node* return_value =
1197 raw_assembler()->CallN(call_descriptor, inputs.size(), inputs.data());
1198 HandleException(return_value);
1200 return UncheckedCast<Object>(return_value);
1203 void CodeAssembler::TailCallRuntimeImpl(
1204 Runtime::FunctionId
function, TNode<Int32T> arity, TNode<Object> context,
1205 std::initializer_list<TNode<Object>> args) {
1206 int result_size = Runtime::FunctionForId(
function)->result_size;
1207 TNode<Code> centry =
1208 HeapConstant(CodeFactory::RuntimeCEntry(isolate(), result_size));
1209 return TailCallRuntimeWithCEntryImpl(
function, arity, centry, context, args);
1212 void CodeAssembler::TailCallRuntimeWithCEntryImpl(
1213 Runtime::FunctionId
function, TNode<Int32T> arity, TNode<Code> centry,
1214 TNode<Object> context, std::initializer_list<TNode<Object>> args) {
1215 constexpr
size_t kMaxNumArgs = 6;
1216 DCHECK_GE(kMaxNumArgs, args.size());
1217 int argc =
static_cast<int>(args.size());
1218 auto call_descriptor = Linkage::GetRuntimeCallDescriptor(
1219 zone(),
function, argc, Operator::kNoProperties,
1220 CallDescriptor::kNoFlags);
1222 Node* ref = ExternalConstant(ExternalReference::Create(
function));
1224 NodeArray<kMaxNumArgs + 4> inputs;
1226 for (
auto arg : args) inputs.Add(arg);
1229 inputs.Add(context);
1231 raw_assembler()->TailCallN(call_descriptor, inputs.size(), inputs.data());
1234 Node* CodeAssembler::CallStubN(
const CallInterfaceDescriptor& descriptor,
1235 size_t result_size,
int input_count,
1236 Node*
const* inputs) {
1238 int implicit_nodes = descriptor.HasContextParameter() ? 2 : 1;
1239 DCHECK_LE(implicit_nodes, input_count);
1240 int argc = input_count - implicit_nodes;
1241 DCHECK_LE(descriptor.GetParameterCount(), argc);
1243 int stack_parameter_count = argc - descriptor.GetRegisterParameterCount();
1244 DCHECK_LE(descriptor.GetStackParameterCount(), stack_parameter_count);
1245 DCHECK_EQ(result_size, descriptor.GetReturnCount());
1247 auto call_descriptor = Linkage::GetStubCallDescriptor(
1248 zone(), descriptor, stack_parameter_count, CallDescriptor::kNoFlags,
1249 Operator::kNoProperties);
1252 Node* return_value =
1253 raw_assembler()->CallN(call_descriptor, input_count, inputs);
1254 HandleException(return_value);
1256 return return_value;
1259 void CodeAssembler::TailCallStubImpl(
const CallInterfaceDescriptor& descriptor,
1260 TNode<Code> target, TNode<Object> context,
1261 std::initializer_list<Node*> args) {
1262 constexpr
size_t kMaxNumArgs = 11;
1263 DCHECK_GE(kMaxNumArgs, args.size());
1264 DCHECK_EQ(descriptor.GetParameterCount(), args.size());
1265 auto call_descriptor = Linkage::GetStubCallDescriptor(
1266 zone(), descriptor, descriptor.GetStackParameterCount(),
1267 CallDescriptor::kNoFlags, Operator::kNoProperties);
1269 NodeArray<kMaxNumArgs + 2> inputs;
1271 for (
auto arg : args) inputs.Add(arg);
1272 if (descriptor.HasContextParameter()) {
1273 inputs.Add(context);
1276 raw_assembler()->TailCallN(call_descriptor, inputs.size(), inputs.data());
1279 Node* CodeAssembler::CallStubRImpl(
const CallInterfaceDescriptor& descriptor,
1280 size_t result_size, SloppyTNode<Code> target,
1281 SloppyTNode<Object> context,
1282 std::initializer_list<Node*> args) {
1283 constexpr
size_t kMaxNumArgs = 10;
1284 DCHECK_GE(kMaxNumArgs, args.size());
1286 NodeArray<kMaxNumArgs + 2> inputs;
1288 for (
auto arg : args) inputs.Add(arg);
1289 if (descriptor.HasContextParameter()) {
1290 inputs.Add(context);
1293 return CallStubN(descriptor, result_size, inputs.size(), inputs.data());
1296 Node* CodeAssembler::TailCallStubThenBytecodeDispatchImpl(
1297 const CallInterfaceDescriptor& descriptor, Node* target, Node* context,
1298 std::initializer_list<Node*> args) {
1299 constexpr
size_t kMaxNumArgs = 6;
1300 DCHECK_GE(kMaxNumArgs, args.size());
1302 DCHECK_LE(descriptor.GetParameterCount(), args.size());
1303 int argc =
static_cast<int>(args.size());
1305 int stack_parameter_count = argc - descriptor.GetRegisterParameterCount();
1306 DCHECK_LE(descriptor.GetStackParameterCount(), stack_parameter_count);
1307 auto call_descriptor = Linkage::GetStubCallDescriptor(
1308 zone(), descriptor, stack_parameter_count, CallDescriptor::kNoFlags,
1309 Operator::kNoProperties);
1311 NodeArray<kMaxNumArgs + 2> inputs;
1313 for (
auto arg : args) inputs.Add(arg);
1314 inputs.Add(context);
1316 return raw_assembler()->TailCallN(call_descriptor, inputs.size(),
1320 template <
class... TArgs>
1321 Node* CodeAssembler::TailCallBytecodeDispatch(
1322 const CallInterfaceDescriptor& descriptor, Node* target, TArgs... args) {
1323 DCHECK_EQ(descriptor.GetParameterCount(),
sizeof...(args));
1324 auto call_descriptor = Linkage::GetBytecodeDispatchCallDescriptor(
1325 zone(), descriptor, descriptor.GetStackParameterCount());
1327 Node* nodes[] = {target, args...};
1328 CHECK_EQ(descriptor.GetParameterCount() + 1, arraysize(nodes));
1329 return raw_assembler()->TailCallN(call_descriptor, arraysize(nodes), nodes);
1334 template V8_EXPORT_PRIVATE Node* CodeAssembler::TailCallBytecodeDispatch(
1335 const CallInterfaceDescriptor& descriptor, Node* target, Node*, Node*,
1338 TNode<Object> CodeAssembler::TailCallJSCode(TNode<Code> code,
1339 TNode<Context> context,
1340 TNode<JSFunction>
function,
1341 TNode<Object> new_target,
1342 TNode<Int32T> arg_count) {
1343 JSTrampolineDescriptor descriptor;
1344 auto call_descriptor = Linkage::GetStubCallDescriptor(
1345 zone(), descriptor, descriptor.GetStackParameterCount(),
1346 CallDescriptor::kFixedTargetRegister, Operator::kNoProperties);
1348 Node* nodes[] = {code,
function, new_target, arg_count, context};
1349 CHECK_EQ(descriptor.GetParameterCount() + 2, arraysize(nodes));
1350 return UncheckedCast<Object>(
1351 raw_assembler()->TailCallN(call_descriptor, arraysize(nodes), nodes));
1354 Node* CodeAssembler::CallCFunctionN(Signature<MachineType>* signature,
1355 int input_count, Node*
const* inputs) {
1356 auto call_descriptor = Linkage::GetSimplifiedCDescriptor(zone(), signature);
1357 return raw_assembler()->CallN(call_descriptor, input_count, inputs);
1360 Node* CodeAssembler::CallCFunction1(MachineType return_type,
1361 MachineType arg0_type, Node*
function,
1363 return raw_assembler()->CallCFunction1(return_type, arg0_type,
function,
1367 Node* CodeAssembler::CallCFunction1WithCallerSavedRegisters(
1368 MachineType return_type, MachineType arg0_type, Node*
function, Node* arg0,
1369 SaveFPRegsMode mode) {
1370 DCHECK(return_type.LessThanOrEqualPointerSize());
1371 return raw_assembler()->CallCFunction1WithCallerSavedRegisters(
1372 return_type, arg0_type,
function, arg0, mode);
1375 Node* CodeAssembler::CallCFunction2(MachineType return_type,
1376 MachineType arg0_type,
1377 MachineType arg1_type, Node*
function,
1378 Node* arg0, Node* arg1) {
1379 return raw_assembler()->CallCFunction2(return_type, arg0_type, arg1_type,
1380 function, arg0, arg1);
1383 Node* CodeAssembler::CallCFunction3(MachineType return_type,
1384 MachineType arg0_type,
1385 MachineType arg1_type,
1386 MachineType arg2_type, Node*
function,
1387 Node* arg0, Node* arg1, Node* arg2) {
1388 return raw_assembler()->CallCFunction3(return_type, arg0_type, arg1_type,
1389 arg2_type,
function, arg0, arg1, arg2);
1392 Node* CodeAssembler::CallCFunction3WithCallerSavedRegisters(
1393 MachineType return_type, MachineType arg0_type, MachineType arg1_type,
1394 MachineType arg2_type, Node*
function, Node* arg0, Node* arg1, Node* arg2,
1395 SaveFPRegsMode mode) {
1396 DCHECK(return_type.LessThanOrEqualPointerSize());
1397 return raw_assembler()->CallCFunction3WithCallerSavedRegisters(
1398 return_type, arg0_type, arg1_type, arg2_type,
function, arg0, arg1, arg2,
1402 Node* CodeAssembler::CallCFunction4(
1403 MachineType return_type, MachineType arg0_type, MachineType arg1_type,
1404 MachineType arg2_type, MachineType arg3_type, Node*
function, Node* arg0,
1405 Node* arg1, Node* arg2, Node* arg3) {
1406 return raw_assembler()->CallCFunction4(return_type, arg0_type, arg1_type,
1407 arg2_type, arg3_type,
function, arg0,
1411 Node* CodeAssembler::CallCFunction5(
1412 MachineType return_type, MachineType arg0_type, MachineType arg1_type,
1413 MachineType arg2_type, MachineType arg3_type, MachineType arg4_type,
1414 Node*
function, Node* arg0, Node* arg1, Node* arg2, Node* arg3,
1416 return raw_assembler()->CallCFunction5(
1417 return_type, arg0_type, arg1_type, arg2_type, arg3_type, arg4_type,
1418 function, arg0, arg1, arg2, arg3, arg4);
1421 Node* CodeAssembler::CallCFunction6(
1422 MachineType return_type, MachineType arg0_type, MachineType arg1_type,
1423 MachineType arg2_type, MachineType arg3_type, MachineType arg4_type,
1424 MachineType arg5_type, Node*
function, Node* arg0, Node* arg1, Node* arg2,
1425 Node* arg3, Node* arg4, Node* arg5) {
1426 return raw_assembler()->CallCFunction6(
1427 return_type, arg0_type, arg1_type, arg2_type, arg3_type, arg4_type,
1428 arg5_type,
function, arg0, arg1, arg2, arg3, arg4, arg5);
1431 Node* CodeAssembler::CallCFunction9(
1432 MachineType return_type, MachineType arg0_type, MachineType arg1_type,
1433 MachineType arg2_type, MachineType arg3_type, MachineType arg4_type,
1434 MachineType arg5_type, MachineType arg6_type, MachineType arg7_type,
1435 MachineType arg8_type, Node*
function, Node* arg0, Node* arg1, Node* arg2,
1436 Node* arg3, Node* arg4, Node* arg5, Node* arg6, Node* arg7, Node* arg8) {
1437 return raw_assembler()->CallCFunction9(
1438 return_type, arg0_type, arg1_type, arg2_type, arg3_type, arg4_type,
1439 arg5_type, arg6_type, arg7_type, arg8_type,
function, arg0, arg1, arg2,
1440 arg3, arg4, arg5, arg6, arg7, arg8);
1443 void CodeAssembler::Goto(Label* label) {
1444 label->MergeVariables();
1445 raw_assembler()->Goto(label->label_);
1448 void CodeAssembler::GotoIf(SloppyTNode<IntegralT> condition,
1449 Label* true_label) {
1450 Label false_label(
this);
1451 Branch(condition, true_label, &false_label);
1455 void CodeAssembler::GotoIfNot(SloppyTNode<IntegralT> condition,
1456 Label* false_label) {
1457 Label true_label(
this);
1458 Branch(condition, &true_label, false_label);
1462 void CodeAssembler::Branch(SloppyTNode<IntegralT> condition, Label* true_label,
1463 Label* false_label) {
1465 if (ToInt32Constant(condition, constant)) {
1466 if ((true_label->is_used() || true_label->is_bound()) &&
1467 (false_label->is_used() || false_label->is_bound())) {
1468 return Goto(constant ? true_label : false_label);
1471 true_label->MergeVariables();
1472 false_label->MergeVariables();
1473 return raw_assembler()->Branch(condition, true_label->label_,
1474 false_label->label_);
1477 void CodeAssembler::Branch(TNode<BoolT> condition,
1478 const std::function<
void()>& true_body,
1479 const std::function<
void()>& false_body) {
1481 if (ToInt32Constant(condition, constant)) {
1482 return constant ? true_body() : false_body();
1485 Label vtrue(
this), vfalse(
this);
1486 Branch(condition, &vtrue, &vfalse);
1495 void CodeAssembler::Branch(TNode<BoolT> condition, Label* true_label,
1496 const std::function<
void()>& false_body) {
1498 if (ToInt32Constant(condition, constant)) {
1499 return constant ? Goto(true_label) : false_body();
1503 Branch(condition, true_label, &vfalse);
1508 void CodeAssembler::Branch(TNode<BoolT> condition,
1509 const std::function<
void()>& true_body,
1510 Label* false_label) {
1512 if (ToInt32Constant(condition, constant)) {
1513 return constant ? true_body() : Goto(false_label);
1517 Branch(condition, &vtrue, false_label);
1522 void CodeAssembler::Switch(Node* index, Label* default_label,
1523 const int32_t* case_values, Label** case_labels,
1524 size_t case_count) {
1525 RawMachineLabel** labels =
1526 new (zone()->New(
sizeof(RawMachineLabel*) * case_count))
1527 RawMachineLabel*[case_count];
1528 for (
size_t i = 0;
i < case_count; ++
i) {
1529 labels[
i] = case_labels[
i]->label_;
1530 case_labels[
i]->MergeVariables();
1532 default_label->MergeVariables();
1533 return raw_assembler()->Switch(index, default_label->label_, case_values,
1534 labels, case_count);
1537 bool CodeAssembler::UnalignedLoadSupported(MachineRepresentation rep)
const {
1538 return raw_assembler()->machine()->UnalignedLoadSupported(rep);
1540 bool CodeAssembler::UnalignedStoreSupported(MachineRepresentation rep)
const {
1541 return raw_assembler()->machine()->UnalignedStoreSupported(rep);
1545 Isolate* CodeAssembler::isolate()
const {
return raw_assembler()->isolate(); }
1547 Factory* CodeAssembler::factory()
const {
return isolate()->factory(); }
1549 Zone* CodeAssembler::zone()
const {
return raw_assembler()->zone(); }
1551 bool CodeAssembler::IsExceptionHandlerActive()
const {
1552 return state_->exception_handler_labels_.size() != 0;
1555 RawMachineAssembler* CodeAssembler::raw_assembler()
const {
1556 return state_->raw_assembler_.get();
1578 debug_info_ = debug_info;
1584 return var_id_ < other.var_id_;
1587 MachineRepresentation rep_;
1591 bool CodeAssemblerVariable::ImplComparator::operator()(
1597 CodeAssemblerVariable::CodeAssemblerVariable(
CodeAssembler* assembler,
1598 MachineRepresentation rep)
1599 : impl_(new (assembler->zone())
1600 Impl(rep, assembler->state()->NextVariableId())),
1601 state_(assembler->state()) {
1602 state_->variables_.insert(impl_);
1605 CodeAssemblerVariable::CodeAssemblerVariable(CodeAssembler* assembler,
1606 MachineRepresentation rep,
1607 Node* initial_value)
1608 : CodeAssemblerVariable(assembler, rep) {
1609 Bind(initial_value);
1613 CodeAssemblerVariable::CodeAssemblerVariable(CodeAssembler* assembler,
1614 AssemblerDebugInfo debug_info,
1615 MachineRepresentation rep)
1616 : impl_(new (assembler->zone())
1617 Impl(rep, assembler->state()->NextVariableId())),
1618 state_(assembler->state()) {
1619 impl_->set_debug_info(debug_info);
1620 state_->variables_.insert(impl_);
1623 CodeAssemblerVariable::CodeAssemblerVariable(CodeAssembler* assembler,
1624 AssemblerDebugInfo debug_info,
1625 MachineRepresentation rep,
1626 Node* initial_value)
1627 : CodeAssemblerVariable(assembler, debug_info, rep) {
1628 impl_->set_debug_info(debug_info);
1629 Bind(initial_value);
1633 CodeAssemblerVariable::~CodeAssemblerVariable() {
1634 state_->variables_.erase(impl_);
1637 void CodeAssemblerVariable::Bind(Node* value) { impl_->value_ = value; }
1639 Node* CodeAssemblerVariable::value()
const {
1642 std::stringstream str;
1643 str <<
"#Use of unbound variable:" 1644 <<
"#\n Variable: " << *
this <<
"#\n Current Block: ";
1645 state_->PrintCurrentBlock(str);
1646 FATAL(
"%s", str.str().c_str());
1648 if (!state_->InsideBlock()) {
1649 std::stringstream str;
1650 str <<
"#Accessing variable value outside a block:" 1651 <<
"#\n Variable: " << *
this;
1652 FATAL(
"%s", str.str().c_str());
1655 return impl_->value_;
1658 MachineRepresentation CodeAssemblerVariable::rep()
const {
return impl_->rep_; }
1660 bool CodeAssemblerVariable::IsBound()
const {
return impl_->value_ !=
nullptr; }
1662 std::ostream& operator<<(std::ostream& os,
1663 const CodeAssemblerVariable::Impl& impl) {
1665 AssemblerDebugInfo info = impl.debug_info();
1666 if (info.name) os <<
"V" << info;
1671 std::ostream& operator<<(std::ostream& os,
1672 const CodeAssemblerVariable& variable) {
1673 os << *variable.impl_;
1677 CodeAssemblerLabel::CodeAssemblerLabel(CodeAssembler* assembler,
1679 CodeAssemblerVariable*
const* vars,
1680 CodeAssemblerLabel::Type type)
1683 state_(assembler->state()),
1685 void* buffer = assembler->zone()->New(
sizeof(RawMachineLabel));
1686 label_ =
new (buffer)
1687 RawMachineLabel(type == kDeferred ? RawMachineLabel::kDeferred
1688 : RawMachineLabel::kNonDeferred);
1689 for (
size_t i = 0;
i < vars_count; ++
i) {
1690 variable_phis_[vars[
i]->impl_] =
nullptr;
1694 CodeAssemblerLabel::~CodeAssemblerLabel() { label_->~RawMachineLabel(); }
1696 void CodeAssemblerLabel::MergeVariables() {
1698 for (CodeAssemblerVariable::Impl* var : state_->variables_) {
1700 Node* node = var->value_;
1701 if (node !=
nullptr) {
1702 auto i = variable_merges_.find(var);
1703 if (
i != variable_merges_.end()) {
1704 i->second.push_back(node);
1705 count =
i->second.size();
1708 variable_merges_[var] = std::vector<Node*>(1, node);
1713 DCHECK(variable_phis_.find(var) == variable_phis_.end() ||
1714 count == merge_count_);
1720 auto phi = variable_phis_.find(var);
1721 if (phi != variable_phis_.end()) {
1722 DCHECK_NOT_NULL(phi->second);
1723 state_->raw_assembler_->AppendPhiInput(phi->second, node);
1725 auto i = variable_merges_.find(var);
1726 if (
i != variable_merges_.end()) {
1734 if (find_if(
i->second.begin(),
i->second.end(),
1735 [node](Node* e) ->
bool {
return node != e; }) !=
1737 std::stringstream str;
1738 str <<
"Unmerged variable found when jumping to block. \n" 1739 <<
"# Variable: " << *var;
1741 str <<
"\n# Target block: " << *label_->block();
1743 str <<
"\n# Current Block: ";
1744 state_->PrintCurrentBlock(str);
1745 FATAL(
"%s", str.str().c_str());
1755 void CodeAssemblerLabel::Bind(AssemblerDebugInfo debug_info) {
1757 std::stringstream str;
1758 str <<
"Cannot bind the same label twice:" 1759 <<
"\n# current: " << debug_info
1760 <<
"\n# previous: " << *label_->block();
1761 FATAL(
"%s", str.str().c_str());
1763 state_->raw_assembler_->Bind(label_, debug_info);
1764 UpdateVariablesAfterBind();
1768 void CodeAssemblerLabel::Bind() {
1770 state_->raw_assembler_->Bind(label_);
1771 UpdateVariablesAfterBind();
1774 void CodeAssemblerLabel::UpdateVariablesAfterBind() {
1777 for (
auto var : state_->variables_) {
1778 Node* shared_value =
nullptr;
1779 auto i = variable_merges_.find(var);
1780 if (
i != variable_merges_.end()) {
1781 for (
auto value :
i->second) {
1782 DCHECK_NOT_NULL(value);
1783 if (value != shared_value) {
1784 if (shared_value ==
nullptr) {
1785 shared_value = value;
1787 variable_phis_[var] =
nullptr;
1794 for (
auto var : variable_phis_) {
1795 CodeAssemblerVariable::Impl* var_impl = var.first;
1796 auto i = variable_merges_.find(var_impl);
1798 bool not_found =
i == variable_merges_.end();
1799 if (not_found ||
i->second.size() != merge_count_) {
1800 std::stringstream str;
1801 str <<
"A variable that has been marked as beeing merged at the label" 1802 <<
"\n# doesn't have a bound value along all of the paths that " 1803 <<
"\n# have been merged into the label up to this point." 1805 <<
"\n# This can happen in the following cases:" 1806 <<
"\n# - By explicitly marking it so in the label constructor" 1807 <<
"\n# - By having seen different bound values at branches" 1809 <<
"\n# Merge count: expected=" << merge_count_
1810 <<
" vs. found=" << (not_found ? 0 :
i->second.size())
1811 <<
"\n# Variable: " << *var_impl
1812 <<
"\n# Current Block: " << *label_->block();
1813 FATAL(
"%s", str.str().c_str());
1816 Node* phi = state_->raw_assembler_->Phi(
1817 var.first->rep_, static_cast<int>(merge_count_), &(
i->second[0]));
1818 variable_phis_[var_impl] = phi;
1823 for (
auto var : state_->variables_) {
1824 auto i = variable_phis_.find(var);
1825 if (
i != variable_phis_.end()) {
1826 var->value_ =
i->second;
1828 auto j = variable_merges_.find(var);
1829 if (j != variable_merges_.end() && j->second.size() == merge_count_) {
1830 var->value_ = j->second.back();
1832 var->value_ =
nullptr;
1840 void CodeAssemblerParameterizedLabelBase::AddInputs(std::vector<Node*> inputs) {
1841 if (!phi_nodes_.empty()) {
1842 DCHECK_EQ(inputs.size(), phi_nodes_.size());
1843 for (
size_t i = 0;
i < inputs.size(); ++
i) {
1844 state_->raw_assembler_->AppendPhiInput(phi_nodes_[
i], inputs[
i]);
1847 DCHECK_EQ(inputs.size(), phi_inputs_.size());
1848 for (
size_t i = 0;
i < inputs.size(); ++
i) {
1849 phi_inputs_[
i].push_back(inputs[
i]);
1854 Node* CodeAssemblerParameterizedLabelBase::CreatePhi(
1855 MachineRepresentation rep,
const std::vector<Node*>& inputs) {
1856 for (Node* input : inputs) {
1859 if (input ==
nullptr)
return nullptr;
1861 return state_->raw_assembler_->Phi(rep, static_cast<int>(inputs.size()),
1865 const std::vector<Node*>& CodeAssemblerParameterizedLabelBase::CreatePhis(
1866 std::vector<MachineRepresentation> representations) {
1868 DCHECK(phi_nodes_.empty());
1869 phi_nodes_.reserve(phi_inputs_.size());
1870 DCHECK_EQ(representations.size(), phi_inputs_.size());
1871 for (
size_t i = 0;
i < phi_inputs_.size(); ++
i) {
1872 phi_nodes_.push_back(CreatePhi(representations[
i], phi_inputs_[
i]));
1877 void CodeAssemblerState::PushExceptionHandler(
1878 CodeAssemblerExceptionHandlerLabel* label) {
1879 exception_handler_labels_.push_back(label);
1882 void CodeAssemblerState::PopExceptionHandler() {
1883 exception_handler_labels_.pop_back();
1886 CodeAssemblerScopedExceptionHandler::CodeAssemblerScopedExceptionHandler(
1887 CodeAssembler* assembler, CodeAssemblerExceptionHandlerLabel* label)
1888 : has_handler_(label != nullptr),
1889 assembler_(assembler),
1890 compatibility_label_(nullptr),
1891 exception_(nullptr) {
1893 assembler_->state()->PushExceptionHandler(label);
1897 CodeAssemblerScopedExceptionHandler::CodeAssemblerScopedExceptionHandler(
1898 CodeAssembler* assembler, CodeAssemblerLabel* label,
1899 TypedCodeAssemblerVariable<Object>* exception)
1900 : has_handler_(label != nullptr),
1901 assembler_(assembler),
1902 compatibility_label_(label),
1903 exception_(exception) {
1905 label_ = base::make_unique<CodeAssemblerExceptionHandlerLabel>(
1906 assembler, CodeAssemblerLabel::kDeferred);
1907 assembler_->state()->PushExceptionHandler(label_.get());
1911 CodeAssemblerScopedExceptionHandler::~CodeAssemblerScopedExceptionHandler() {
1913 assembler_->state()->PopExceptionHandler();
1915 if (label_ && label_->is_used()) {
1916 CodeAssembler::Label skip(assembler_);
1917 bool inside_block = assembler_->state()->InsideBlock();
1919 assembler_->Goto(&skip);
1922 assembler_->Bind(label_.get(), &e);
1924 assembler_->Goto(compatibility_label_);
1926 assembler_->Bind(&skip);
1933 Address CheckObjectType(Object* value, Address raw_type, Address raw_location) {
1936 String location = String::cast(ObjectPtr(raw_location));
1937 const char* expected;
1938 switch (static_cast<ObjectType>(type->value())) {
1939 #define TYPE_CASE(Name) \ 1940 case ObjectType::k##Name: \ 1941 if (value->Is##Name()) return Smi::FromInt(0).ptr(); \ 1944 #define TYPE_STRUCT_CASE(NAME, Name, name) \ 1945 case ObjectType::k##Name: \ 1946 if (value->Is##Name()) return Smi::FromInt(0).ptr(); \ 1951 OBJECT_TYPE_LIST(TYPE_CASE)
1952 HEAP_OBJECT_TYPE_LIST(TYPE_CASE)
1953 STRUCT_LIST(TYPE_STRUCT_CASE)
1955 #undef TYPE_STRUCT_CASE 1957 std::stringstream value_description;
1958 value->Print(value_description);
1959 V8_Fatal(__FILE__, __LINE__,
1960 "Type cast failed in %s\n" 1961 " Expected %s but found %s",
1962 location->ToAsciiArray(), expected, value_description.str().c_str());