1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/compiler/code-assembler.h"
6 
7 #include <ostream>
8 
9 #include "src/code-factory.h"
10 #include "src/compiler/graph.h"
11 #include "src/compiler/instruction-selector.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"
20 #include "src/machine-type.h"
21 #include "src/macro-assembler.h"
22 #include "src/utils.h"
23 #include "src/zone/zone.h"
24 
25 namespace v8 {
26 namespace internal {
27 namespace compiler {
28 
CodeAssembler(Isolate * isolate,Zone * zone,const CallInterfaceDescriptor & descriptor,Code::Flags flags,const char * name,size_t result_size)29 CodeAssembler::CodeAssembler(Isolate* isolate, Zone* zone,
30                              const CallInterfaceDescriptor& descriptor,
31                              Code::Flags flags, const char* name,
32                              size_t result_size)
33     : CodeAssembler(
34           isolate, zone,
35           Linkage::GetStubCallDescriptor(
36               isolate, zone, descriptor, descriptor.GetStackParameterCount(),
37               CallDescriptor::kNoFlags, Operator::kNoProperties,
38               MachineType::AnyTagged(), result_size),
39           flags, name) {}
40 
CodeAssembler(Isolate * isolate,Zone * zone,int parameter_count,Code::Flags flags,const char * name)41 CodeAssembler::CodeAssembler(Isolate* isolate, Zone* zone, int parameter_count,
42                              Code::Flags flags, const char* name)
43     : CodeAssembler(isolate, zone,
44                     Linkage::GetJSCallDescriptor(
45                         zone, false, parameter_count,
46                         Code::ExtractKindFromFlags(flags) == Code::BUILTIN
47                             ? CallDescriptor::kPushArgumentCount
48                             : CallDescriptor::kNoFlags),
49                     flags, name) {}
50 
CodeAssembler(Isolate * isolate,Zone * zone,CallDescriptor * call_descriptor,Code::Flags flags,const char * name)51 CodeAssembler::CodeAssembler(Isolate* isolate, Zone* zone,
52                              CallDescriptor* call_descriptor, Code::Flags flags,
53                              const char* name)
54     : raw_assembler_(new RawMachineAssembler(
55           isolate, new (zone) Graph(zone), call_descriptor,
56           MachineType::PointerRepresentation(),
57           InstructionSelector::SupportedMachineOperatorFlags(),
58           InstructionSelector::AlignmentRequirements())),
59       flags_(flags),
60       name_(name),
61       code_generated_(false),
62       variables_(zone) {}
63 
~CodeAssembler()64 CodeAssembler::~CodeAssembler() {}
65 
CallPrologue()66 void CodeAssembler::CallPrologue() {}
67 
CallEpilogue()68 void CodeAssembler::CallEpilogue() {}
69 
GenerateCode()70 Handle<Code> CodeAssembler::GenerateCode() {
71   DCHECK(!code_generated_);
72 
73   Schedule* schedule = raw_assembler_->Export();
74   Handle<Code> code = Pipeline::GenerateCodeForCodeStub(
75       isolate(), raw_assembler_->call_descriptor(), raw_assembler_->graph(),
76       schedule, flags_, name_);
77 
78   code_generated_ = true;
79   return code;
80 }
81 
Is64() const82 bool CodeAssembler::Is64() const { return raw_assembler_->machine()->Is64(); }
83 
IsFloat64RoundUpSupported() const84 bool CodeAssembler::IsFloat64RoundUpSupported() const {
85   return raw_assembler_->machine()->Float64RoundUp().IsSupported();
86 }
87 
IsFloat64RoundDownSupported() const88 bool CodeAssembler::IsFloat64RoundDownSupported() const {
89   return raw_assembler_->machine()->Float64RoundDown().IsSupported();
90 }
91 
IsFloat64RoundTiesEvenSupported() const92 bool CodeAssembler::IsFloat64RoundTiesEvenSupported() const {
93   return raw_assembler_->machine()->Float64RoundTiesEven().IsSupported();
94 }
95 
IsFloat64RoundTruncateSupported() const96 bool CodeAssembler::IsFloat64RoundTruncateSupported() const {
97   return raw_assembler_->machine()->Float64RoundTruncate().IsSupported();
98 }
99 
Int32Constant(int32_t value)100 Node* CodeAssembler::Int32Constant(int32_t value) {
101   return raw_assembler_->Int32Constant(value);
102 }
103 
Int64Constant(int64_t value)104 Node* CodeAssembler::Int64Constant(int64_t value) {
105   return raw_assembler_->Int64Constant(value);
106 }
107 
IntPtrConstant(intptr_t value)108 Node* CodeAssembler::IntPtrConstant(intptr_t value) {
109   return raw_assembler_->IntPtrConstant(value);
110 }
111 
NumberConstant(double value)112 Node* CodeAssembler::NumberConstant(double value) {
113   return raw_assembler_->NumberConstant(value);
114 }
115 
SmiConstant(Smi * value)116 Node* CodeAssembler::SmiConstant(Smi* value) {
117   return BitcastWordToTaggedSigned(IntPtrConstant(bit_cast<intptr_t>(value)));
118 }
119 
SmiConstant(int value)120 Node* CodeAssembler::SmiConstant(int value) {
121   return SmiConstant(Smi::FromInt(value));
122 }
123 
HeapConstant(Handle<HeapObject> object)124 Node* CodeAssembler::HeapConstant(Handle<HeapObject> object) {
125   return raw_assembler_->HeapConstant(object);
126 }
127 
BooleanConstant(bool value)128 Node* CodeAssembler::BooleanConstant(bool value) {
129   return raw_assembler_->BooleanConstant(value);
130 }
131 
ExternalConstant(ExternalReference address)132 Node* CodeAssembler::ExternalConstant(ExternalReference address) {
133   return raw_assembler_->ExternalConstant(address);
134 }
135 
Float64Constant(double value)136 Node* CodeAssembler::Float64Constant(double value) {
137   return raw_assembler_->Float64Constant(value);
138 }
139 
NaNConstant()140 Node* CodeAssembler::NaNConstant() {
141   return LoadRoot(Heap::kNanValueRootIndex);
142 }
143 
ToInt32Constant(Node * node,int32_t & out_value)144 bool CodeAssembler::ToInt32Constant(Node* node, int32_t& out_value) {
145   Int64Matcher m(node);
146   if (m.HasValue() &&
147       m.IsInRange(std::numeric_limits<int32_t>::min(),
148                   std::numeric_limits<int32_t>::max())) {
149     out_value = static_cast<int32_t>(m.Value());
150     return true;
151   }
152 
153   return false;
154 }
155 
ToInt64Constant(Node * node,int64_t & out_value)156 bool CodeAssembler::ToInt64Constant(Node* node, int64_t& out_value) {
157   Int64Matcher m(node);
158   if (m.HasValue()) out_value = m.Value();
159   return m.HasValue();
160 }
161 
ToSmiConstant(Node * node,Smi * & out_value)162 bool CodeAssembler::ToSmiConstant(Node* node, Smi*& out_value) {
163   if (node->opcode() == IrOpcode::kBitcastWordToTaggedSigned) {
164     node = node->InputAt(0);
165   } else {
166     return false;
167   }
168   IntPtrMatcher m(node);
169   if (m.HasValue()) {
170     out_value = Smi::cast(bit_cast<Object*>(m.Value()));
171     return true;
172   }
173   return false;
174 }
175 
ToIntPtrConstant(Node * node,intptr_t & out_value)176 bool CodeAssembler::ToIntPtrConstant(Node* node, intptr_t& out_value) {
177   IntPtrMatcher m(node);
178   if (m.HasValue()) out_value = m.Value();
179   return m.HasValue();
180 }
181 
Parameter(int value)182 Node* CodeAssembler::Parameter(int value) {
183   return raw_assembler_->Parameter(value);
184 }
185 
Return(Node * value)186 void CodeAssembler::Return(Node* value) {
187   return raw_assembler_->Return(value);
188 }
189 
PopAndReturn(Node * pop,Node * value)190 void CodeAssembler::PopAndReturn(Node* pop, Node* value) {
191   return raw_assembler_->PopAndReturn(pop, value);
192 }
193 
DebugBreak()194 void CodeAssembler::DebugBreak() { raw_assembler_->DebugBreak(); }
195 
Comment(const char * format,...)196 void CodeAssembler::Comment(const char* format, ...) {
197   if (!FLAG_code_comments) return;
198   char buffer[4 * KB];
199   StringBuilder builder(buffer, arraysize(buffer));
200   va_list arguments;
201   va_start(arguments, format);
202   builder.AddFormattedList(format, arguments);
203   va_end(arguments);
204 
205   // Copy the string before recording it in the assembler to avoid
206   // issues when the stack allocated buffer goes out of scope.
207   const int prefix_len = 2;
208   int length = builder.position() + 1;
209   char* copy = reinterpret_cast<char*>(malloc(length + prefix_len));
210   MemCopy(copy + prefix_len, builder.Finalize(), length);
211   copy[0] = ';';
212   copy[1] = ' ';
213   raw_assembler_->Comment(copy);
214 }
215 
Bind(CodeAssembler::Label * label)216 void CodeAssembler::Bind(CodeAssembler::Label* label) { return label->Bind(); }
217 
LoadFramePointer()218 Node* CodeAssembler::LoadFramePointer() {
219   return raw_assembler_->LoadFramePointer();
220 }
221 
LoadParentFramePointer()222 Node* CodeAssembler::LoadParentFramePointer() {
223   return raw_assembler_->LoadParentFramePointer();
224 }
225 
LoadStackPointer()226 Node* CodeAssembler::LoadStackPointer() {
227   return raw_assembler_->LoadStackPointer();
228 }
229 
230 #define DEFINE_CODE_ASSEMBLER_BINARY_OP(name)   \
231   Node* CodeAssembler::name(Node* a, Node* b) { \
232     return raw_assembler_->name(a, b);          \
233   }
CODE_ASSEMBLER_BINARY_OP_LIST(DEFINE_CODE_ASSEMBLER_BINARY_OP)234 CODE_ASSEMBLER_BINARY_OP_LIST(DEFINE_CODE_ASSEMBLER_BINARY_OP)
235 #undef DEFINE_CODE_ASSEMBLER_BINARY_OP
236 
237 Node* CodeAssembler::WordShl(Node* value, int shift) {
238   return (shift != 0) ? raw_assembler_->WordShl(value, IntPtrConstant(shift))
239                       : value;
240 }
241 
WordShr(Node * value,int shift)242 Node* CodeAssembler::WordShr(Node* value, int shift) {
243   return (shift != 0) ? raw_assembler_->WordShr(value, IntPtrConstant(shift))
244                       : value;
245 }
246 
Word32Shr(Node * value,int shift)247 Node* CodeAssembler::Word32Shr(Node* value, int shift) {
248   return (shift != 0) ? raw_assembler_->Word32Shr(value, Int32Constant(shift))
249                       : value;
250 }
251 
ChangeUint32ToWord(Node * value)252 Node* CodeAssembler::ChangeUint32ToWord(Node* value) {
253   if (raw_assembler_->machine()->Is64()) {
254     value = raw_assembler_->ChangeUint32ToUint64(value);
255   }
256   return value;
257 }
258 
ChangeInt32ToIntPtr(Node * value)259 Node* CodeAssembler::ChangeInt32ToIntPtr(Node* value) {
260   if (raw_assembler_->machine()->Is64()) {
261     value = raw_assembler_->ChangeInt32ToInt64(value);
262   }
263   return value;
264 }
265 
RoundIntPtrToFloat64(Node * value)266 Node* CodeAssembler::RoundIntPtrToFloat64(Node* value) {
267   if (raw_assembler_->machine()->Is64()) {
268     return raw_assembler_->RoundInt64ToFloat64(value);
269   }
270   return raw_assembler_->ChangeInt32ToFloat64(value);
271 }
272 
273 #define DEFINE_CODE_ASSEMBLER_UNARY_OP(name) \
274   Node* CodeAssembler::name(Node* a) { return raw_assembler_->name(a); }
CODE_ASSEMBLER_UNARY_OP_LIST(DEFINE_CODE_ASSEMBLER_UNARY_OP)275 CODE_ASSEMBLER_UNARY_OP_LIST(DEFINE_CODE_ASSEMBLER_UNARY_OP)
276 #undef DEFINE_CODE_ASSEMBLER_UNARY_OP
277 
278 Node* CodeAssembler::Load(MachineType rep, Node* base) {
279   return raw_assembler_->Load(rep, base);
280 }
281 
Load(MachineType rep,Node * base,Node * index)282 Node* CodeAssembler::Load(MachineType rep, Node* base, Node* index) {
283   return raw_assembler_->Load(rep, base, index);
284 }
285 
AtomicLoad(MachineType rep,Node * base,Node * index)286 Node* CodeAssembler::AtomicLoad(MachineType rep, Node* base, Node* index) {
287   return raw_assembler_->AtomicLoad(rep, base, index);
288 }
289 
LoadRoot(Heap::RootListIndex root_index)290 Node* CodeAssembler::LoadRoot(Heap::RootListIndex root_index) {
291   if (isolate()->heap()->RootCanBeTreatedAsConstant(root_index)) {
292     Handle<Object> root = isolate()->heap()->root_handle(root_index);
293     if (root->IsSmi()) {
294       return SmiConstant(Smi::cast(*root));
295     } else {
296       return HeapConstant(Handle<HeapObject>::cast(root));
297     }
298   }
299 
300   Node* roots_array_start =
301       ExternalConstant(ExternalReference::roots_array_start(isolate()));
302   return Load(MachineType::AnyTagged(), roots_array_start,
303               IntPtrConstant(root_index * kPointerSize));
304 }
305 
Store(MachineRepresentation rep,Node * base,Node * value)306 Node* CodeAssembler::Store(MachineRepresentation rep, Node* base, Node* value) {
307   return raw_assembler_->Store(rep, base, value, kFullWriteBarrier);
308 }
309 
Store(MachineRepresentation rep,Node * base,Node * index,Node * value)310 Node* CodeAssembler::Store(MachineRepresentation rep, Node* base, Node* index,
311                            Node* value) {
312   return raw_assembler_->Store(rep, base, index, value, kFullWriteBarrier);
313 }
314 
StoreNoWriteBarrier(MachineRepresentation rep,Node * base,Node * value)315 Node* CodeAssembler::StoreNoWriteBarrier(MachineRepresentation rep, Node* base,
316                                          Node* value) {
317   return raw_assembler_->Store(rep, base, value, kNoWriteBarrier);
318 }
319 
StoreNoWriteBarrier(MachineRepresentation rep,Node * base,Node * index,Node * value)320 Node* CodeAssembler::StoreNoWriteBarrier(MachineRepresentation rep, Node* base,
321                                          Node* index, Node* value) {
322   return raw_assembler_->Store(rep, base, index, value, kNoWriteBarrier);
323 }
324 
AtomicStore(MachineRepresentation rep,Node * base,Node * index,Node * value)325 Node* CodeAssembler::AtomicStore(MachineRepresentation rep, Node* base,
326                                  Node* index, Node* value) {
327   return raw_assembler_->AtomicStore(rep, base, index, value);
328 }
329 
StoreRoot(Heap::RootListIndex root_index,Node * value)330 Node* CodeAssembler::StoreRoot(Heap::RootListIndex root_index, Node* value) {
331   DCHECK(Heap::RootCanBeWrittenAfterInitialization(root_index));
332   Node* roots_array_start =
333       ExternalConstant(ExternalReference::roots_array_start(isolate()));
334   return StoreNoWriteBarrier(MachineRepresentation::kTagged, roots_array_start,
335                              IntPtrConstant(root_index * kPointerSize), value);
336 }
337 
Retain(Node * value)338 Node* CodeAssembler::Retain(Node* value) {
339   return raw_assembler_->Retain(value);
340 }
341 
Projection(int index,Node * value)342 Node* CodeAssembler::Projection(int index, Node* value) {
343   return raw_assembler_->Projection(index, value);
344 }
345 
GotoIfException(Node * node,Label * if_exception,Variable * exception_var)346 void CodeAssembler::GotoIfException(Node* node, Label* if_exception,
347                                     Variable* exception_var) {
348   Label success(this), exception(this, Label::kDeferred);
349   success.MergeVariables();
350   exception.MergeVariables();
351   DCHECK(!node->op()->HasProperty(Operator::kNoThrow));
352 
353   raw_assembler_->Continuations(node, success.label_, exception.label_);
354 
355   Bind(&exception);
356   const Operator* op = raw_assembler_->common()->IfException();
357   Node* exception_value = raw_assembler_->AddNode(op, node, node);
358   if (exception_var != nullptr) {
359     exception_var->Bind(exception_value);
360   }
361   Goto(if_exception);
362 
363   Bind(&success);
364 }
365 
CallN(CallDescriptor * descriptor,Node * code_target,Node ** args)366 Node* CodeAssembler::CallN(CallDescriptor* descriptor, Node* code_target,
367                            Node** args) {
368   CallPrologue();
369   Node* return_value = raw_assembler_->CallN(descriptor, code_target, args);
370   CallEpilogue();
371   return return_value;
372 }
373 
TailCallN(CallDescriptor * descriptor,Node * code_target,Node ** args)374 Node* CodeAssembler::TailCallN(CallDescriptor* descriptor, Node* code_target,
375                                Node** args) {
376   return raw_assembler_->TailCallN(descriptor, code_target, args);
377 }
378 
CallRuntime(Runtime::FunctionId function_id,Node * context)379 Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id,
380                                  Node* context) {
381   CallPrologue();
382   Node* return_value = raw_assembler_->CallRuntime0(function_id, context);
383   CallEpilogue();
384   return return_value;
385 }
386 
CallRuntime(Runtime::FunctionId function_id,Node * context,Node * arg1)387 Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id, Node* context,
388                                  Node* arg1) {
389   CallPrologue();
390   Node* return_value = raw_assembler_->CallRuntime1(function_id, arg1, context);
391   CallEpilogue();
392   return return_value;
393 }
394 
CallRuntime(Runtime::FunctionId function_id,Node * context,Node * arg1,Node * arg2)395 Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id, Node* context,
396                                  Node* arg1, Node* arg2) {
397   CallPrologue();
398   Node* return_value =
399       raw_assembler_->CallRuntime2(function_id, arg1, arg2, context);
400   CallEpilogue();
401   return return_value;
402 }
403 
CallRuntime(Runtime::FunctionId function_id,Node * context,Node * arg1,Node * arg2,Node * arg3)404 Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id, Node* context,
405                                  Node* arg1, Node* arg2, Node* arg3) {
406   CallPrologue();
407   Node* return_value =
408       raw_assembler_->CallRuntime3(function_id, arg1, arg2, arg3, context);
409   CallEpilogue();
410   return return_value;
411 }
412 
CallRuntime(Runtime::FunctionId function_id,Node * context,Node * arg1,Node * arg2,Node * arg3,Node * arg4)413 Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id, Node* context,
414                                  Node* arg1, Node* arg2, Node* arg3,
415                                  Node* arg4) {
416   CallPrologue();
417   Node* return_value = raw_assembler_->CallRuntime4(function_id, arg1, arg2,
418                                                     arg3, arg4, context);
419   CallEpilogue();
420   return return_value;
421 }
422 
CallRuntime(Runtime::FunctionId function_id,Node * context,Node * arg1,Node * arg2,Node * arg3,Node * arg4,Node * arg5)423 Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id, Node* context,
424                                  Node* arg1, Node* arg2, Node* arg3, Node* arg4,
425                                  Node* arg5) {
426   CallPrologue();
427   Node* return_value = raw_assembler_->CallRuntime5(function_id, arg1, arg2,
428                                                     arg3, arg4, arg5, context);
429   CallEpilogue();
430   return return_value;
431 }
432 
TailCallRuntime(Runtime::FunctionId function_id,Node * context)433 Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
434                                      Node* context) {
435   return raw_assembler_->TailCallRuntime0(function_id, context);
436 }
437 
TailCallRuntime(Runtime::FunctionId function_id,Node * context,Node * arg1)438 Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
439                                      Node* context, Node* arg1) {
440   return raw_assembler_->TailCallRuntime1(function_id, arg1, context);
441 }
442 
TailCallRuntime(Runtime::FunctionId function_id,Node * context,Node * arg1,Node * arg2)443 Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
444                                      Node* context, Node* arg1, Node* arg2) {
445   return raw_assembler_->TailCallRuntime2(function_id, arg1, arg2, context);
446 }
447 
TailCallRuntime(Runtime::FunctionId function_id,Node * context,Node * arg1,Node * arg2,Node * arg3)448 Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
449                                      Node* context, Node* arg1, Node* arg2,
450                                      Node* arg3) {
451   return raw_assembler_->TailCallRuntime3(function_id, arg1, arg2, arg3,
452                                           context);
453 }
454 
TailCallRuntime(Runtime::FunctionId function_id,Node * context,Node * arg1,Node * arg2,Node * arg3,Node * arg4)455 Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
456                                      Node* context, Node* arg1, Node* arg2,
457                                      Node* arg3, Node* arg4) {
458   return raw_assembler_->TailCallRuntime4(function_id, arg1, arg2, arg3, arg4,
459                                           context);
460 }
461 
TailCallRuntime(Runtime::FunctionId function_id,Node * context,Node * arg1,Node * arg2,Node * arg3,Node * arg4,Node * arg5)462 Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
463                                      Node* context, Node* arg1, Node* arg2,
464                                      Node* arg3, Node* arg4, Node* arg5) {
465   return raw_assembler_->TailCallRuntime5(function_id, arg1, arg2, arg3, arg4,
466                                           arg5, context);
467 }
468 
TailCallRuntime(Runtime::FunctionId function_id,Node * context,Node * arg1,Node * arg2,Node * arg3,Node * arg4,Node * arg5,Node * arg6)469 Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
470                                      Node* context, Node* arg1, Node* arg2,
471                                      Node* arg3, Node* arg4, Node* arg5,
472                                      Node* arg6) {
473   return raw_assembler_->TailCallRuntime6(function_id, arg1, arg2, arg3, arg4,
474                                           arg5, arg6, context);
475 }
476 
CallStub(Callable const & callable,Node * context,Node * arg1,size_t result_size)477 Node* CodeAssembler::CallStub(Callable const& callable, Node* context,
478                               Node* arg1, size_t result_size) {
479   Node* target = HeapConstant(callable.code());
480   return CallStub(callable.descriptor(), target, context, arg1, result_size);
481 }
482 
CallStub(Callable const & callable,Node * context,Node * arg1,Node * arg2,size_t result_size)483 Node* CodeAssembler::CallStub(Callable const& callable, Node* context,
484                               Node* arg1, Node* arg2, size_t result_size) {
485   Node* target = HeapConstant(callable.code());
486   return CallStub(callable.descriptor(), target, context, arg1, arg2,
487                   result_size);
488 }
489 
CallStub(Callable const & callable,Node * context,Node * arg1,Node * arg2,Node * arg3,size_t result_size)490 Node* CodeAssembler::CallStub(Callable const& callable, Node* context,
491                               Node* arg1, Node* arg2, Node* arg3,
492                               size_t result_size) {
493   Node* target = HeapConstant(callable.code());
494   return CallStub(callable.descriptor(), target, context, arg1, arg2, arg3,
495                   result_size);
496 }
497 
CallStub(Callable const & callable,Node * context,Node * arg1,Node * arg2,Node * arg3,Node * arg4,size_t result_size)498 Node* CodeAssembler::CallStub(Callable const& callable, Node* context,
499                               Node* arg1, Node* arg2, Node* arg3, Node* arg4,
500                               size_t result_size) {
501   Node* target = HeapConstant(callable.code());
502   return CallStub(callable.descriptor(), target, context, arg1, arg2, arg3,
503                   arg4, result_size);
504 }
505 
CallStubN(Callable const & callable,Node ** args,size_t result_size)506 Node* CodeAssembler::CallStubN(Callable const& callable, Node** args,
507                                size_t result_size) {
508   Node* target = HeapConstant(callable.code());
509   return CallStubN(callable.descriptor(), target, args, result_size);
510 }
511 
CallStub(const CallInterfaceDescriptor & descriptor,Node * target,Node * context,size_t result_size)512 Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
513                               Node* target, Node* context, size_t result_size) {
514   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
515       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
516       CallDescriptor::kNoFlags, Operator::kNoProperties,
517       MachineType::AnyTagged(), result_size);
518 
519   Node** args = zone()->NewArray<Node*>(1);
520   args[0] = context;
521 
522   return CallN(call_descriptor, target, args);
523 }
524 
CallStub(const CallInterfaceDescriptor & descriptor,Node * target,Node * context,Node * arg1,size_t result_size)525 Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
526                               Node* target, Node* context, Node* arg1,
527                               size_t result_size) {
528   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
529       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
530       CallDescriptor::kNoFlags, Operator::kNoProperties,
531       MachineType::AnyTagged(), result_size);
532 
533   Node** args = zone()->NewArray<Node*>(2);
534   args[0] = arg1;
535   args[1] = context;
536 
537   return CallN(call_descriptor, target, args);
538 }
539 
CallStub(const CallInterfaceDescriptor & descriptor,Node * target,Node * context,Node * arg1,Node * arg2,size_t result_size)540 Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
541                               Node* target, Node* context, Node* arg1,
542                               Node* arg2, size_t result_size) {
543   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
544       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
545       CallDescriptor::kNoFlags, Operator::kNoProperties,
546       MachineType::AnyTagged(), result_size);
547 
548   Node** args = zone()->NewArray<Node*>(3);
549   args[0] = arg1;
550   args[1] = arg2;
551   args[2] = context;
552 
553   return CallN(call_descriptor, target, args);
554 }
555 
CallStub(const CallInterfaceDescriptor & descriptor,Node * target,Node * context,Node * arg1,Node * arg2,Node * arg3,size_t result_size)556 Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
557                               Node* target, Node* context, Node* arg1,
558                               Node* arg2, Node* arg3, size_t result_size) {
559   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
560       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
561       CallDescriptor::kNoFlags, Operator::kNoProperties,
562       MachineType::AnyTagged(), result_size);
563 
564   Node** args = zone()->NewArray<Node*>(4);
565   args[0] = arg1;
566   args[1] = arg2;
567   args[2] = arg3;
568   args[3] = context;
569 
570   return CallN(call_descriptor, target, args);
571 }
572 
CallStub(const CallInterfaceDescriptor & descriptor,Node * target,Node * context,Node * arg1,Node * arg2,Node * arg3,Node * arg4,size_t result_size)573 Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
574                               Node* target, Node* context, Node* arg1,
575                               Node* arg2, Node* arg3, Node* arg4,
576                               size_t result_size) {
577   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
578       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
579       CallDescriptor::kNoFlags, Operator::kNoProperties,
580       MachineType::AnyTagged(), result_size);
581 
582   Node** args = zone()->NewArray<Node*>(5);
583   args[0] = arg1;
584   args[1] = arg2;
585   args[2] = arg3;
586   args[3] = arg4;
587   args[4] = context;
588 
589   return CallN(call_descriptor, target, args);
590 }
591 
CallStub(const CallInterfaceDescriptor & descriptor,Node * target,Node * context,Node * arg1,Node * arg2,Node * arg3,Node * arg4,Node * arg5,size_t result_size)592 Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
593                               Node* target, Node* context, Node* arg1,
594                               Node* arg2, Node* arg3, Node* arg4, Node* arg5,
595                               size_t result_size) {
596   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
597       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
598       CallDescriptor::kNoFlags, Operator::kNoProperties,
599       MachineType::AnyTagged(), result_size);
600 
601   Node** args = zone()->NewArray<Node*>(6);
602   args[0] = arg1;
603   args[1] = arg2;
604   args[2] = arg3;
605   args[3] = arg4;
606   args[4] = arg5;
607   args[5] = context;
608 
609   return CallN(call_descriptor, target, args);
610 }
611 
CallStub(const CallInterfaceDescriptor & descriptor,Node * target,Node * context,const Arg & arg1,const Arg & arg2,size_t result_size)612 Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
613                               Node* target, Node* context, const Arg& arg1,
614                               const Arg& arg2, size_t result_size) {
615   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
616       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
617       CallDescriptor::kNoFlags, Operator::kNoProperties,
618       MachineType::AnyTagged(), result_size);
619 
620   const int kArgsCount = 3;
621   Node** args = zone()->NewArray<Node*>(kArgsCount);
622   DCHECK((std::fill(&args[0], &args[kArgsCount], nullptr), true));
623   args[arg1.index] = arg1.value;
624   args[arg2.index] = arg2.value;
625   args[kArgsCount - 1] = context;
626   DCHECK_EQ(0, std::count(&args[0], &args[kArgsCount], nullptr));
627 
628   return CallN(call_descriptor, target, args);
629 }
630 
CallStub(const CallInterfaceDescriptor & descriptor,Node * target,Node * context,const Arg & arg1,const Arg & arg2,const Arg & arg3,size_t result_size)631 Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
632                               Node* target, Node* context, const Arg& arg1,
633                               const Arg& arg2, const Arg& arg3,
634                               size_t result_size) {
635   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
636       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
637       CallDescriptor::kNoFlags, Operator::kNoProperties,
638       MachineType::AnyTagged(), result_size);
639 
640   const int kArgsCount = 4;
641   Node** args = zone()->NewArray<Node*>(kArgsCount);
642   DCHECK((std::fill(&args[0], &args[kArgsCount], nullptr), true));
643   args[arg1.index] = arg1.value;
644   args[arg2.index] = arg2.value;
645   args[arg3.index] = arg3.value;
646   args[kArgsCount - 1] = context;
647   DCHECK_EQ(0, std::count(&args[0], &args[kArgsCount], nullptr));
648 
649   return CallN(call_descriptor, target, args);
650 }
651 
CallStub(const CallInterfaceDescriptor & descriptor,Node * target,Node * context,const Arg & arg1,const Arg & arg2,const Arg & arg3,const Arg & arg4,size_t result_size)652 Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
653                               Node* target, Node* context, const Arg& arg1,
654                               const Arg& arg2, const Arg& arg3, const Arg& arg4,
655                               size_t result_size) {
656   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
657       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
658       CallDescriptor::kNoFlags, Operator::kNoProperties,
659       MachineType::AnyTagged(), result_size);
660 
661   const int kArgsCount = 5;
662   Node** args = zone()->NewArray<Node*>(kArgsCount);
663   DCHECK((std::fill(&args[0], &args[kArgsCount], nullptr), true));
664   args[arg1.index] = arg1.value;
665   args[arg2.index] = arg2.value;
666   args[arg3.index] = arg3.value;
667   args[arg4.index] = arg4.value;
668   args[kArgsCount - 1] = context;
669   DCHECK_EQ(0, std::count(&args[0], &args[kArgsCount], nullptr));
670 
671   return CallN(call_descriptor, target, args);
672 }
673 
CallStub(const CallInterfaceDescriptor & descriptor,Node * target,Node * context,const Arg & arg1,const Arg & arg2,const Arg & arg3,const Arg & arg4,const Arg & arg5,size_t result_size)674 Node* CodeAssembler::CallStub(const CallInterfaceDescriptor& descriptor,
675                               Node* target, Node* context, const Arg& arg1,
676                               const Arg& arg2, const Arg& arg3, const Arg& arg4,
677                               const Arg& arg5, size_t result_size) {
678   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
679       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
680       CallDescriptor::kNoFlags, Operator::kNoProperties,
681       MachineType::AnyTagged(), result_size);
682 
683   const int kArgsCount = 6;
684   Node** args = zone()->NewArray<Node*>(kArgsCount);
685   DCHECK((std::fill(&args[0], &args[kArgsCount], nullptr), true));
686   args[arg1.index] = arg1.value;
687   args[arg2.index] = arg2.value;
688   args[arg3.index] = arg3.value;
689   args[arg4.index] = arg4.value;
690   args[arg5.index] = arg5.value;
691   args[kArgsCount - 1] = context;
692   DCHECK_EQ(0, std::count(&args[0], &args[kArgsCount], nullptr));
693 
694   return CallN(call_descriptor, target, args);
695 }
696 
CallStubN(const CallInterfaceDescriptor & descriptor,int js_parameter_count,Node * target,Node ** args,size_t result_size)697 Node* CodeAssembler::CallStubN(const CallInterfaceDescriptor& descriptor,
698                                int js_parameter_count, Node* target,
699                                Node** args, size_t result_size) {
700   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
701       isolate(), zone(), descriptor,
702       descriptor.GetStackParameterCount() + js_parameter_count,
703       CallDescriptor::kNoFlags, Operator::kNoProperties,
704       MachineType::AnyTagged(), result_size);
705 
706   return CallN(call_descriptor, target, args);
707 }
708 
TailCallStub(Callable const & callable,Node * context,Node * arg1,size_t result_size)709 Node* CodeAssembler::TailCallStub(Callable const& callable, Node* context,
710                                   Node* arg1, size_t result_size) {
711   Node* target = HeapConstant(callable.code());
712   return TailCallStub(callable.descriptor(), target, context, arg1,
713                       result_size);
714 }
715 
TailCallStub(Callable const & callable,Node * context,Node * arg1,Node * arg2,size_t result_size)716 Node* CodeAssembler::TailCallStub(Callable const& callable, Node* context,
717                                   Node* arg1, Node* arg2, size_t result_size) {
718   Node* target = HeapConstant(callable.code());
719   return TailCallStub(callable.descriptor(), target, context, arg1, arg2,
720                       result_size);
721 }
722 
TailCallStub(Callable const & callable,Node * context,Node * arg1,Node * arg2,Node * arg3,size_t result_size)723 Node* CodeAssembler::TailCallStub(Callable const& callable, Node* context,
724                                   Node* arg1, Node* arg2, Node* arg3,
725                                   size_t result_size) {
726   Node* target = HeapConstant(callable.code());
727   return TailCallStub(callable.descriptor(), target, context, arg1, arg2, arg3,
728                       result_size);
729 }
730 
TailCallStub(Callable const & callable,Node * context,Node * arg1,Node * arg2,Node * arg3,Node * arg4,size_t result_size)731 Node* CodeAssembler::TailCallStub(Callable const& callable, Node* context,
732                                   Node* arg1, Node* arg2, Node* arg3,
733                                   Node* arg4, size_t result_size) {
734   Node* target = HeapConstant(callable.code());
735   return TailCallStub(callable.descriptor(), target, context, arg1, arg2, arg3,
736                       arg4, result_size);
737 }
738 
TailCallStub(Callable const & callable,Node * context,Node * arg1,Node * arg2,Node * arg3,Node * arg4,Node * arg5,size_t result_size)739 Node* CodeAssembler::TailCallStub(Callable const& callable, Node* context,
740                                   Node* arg1, Node* arg2, Node* arg3,
741                                   Node* arg4, Node* arg5, size_t result_size) {
742   Node* target = HeapConstant(callable.code());
743   return TailCallStub(callable.descriptor(), target, context, arg1, arg2, arg3,
744                       arg4, arg5, result_size);
745 }
746 
TailCallStub(const CallInterfaceDescriptor & descriptor,Node * target,Node * context,Node * arg1,size_t result_size)747 Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
748                                   Node* target, Node* context, Node* arg1,
749                                   size_t result_size) {
750   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
751       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
752       CallDescriptor::kSupportsTailCalls, Operator::kNoProperties,
753       MachineType::AnyTagged(), result_size);
754 
755   Node** args = zone()->NewArray<Node*>(2);
756   args[0] = arg1;
757   args[1] = context;
758 
759   return raw_assembler_->TailCallN(call_descriptor, target, args);
760 }
761 
TailCallStub(const CallInterfaceDescriptor & descriptor,Node * target,Node * context,Node * arg1,Node * arg2,size_t result_size)762 Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
763                                   Node* target, Node* context, Node* arg1,
764                                   Node* arg2, size_t result_size) {
765   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
766       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
767       CallDescriptor::kSupportsTailCalls, Operator::kNoProperties,
768       MachineType::AnyTagged(), result_size);
769 
770   Node** args = zone()->NewArray<Node*>(3);
771   args[0] = arg1;
772   args[1] = arg2;
773   args[2] = context;
774 
775   return raw_assembler_->TailCallN(call_descriptor, target, args);
776 }
777 
TailCallStub(const CallInterfaceDescriptor & descriptor,Node * target,Node * context,Node * arg1,Node * arg2,Node * arg3,size_t result_size)778 Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
779                                   Node* target, Node* context, Node* arg1,
780                                   Node* arg2, Node* arg3, size_t result_size) {
781   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
782       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
783       CallDescriptor::kSupportsTailCalls, Operator::kNoProperties,
784       MachineType::AnyTagged(), result_size);
785 
786   Node** args = zone()->NewArray<Node*>(4);
787   args[0] = arg1;
788   args[1] = arg2;
789   args[2] = arg3;
790   args[3] = context;
791 
792   return raw_assembler_->TailCallN(call_descriptor, target, args);
793 }
794 
TailCallStub(const CallInterfaceDescriptor & descriptor,Node * target,Node * context,Node * arg1,Node * arg2,Node * arg3,Node * arg4,size_t result_size)795 Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
796                                   Node* target, Node* context, Node* arg1,
797                                   Node* arg2, Node* arg3, Node* arg4,
798                                   size_t result_size) {
799   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
800       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
801       CallDescriptor::kSupportsTailCalls, Operator::kNoProperties,
802       MachineType::AnyTagged(), result_size);
803 
804   Node** args = zone()->NewArray<Node*>(5);
805   args[0] = arg1;
806   args[1] = arg2;
807   args[2] = arg3;
808   args[3] = arg4;
809   args[4] = context;
810 
811   return raw_assembler_->TailCallN(call_descriptor, target, args);
812 }
813 
TailCallStub(const CallInterfaceDescriptor & descriptor,Node * target,Node * context,Node * arg1,Node * arg2,Node * arg3,Node * arg4,Node * arg5,size_t result_size)814 Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
815                                   Node* target, Node* context, Node* arg1,
816                                   Node* arg2, Node* arg3, Node* arg4,
817                                   Node* arg5, size_t result_size) {
818   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
819       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
820       CallDescriptor::kSupportsTailCalls, Operator::kNoProperties,
821       MachineType::AnyTagged(), result_size);
822 
823   Node** args = zone()->NewArray<Node*>(6);
824   args[0] = arg1;
825   args[1] = arg2;
826   args[2] = arg3;
827   args[3] = arg4;
828   args[4] = arg5;
829   args[5] = context;
830 
831   return raw_assembler_->TailCallN(call_descriptor, target, args);
832 }
833 
TailCallStub(const CallInterfaceDescriptor & descriptor,Node * target,Node * context,Node * arg1,Node * arg2,Node * arg3,Node * arg4,Node * arg5,Node * arg6,size_t result_size)834 Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
835                                   Node* target, Node* context, Node* arg1,
836                                   Node* arg2, Node* arg3, Node* arg4,
837                                   Node* arg5, Node* arg6, size_t result_size) {
838   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
839       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
840       CallDescriptor::kSupportsTailCalls, Operator::kNoProperties,
841       MachineType::AnyTagged(), result_size);
842 
843   Node** args = zone()->NewArray<Node*>(7);
844   args[0] = arg1;
845   args[1] = arg2;
846   args[2] = arg3;
847   args[3] = arg4;
848   args[4] = arg5;
849   args[5] = arg6;
850   args[6] = context;
851 
852   return raw_assembler_->TailCallN(call_descriptor, target, args);
853 }
854 
TailCallStub(const CallInterfaceDescriptor & descriptor,Node * target,Node * context,const Arg & arg1,const Arg & arg2,const Arg & arg3,const Arg & arg4,size_t result_size)855 Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
856                                   Node* target, Node* context, const Arg& arg1,
857                                   const Arg& arg2, const Arg& arg3,
858                                   const Arg& arg4, size_t result_size) {
859   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
860       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
861       CallDescriptor::kSupportsTailCalls, Operator::kNoProperties,
862       MachineType::AnyTagged(), result_size);
863 
864   const int kArgsCount = 5;
865   Node** args = zone()->NewArray<Node*>(kArgsCount);
866   DCHECK((std::fill(&args[0], &args[kArgsCount], nullptr), true));
867   args[arg1.index] = arg1.value;
868   args[arg2.index] = arg2.value;
869   args[arg3.index] = arg3.value;
870   args[arg4.index] = arg4.value;
871   args[kArgsCount - 1] = context;
872   DCHECK_EQ(0, std::count(&args[0], &args[kArgsCount], nullptr));
873 
874   return raw_assembler_->TailCallN(call_descriptor, target, args);
875 }
876 
TailCallStub(const CallInterfaceDescriptor & descriptor,Node * target,Node * context,const Arg & arg1,const Arg & arg2,const Arg & arg3,const Arg & arg4,const Arg & arg5,size_t result_size)877 Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
878                                   Node* target, Node* context, const Arg& arg1,
879                                   const Arg& arg2, const Arg& arg3,
880                                   const Arg& arg4, const Arg& arg5,
881                                   size_t result_size) {
882   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
883       isolate(), zone(), descriptor, descriptor.GetStackParameterCount(),
884       CallDescriptor::kSupportsTailCalls, Operator::kNoProperties,
885       MachineType::AnyTagged(), result_size);
886 
887   const int kArgsCount = 6;
888   Node** args = zone()->NewArray<Node*>(kArgsCount);
889   DCHECK((std::fill(&args[0], &args[kArgsCount], nullptr), true));
890   args[arg1.index] = arg1.value;
891   args[arg2.index] = arg2.value;
892   args[arg3.index] = arg3.value;
893   args[arg4.index] = arg4.value;
894   args[arg5.index] = arg5.value;
895   args[kArgsCount - 1] = context;
896   DCHECK_EQ(0, std::count(&args[0], &args[kArgsCount], nullptr));
897 
898   return raw_assembler_->TailCallN(call_descriptor, target, args);
899 }
900 
TailCallBytecodeDispatch(const CallInterfaceDescriptor & interface_descriptor,Node * code_target_address,Node ** args)901 Node* CodeAssembler::TailCallBytecodeDispatch(
902     const CallInterfaceDescriptor& interface_descriptor,
903     Node* code_target_address, Node** args) {
904   CallDescriptor* descriptor = Linkage::GetBytecodeDispatchCallDescriptor(
905       isolate(), zone(), interface_descriptor,
906       interface_descriptor.GetStackParameterCount());
907   return raw_assembler_->TailCallN(descriptor, code_target_address, args);
908 }
909 
CallJS(Callable const & callable,Node * context,Node * function,Node * receiver,size_t result_size)910 Node* CodeAssembler::CallJS(Callable const& callable, Node* context,
911                             Node* function, Node* receiver,
912                             size_t result_size) {
913   const int argc = 0;
914   Node* target = HeapConstant(callable.code());
915 
916   Node** args = zone()->NewArray<Node*>(argc + 4);
917   args[0] = function;
918   args[1] = Int32Constant(argc);
919   args[2] = receiver;
920   args[3] = context;
921 
922   return CallStubN(callable.descriptor(), argc + 1, target, args, result_size);
923 }
924 
CallJS(Callable const & callable,Node * context,Node * function,Node * receiver,Node * arg1,size_t result_size)925 Node* CodeAssembler::CallJS(Callable const& callable, Node* context,
926                             Node* function, Node* receiver, Node* arg1,
927                             size_t result_size) {
928   const int argc = 1;
929   Node* target = HeapConstant(callable.code());
930 
931   Node** args = zone()->NewArray<Node*>(argc + 4);
932   args[0] = function;
933   args[1] = Int32Constant(argc);
934   args[2] = receiver;
935   args[3] = arg1;
936   args[4] = context;
937 
938   return CallStubN(callable.descriptor(), argc + 1, target, args, result_size);
939 }
940 
CallJS(Callable const & callable,Node * context,Node * function,Node * receiver,Node * arg1,Node * arg2,size_t result_size)941 Node* CodeAssembler::CallJS(Callable const& callable, Node* context,
942                             Node* function, Node* receiver, Node* arg1,
943                             Node* arg2, size_t result_size) {
944   const int argc = 2;
945   Node* target = HeapConstant(callable.code());
946 
947   Node** args = zone()->NewArray<Node*>(argc + 4);
948   args[0] = function;
949   args[1] = Int32Constant(argc);
950   args[2] = receiver;
951   args[3] = arg1;
952   args[4] = arg2;
953   args[5] = context;
954 
955   return CallStubN(callable.descriptor(), argc + 1, target, args, result_size);
956 }
957 
CallJS(Callable const & callable,Node * context,Node * function,Node * receiver,Node * arg1,Node * arg2,Node * arg3,size_t result_size)958 Node* CodeAssembler::CallJS(Callable const& callable, Node* context,
959                             Node* function, Node* receiver, Node* arg1,
960                             Node* arg2, Node* arg3, size_t result_size) {
961   const int argc = 3;
962   Node* target = HeapConstant(callable.code());
963 
964   Node** args = zone()->NewArray<Node*>(argc + 4);
965   args[0] = function;
966   args[1] = Int32Constant(argc);
967   args[2] = receiver;
968   args[3] = arg1;
969   args[4] = arg2;
970   args[5] = arg3;
971   args[6] = context;
972 
973   return CallStubN(callable.descriptor(), argc + 1, target, args, result_size);
974 }
975 
CallCFunction2(MachineType return_type,MachineType arg0_type,MachineType arg1_type,Node * function,Node * arg0,Node * arg1)976 Node* CodeAssembler::CallCFunction2(MachineType return_type,
977                                     MachineType arg0_type,
978                                     MachineType arg1_type, Node* function,
979                                     Node* arg0, Node* arg1) {
980   return raw_assembler_->CallCFunction2(return_type, arg0_type, arg1_type,
981                                         function, arg0, arg1);
982 }
983 
Goto(CodeAssembler::Label * label)984 void CodeAssembler::Goto(CodeAssembler::Label* label) {
985   label->MergeVariables();
986   raw_assembler_->Goto(label->label_);
987 }
988 
GotoIf(Node * condition,Label * true_label)989 void CodeAssembler::GotoIf(Node* condition, Label* true_label) {
990   Label false_label(this);
991   Branch(condition, true_label, &false_label);
992   Bind(&false_label);
993 }
994 
GotoUnless(Node * condition,Label * false_label)995 void CodeAssembler::GotoUnless(Node* condition, Label* false_label) {
996   Label true_label(this);
997   Branch(condition, &true_label, false_label);
998   Bind(&true_label);
999 }
1000 
Branch(Node * condition,CodeAssembler::Label * true_label,CodeAssembler::Label * false_label)1001 void CodeAssembler::Branch(Node* condition, CodeAssembler::Label* true_label,
1002                            CodeAssembler::Label* false_label) {
1003   true_label->MergeVariables();
1004   false_label->MergeVariables();
1005   return raw_assembler_->Branch(condition, true_label->label_,
1006                                 false_label->label_);
1007 }
1008 
Switch(Node * index,Label * default_label,const int32_t * case_values,Label ** case_labels,size_t case_count)1009 void CodeAssembler::Switch(Node* index, Label* default_label,
1010                            const int32_t* case_values, Label** case_labels,
1011                            size_t case_count) {
1012   RawMachineLabel** labels =
1013       new (zone()->New(sizeof(RawMachineLabel*) * case_count))
1014           RawMachineLabel*[case_count];
1015   for (size_t i = 0; i < case_count; ++i) {
1016     labels[i] = case_labels[i]->label_;
1017     case_labels[i]->MergeVariables();
1018     default_label->MergeVariables();
1019   }
1020   return raw_assembler_->Switch(index, default_label->label_, case_values,
1021                                 labels, case_count);
1022 }
1023 
Select(Node * condition,Node * true_value,Node * false_value,MachineRepresentation rep)1024 Node* CodeAssembler::Select(Node* condition, Node* true_value,
1025                             Node* false_value, MachineRepresentation rep) {
1026   Variable value(this, rep);
1027   Label vtrue(this), vfalse(this), end(this);
1028   Branch(condition, &vtrue, &vfalse);
1029 
1030   Bind(&vtrue);
1031   {
1032     value.Bind(true_value);
1033     Goto(&end);
1034   }
1035   Bind(&vfalse);
1036   {
1037     value.Bind(false_value);
1038     Goto(&end);
1039   }
1040 
1041   Bind(&end);
1042   return value.value();
1043 }
1044 
1045 // RawMachineAssembler delegate helpers:
isolate() const1046 Isolate* CodeAssembler::isolate() const { return raw_assembler_->isolate(); }
1047 
factory() const1048 Factory* CodeAssembler::factory() const { return isolate()->factory(); }
1049 
zone() const1050 Zone* CodeAssembler::zone() const { return raw_assembler_->zone(); }
1051 
1052 // The core implementation of Variable is stored through an indirection so
1053 // that it can outlive the often block-scoped Variable declarations. This is
1054 // needed to ensure that variable binding and merging through phis can
1055 // properly be verified.
1056 class CodeAssembler::Variable::Impl : public ZoneObject {
1057  public:
Impl(MachineRepresentation rep)1058   explicit Impl(MachineRepresentation rep) : value_(nullptr), rep_(rep) {}
1059   Node* value_;
1060   MachineRepresentation rep_;
1061 };
1062 
Variable(CodeAssembler * assembler,MachineRepresentation rep)1063 CodeAssembler::Variable::Variable(CodeAssembler* assembler,
1064                                   MachineRepresentation rep)
1065     : impl_(new (assembler->zone()) Impl(rep)), assembler_(assembler) {
1066   assembler->variables_.insert(impl_);
1067 }
1068 
~Variable()1069 CodeAssembler::Variable::~Variable() { assembler_->variables_.erase(impl_); }
1070 
Bind(Node * value)1071 void CodeAssembler::Variable::Bind(Node* value) { impl_->value_ = value; }
1072 
value() const1073 Node* CodeAssembler::Variable::value() const {
1074   DCHECK_NOT_NULL(impl_->value_);
1075   return impl_->value_;
1076 }
1077 
rep() const1078 MachineRepresentation CodeAssembler::Variable::rep() const {
1079   return impl_->rep_;
1080 }
1081 
IsBound() const1082 bool CodeAssembler::Variable::IsBound() const {
1083   return impl_->value_ != nullptr;
1084 }
1085 
Label(CodeAssembler * assembler,size_t vars_count,Variable ** vars,CodeAssembler::Label::Type type)1086 CodeAssembler::Label::Label(CodeAssembler* assembler, size_t vars_count,
1087                             Variable** vars, CodeAssembler::Label::Type type)
1088     : bound_(false), merge_count_(0), assembler_(assembler), label_(nullptr) {
1089   void* buffer = assembler->zone()->New(sizeof(RawMachineLabel));
1090   label_ = new (buffer)
1091       RawMachineLabel(type == kDeferred ? RawMachineLabel::kDeferred
1092                                         : RawMachineLabel::kNonDeferred);
1093   for (size_t i = 0; i < vars_count; ++i) {
1094     variable_phis_[vars[i]->impl_] = nullptr;
1095   }
1096 }
1097 
MergeVariables()1098 void CodeAssembler::Label::MergeVariables() {
1099   ++merge_count_;
1100   for (auto var : assembler_->variables_) {
1101     size_t count = 0;
1102     Node* node = var->value_;
1103     if (node != nullptr) {
1104       auto i = variable_merges_.find(var);
1105       if (i != variable_merges_.end()) {
1106         i->second.push_back(node);
1107         count = i->second.size();
1108       } else {
1109         count = 1;
1110         variable_merges_[var] = std::vector<Node*>(1, node);
1111       }
1112     }
1113     // If the following asserts, then you've jumped to a label without a bound
1114     // variable along that path that expects to merge its value into a phi.
1115     DCHECK(variable_phis_.find(var) == variable_phis_.end() ||
1116            count == merge_count_);
1117     USE(count);
1118 
1119     // If the label is already bound, we already know the set of variables to
1120     // merge and phi nodes have already been created.
1121     if (bound_) {
1122       auto phi = variable_phis_.find(var);
1123       if (phi != variable_phis_.end()) {
1124         DCHECK_NOT_NULL(phi->second);
1125         assembler_->raw_assembler_->AppendPhiInput(phi->second, node);
1126       } else {
1127         auto i = variable_merges_.find(var);
1128         if (i != variable_merges_.end()) {
1129           // If the following assert fires, then you've declared a variable that
1130           // has the same bound value along all paths up until the point you
1131           // bound this label, but then later merged a path with a new value for
1132           // the variable after the label bind (it's not possible to add phis to
1133           // the bound label after the fact, just make sure to list the variable
1134           // in the label's constructor's list of merged variables).
1135           DCHECK(find_if(i->second.begin(), i->second.end(),
1136                          [node](Node* e) -> bool { return node != e; }) ==
1137                  i->second.end());
1138         }
1139       }
1140     }
1141   }
1142 }
1143 
Bind()1144 void CodeAssembler::Label::Bind() {
1145   DCHECK(!bound_);
1146   assembler_->raw_assembler_->Bind(label_);
1147 
1148   // Make sure that all variables that have changed along any path up to this
1149   // point are marked as merge variables.
1150   for (auto var : assembler_->variables_) {
1151     Node* shared_value = nullptr;
1152     auto i = variable_merges_.find(var);
1153     if (i != variable_merges_.end()) {
1154       for (auto value : i->second) {
1155         DCHECK(value != nullptr);
1156         if (value != shared_value) {
1157           if (shared_value == nullptr) {
1158             shared_value = value;
1159           } else {
1160             variable_phis_[var] = nullptr;
1161           }
1162         }
1163       }
1164     }
1165   }
1166 
1167   for (auto var : variable_phis_) {
1168     CodeAssembler::Variable::Impl* var_impl = var.first;
1169     auto i = variable_merges_.find(var_impl);
1170     // If the following assert fires, then a variable that has been marked as
1171     // being merged at the label--either by explicitly marking it so in the
1172     // label constructor or by having seen different bound values at branches
1173     // into the label--doesn't have a bound value along all of the paths that
1174     // have been merged into the label up to this point.
1175     DCHECK(i != variable_merges_.end() && i->second.size() == merge_count_);
1176     Node* phi = assembler_->raw_assembler_->Phi(
1177         var.first->rep_, static_cast<int>(merge_count_), &(i->second[0]));
1178     variable_phis_[var_impl] = phi;
1179   }
1180 
1181   // Bind all variables to a merge phi, the common value along all paths or
1182   // null.
1183   for (auto var : assembler_->variables_) {
1184     auto i = variable_phis_.find(var);
1185     if (i != variable_phis_.end()) {
1186       var->value_ = i->second;
1187     } else {
1188       auto j = variable_merges_.find(var);
1189       if (j != variable_merges_.end() && j->second.size() == merge_count_) {
1190         var->value_ = j->second.back();
1191       } else {
1192         var->value_ = nullptr;
1193       }
1194     }
1195   }
1196 
1197   bound_ = true;
1198 }
1199 
1200 }  // namespace compiler
1201 }  // namespace internal
1202 }  // namespace v8
1203