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