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 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 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 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 64 CodeAssembler::~CodeAssembler() {} 65 66 void CodeAssembler::CallPrologue() {} 67 68 void CodeAssembler::CallEpilogue() {} 69 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 82 bool CodeAssembler::Is64() const { return raw_assembler_->machine()->Is64(); } 83 84 bool CodeAssembler::IsFloat64RoundUpSupported() const { 85 return raw_assembler_->machine()->Float64RoundUp().IsSupported(); 86 } 87 88 bool CodeAssembler::IsFloat64RoundDownSupported() const { 89 return raw_assembler_->machine()->Float64RoundDown().IsSupported(); 90 } 91 92 bool CodeAssembler::IsFloat64RoundTiesEvenSupported() const { 93 return raw_assembler_->machine()->Float64RoundTiesEven().IsSupported(); 94 } 95 96 bool CodeAssembler::IsFloat64RoundTruncateSupported() const { 97 return raw_assembler_->machine()->Float64RoundTruncate().IsSupported(); 98 } 99 100 Node* CodeAssembler::Int32Constant(int32_t value) { 101 return raw_assembler_->Int32Constant(value); 102 } 103 104 Node* CodeAssembler::Int64Constant(int64_t value) { 105 return raw_assembler_->Int64Constant(value); 106 } 107 108 Node* CodeAssembler::IntPtrConstant(intptr_t value) { 109 return raw_assembler_->IntPtrConstant(value); 110 } 111 112 Node* CodeAssembler::NumberConstant(double value) { 113 return raw_assembler_->NumberConstant(value); 114 } 115 116 Node* CodeAssembler::SmiConstant(Smi* value) { 117 return BitcastWordToTaggedSigned(IntPtrConstant(bit_cast<intptr_t>(value))); 118 } 119 120 Node* CodeAssembler::SmiConstant(int value) { 121 return SmiConstant(Smi::FromInt(value)); 122 } 123 124 Node* CodeAssembler::HeapConstant(Handle<HeapObject> object) { 125 return raw_assembler_->HeapConstant(object); 126 } 127 128 Node* CodeAssembler::BooleanConstant(bool value) { 129 return raw_assembler_->BooleanConstant(value); 130 } 131 132 Node* CodeAssembler::ExternalConstant(ExternalReference address) { 133 return raw_assembler_->ExternalConstant(address); 134 } 135 136 Node* CodeAssembler::Float64Constant(double value) { 137 return raw_assembler_->Float64Constant(value); 138 } 139 140 Node* CodeAssembler::NaNConstant() { 141 return LoadRoot(Heap::kNanValueRootIndex); 142 } 143 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 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 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 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 182 Node* CodeAssembler::Parameter(int value) { 183 return raw_assembler_->Parameter(value); 184 } 185 186 void CodeAssembler::Return(Node* value) { 187 return raw_assembler_->Return(value); 188 } 189 190 void CodeAssembler::PopAndReturn(Node* pop, Node* value) { 191 return raw_assembler_->PopAndReturn(pop, value); 192 } 193 194 void CodeAssembler::DebugBreak() { raw_assembler_->DebugBreak(); } 195 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 216 void CodeAssembler::Bind(CodeAssembler::Label* label) { return label->Bind(); } 217 218 Node* CodeAssembler::LoadFramePointer() { 219 return raw_assembler_->LoadFramePointer(); 220 } 221 222 Node* CodeAssembler::LoadParentFramePointer() { 223 return raw_assembler_->LoadParentFramePointer(); 224 } 225 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 } 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 242 Node* CodeAssembler::WordShr(Node* value, int shift) { 243 return (shift != 0) ? raw_assembler_->WordShr(value, IntPtrConstant(shift)) 244 : value; 245 } 246 247 Node* CodeAssembler::Word32Shr(Node* value, int shift) { 248 return (shift != 0) ? raw_assembler_->Word32Shr(value, Int32Constant(shift)) 249 : value; 250 } 251 252 Node* CodeAssembler::ChangeUint32ToWord(Node* value) { 253 if (raw_assembler_->machine()->Is64()) { 254 value = raw_assembler_->ChangeUint32ToUint64(value); 255 } 256 return value; 257 } 258 259 Node* CodeAssembler::ChangeInt32ToIntPtr(Node* value) { 260 if (raw_assembler_->machine()->Is64()) { 261 value = raw_assembler_->ChangeInt32ToInt64(value); 262 } 263 return value; 264 } 265 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); } 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 282 Node* CodeAssembler::Load(MachineType rep, Node* base, Node* index) { 283 return raw_assembler_->Load(rep, base, index); 284 } 285 286 Node* CodeAssembler::AtomicLoad(MachineType rep, Node* base, Node* index) { 287 return raw_assembler_->AtomicLoad(rep, base, index); 288 } 289 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 306 Node* CodeAssembler::Store(MachineRepresentation rep, Node* base, Node* value) { 307 return raw_assembler_->Store(rep, base, value, kFullWriteBarrier); 308 } 309 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 315 Node* CodeAssembler::StoreNoWriteBarrier(MachineRepresentation rep, Node* base, 316 Node* value) { 317 return raw_assembler_->Store(rep, base, value, kNoWriteBarrier); 318 } 319 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 325 Node* CodeAssembler::AtomicStore(MachineRepresentation rep, Node* base, 326 Node* index, Node* value) { 327 return raw_assembler_->AtomicStore(rep, base, index, value); 328 } 329 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 338 Node* CodeAssembler::Retain(Node* value) { 339 return raw_assembler_->Retain(value); 340 } 341 342 Node* CodeAssembler::Projection(int index, Node* value) { 343 return raw_assembler_->Projection(index, value); 344 } 345 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 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 374 Node* CodeAssembler::TailCallN(CallDescriptor* descriptor, Node* code_target, 375 Node** args) { 376 return raw_assembler_->TailCallN(descriptor, code_target, args); 377 } 378 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 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 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 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 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 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 433 Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id, 434 Node* context) { 435 return raw_assembler_->TailCallRuntime0(function_id, context); 436 } 437 438 Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id, 439 Node* context, Node* arg1) { 440 return raw_assembler_->TailCallRuntime1(function_id, arg1, context); 441 } 442 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 984 void CodeAssembler::Goto(CodeAssembler::Label* label) { 985 label->MergeVariables(); 986 raw_assembler_->Goto(label->label_); 987 } 988 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 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 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 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 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: 1046 Isolate* CodeAssembler::isolate() const { return raw_assembler_->isolate(); } 1047 1048 Factory* CodeAssembler::factory() const { return isolate()->factory(); } 1049 1050 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: 1058 explicit Impl(MachineRepresentation rep) : value_(nullptr), rep_(rep) {} 1059 Node* value_; 1060 MachineRepresentation rep_; 1061 }; 1062 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 1069 CodeAssembler::Variable::~Variable() { assembler_->variables_.erase(impl_); } 1070 1071 void CodeAssembler::Variable::Bind(Node* value) { impl_->value_ = value; } 1072 1073 Node* CodeAssembler::Variable::value() const { 1074 DCHECK_NOT_NULL(impl_->value_); 1075 return impl_->value_; 1076 } 1077 1078 MachineRepresentation CodeAssembler::Variable::rep() const { 1079 return impl_->rep_; 1080 } 1081 1082 bool CodeAssembler::Variable::IsBound() const { 1083 return impl_->value_ != nullptr; 1084 } 1085 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 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 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