Home | History | Annotate | Download | only in compiler
      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/interpreter-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/pipeline.h"
     14 #include "src/compiler/raw-machine-assembler.h"
     15 #include "src/compiler/schedule.h"
     16 #include "src/frames.h"
     17 #include "src/interface-descriptors.h"
     18 #include "src/interpreter/bytecodes.h"
     19 #include "src/machine-type.h"
     20 #include "src/macro-assembler.h"
     21 #include "src/zone.h"
     22 
     23 namespace v8 {
     24 namespace internal {
     25 namespace compiler {
     26 
     27 
     28 InterpreterAssembler::InterpreterAssembler(Isolate* isolate, Zone* zone,
     29                                            interpreter::Bytecode bytecode)
     30     : bytecode_(bytecode),
     31       raw_assembler_(new RawMachineAssembler(
     32           isolate, new (zone) Graph(zone),
     33           Linkage::GetInterpreterDispatchDescriptor(zone),
     34           MachineType::PointerRepresentation(),
     35           InstructionSelector::SupportedMachineOperatorFlags())),
     36       accumulator_(
     37           raw_assembler_->Parameter(Linkage::kInterpreterAccumulatorParameter)),
     38       bytecode_offset_(raw_assembler_->Parameter(
     39           Linkage::kInterpreterBytecodeOffsetParameter)),
     40       context_(
     41           raw_assembler_->Parameter(Linkage::kInterpreterContextParameter)),
     42       code_generated_(false) {}
     43 
     44 
     45 InterpreterAssembler::~InterpreterAssembler() {}
     46 
     47 
     48 Handle<Code> InterpreterAssembler::GenerateCode() {
     49   DCHECK(!code_generated_);
     50 
     51   // Disallow empty handlers that never return.
     52   DCHECK_NE(0, graph()->end()->InputCount());
     53 
     54   const char* bytecode_name = interpreter::Bytecodes::ToString(bytecode_);
     55   Schedule* schedule = raw_assembler_->Export();
     56   Handle<Code> code = Pipeline::GenerateCodeForCodeStub(
     57       isolate(), raw_assembler_->call_descriptor(), graph(), schedule,
     58       Code::STUB, bytecode_name);
     59 
     60 #ifdef ENABLE_DISASSEMBLER
     61   if (FLAG_trace_ignition_codegen) {
     62     OFStream os(stdout);
     63     code->Disassemble(bytecode_name, os);
     64     os << std::flush;
     65   }
     66 #endif
     67 
     68   code_generated_ = true;
     69   return code;
     70 }
     71 
     72 
     73 Node* InterpreterAssembler::GetAccumulator() { return accumulator_; }
     74 
     75 
     76 void InterpreterAssembler::SetAccumulator(Node* value) { accumulator_ = value; }
     77 
     78 
     79 Node* InterpreterAssembler::GetContext() { return context_; }
     80 
     81 
     82 void InterpreterAssembler::SetContext(Node* value) { context_ = value; }
     83 
     84 
     85 Node* InterpreterAssembler::BytecodeOffset() { return bytecode_offset_; }
     86 
     87 
     88 Node* InterpreterAssembler::RegisterFileRawPointer() {
     89   return raw_assembler_->Parameter(Linkage::kInterpreterRegisterFileParameter);
     90 }
     91 
     92 
     93 Node* InterpreterAssembler::BytecodeArrayTaggedPointer() {
     94   return raw_assembler_->Parameter(Linkage::kInterpreterBytecodeArrayParameter);
     95 }
     96 
     97 
     98 Node* InterpreterAssembler::DispatchTableRawPointer() {
     99   return raw_assembler_->Parameter(Linkage::kInterpreterDispatchTableParameter);
    100 }
    101 
    102 
    103 Node* InterpreterAssembler::RegisterLocation(Node* reg_index) {
    104   return IntPtrAdd(RegisterFileRawPointer(), RegisterFrameOffset(reg_index));
    105 }
    106 
    107 
    108 Node* InterpreterAssembler::LoadRegister(int offset) {
    109   return raw_assembler_->Load(MachineType::AnyTagged(),
    110                               RegisterFileRawPointer(), Int32Constant(offset));
    111 }
    112 
    113 
    114 Node* InterpreterAssembler::LoadRegister(interpreter::Register reg) {
    115   return LoadRegister(reg.ToOperand() << kPointerSizeLog2);
    116 }
    117 
    118 
    119 Node* InterpreterAssembler::RegisterFrameOffset(Node* index) {
    120   return WordShl(index, kPointerSizeLog2);
    121 }
    122 
    123 
    124 Node* InterpreterAssembler::LoadRegister(Node* reg_index) {
    125   return raw_assembler_->Load(MachineType::AnyTagged(),
    126                               RegisterFileRawPointer(),
    127                               RegisterFrameOffset(reg_index));
    128 }
    129 
    130 
    131 Node* InterpreterAssembler::StoreRegister(Node* value, int offset) {
    132   return raw_assembler_->Store(MachineRepresentation::kTagged,
    133                                RegisterFileRawPointer(), Int32Constant(offset),
    134                                value, kNoWriteBarrier);
    135 }
    136 
    137 
    138 Node* InterpreterAssembler::StoreRegister(Node* value,
    139                                           interpreter::Register reg) {
    140   return StoreRegister(value, reg.ToOperand() << kPointerSizeLog2);
    141 }
    142 
    143 
    144 Node* InterpreterAssembler::StoreRegister(Node* value, Node* reg_index) {
    145   return raw_assembler_->Store(
    146       MachineRepresentation::kTagged, RegisterFileRawPointer(),
    147       RegisterFrameOffset(reg_index), value, kNoWriteBarrier);
    148 }
    149 
    150 
    151 Node* InterpreterAssembler::NextRegister(Node* reg_index) {
    152   // Register indexes are negative, so the next index is minus one.
    153   return IntPtrAdd(reg_index, Int32Constant(-1));
    154 }
    155 
    156 
    157 Node* InterpreterAssembler::BytecodeOperand(int operand_index) {
    158   DCHECK_LT(operand_index, interpreter::Bytecodes::NumberOfOperands(bytecode_));
    159   DCHECK_EQ(interpreter::OperandSize::kByte,
    160             interpreter::Bytecodes::GetOperandSize(bytecode_, operand_index));
    161   return raw_assembler_->Load(
    162       MachineType::Uint8(), BytecodeArrayTaggedPointer(),
    163       IntPtrAdd(BytecodeOffset(),
    164                 Int32Constant(interpreter::Bytecodes::GetOperandOffset(
    165                     bytecode_, operand_index))));
    166 }
    167 
    168 
    169 Node* InterpreterAssembler::BytecodeOperandSignExtended(int operand_index) {
    170   DCHECK_LT(operand_index, interpreter::Bytecodes::NumberOfOperands(bytecode_));
    171   DCHECK_EQ(interpreter::OperandSize::kByte,
    172             interpreter::Bytecodes::GetOperandSize(bytecode_, operand_index));
    173   Node* load = raw_assembler_->Load(
    174       MachineType::Int8(), BytecodeArrayTaggedPointer(),
    175       IntPtrAdd(BytecodeOffset(),
    176                 Int32Constant(interpreter::Bytecodes::GetOperandOffset(
    177                     bytecode_, operand_index))));
    178   // Ensure that we sign extend to full pointer size
    179   if (kPointerSize == 8) {
    180     load = raw_assembler_->ChangeInt32ToInt64(load);
    181   }
    182   return load;
    183 }
    184 
    185 
    186 Node* InterpreterAssembler::BytecodeOperandShort(int operand_index) {
    187   DCHECK_LT(operand_index, interpreter::Bytecodes::NumberOfOperands(bytecode_));
    188   DCHECK_EQ(interpreter::OperandSize::kShort,
    189             interpreter::Bytecodes::GetOperandSize(bytecode_, operand_index));
    190   if (TargetSupportsUnalignedAccess()) {
    191     return raw_assembler_->Load(
    192         MachineType::Uint16(), BytecodeArrayTaggedPointer(),
    193         IntPtrAdd(BytecodeOffset(),
    194                   Int32Constant(interpreter::Bytecodes::GetOperandOffset(
    195                       bytecode_, operand_index))));
    196   } else {
    197     int offset =
    198         interpreter::Bytecodes::GetOperandOffset(bytecode_, operand_index);
    199     Node* first_byte = raw_assembler_->Load(
    200         MachineType::Uint8(), BytecodeArrayTaggedPointer(),
    201         IntPtrAdd(BytecodeOffset(), Int32Constant(offset)));
    202     Node* second_byte = raw_assembler_->Load(
    203         MachineType::Uint8(), BytecodeArrayTaggedPointer(),
    204         IntPtrAdd(BytecodeOffset(), Int32Constant(offset + 1)));
    205 #if V8_TARGET_LITTLE_ENDIAN
    206     return raw_assembler_->WordOr(WordShl(second_byte, kBitsPerByte),
    207                                   first_byte);
    208 #elif V8_TARGET_BIG_ENDIAN
    209     return raw_assembler_->WordOr(WordShl(first_byte, kBitsPerByte),
    210                                   second_byte);
    211 #else
    212 #error "Unknown Architecture"
    213 #endif
    214   }
    215 }
    216 
    217 
    218 Node* InterpreterAssembler::BytecodeOperandShortSignExtended(
    219     int operand_index) {
    220   DCHECK_LT(operand_index, interpreter::Bytecodes::NumberOfOperands(bytecode_));
    221   DCHECK_EQ(interpreter::OperandSize::kShort,
    222             interpreter::Bytecodes::GetOperandSize(bytecode_, operand_index));
    223   int operand_offset =
    224       interpreter::Bytecodes::GetOperandOffset(bytecode_, operand_index);
    225   Node* load;
    226   if (TargetSupportsUnalignedAccess()) {
    227     load = raw_assembler_->Load(
    228         MachineType::Int16(), BytecodeArrayTaggedPointer(),
    229         IntPtrAdd(BytecodeOffset(), Int32Constant(operand_offset)));
    230   } else {
    231 #if V8_TARGET_LITTLE_ENDIAN
    232     Node* hi_byte_offset = Int32Constant(operand_offset + 1);
    233     Node* lo_byte_offset = Int32Constant(operand_offset);
    234 #elif V8_TARGET_BIG_ENDIAN
    235     Node* hi_byte_offset = Int32Constant(operand_offset);
    236     Node* lo_byte_offset = Int32Constant(operand_offset + 1);
    237 #else
    238 #error "Unknown Architecture"
    239 #endif
    240     Node* hi_byte =
    241         raw_assembler_->Load(MachineType::Int8(), BytecodeArrayTaggedPointer(),
    242                              IntPtrAdd(BytecodeOffset(), hi_byte_offset));
    243     Node* lo_byte =
    244         raw_assembler_->Load(MachineType::Uint8(), BytecodeArrayTaggedPointer(),
    245                              IntPtrAdd(BytecodeOffset(), lo_byte_offset));
    246     hi_byte = raw_assembler_->Word32Shl(hi_byte, Int32Constant(kBitsPerByte));
    247     load = raw_assembler_->Word32Or(hi_byte, lo_byte);
    248   }
    249 
    250   // Ensure that we sign extend to full pointer size
    251   if (kPointerSize == 8) {
    252     load = raw_assembler_->ChangeInt32ToInt64(load);
    253   }
    254   return load;
    255 }
    256 
    257 
    258 Node* InterpreterAssembler::BytecodeOperandCount(int operand_index) {
    259   switch (interpreter::Bytecodes::GetOperandSize(bytecode_, operand_index)) {
    260     case interpreter::OperandSize::kByte:
    261       DCHECK_EQ(
    262           interpreter::OperandType::kCount8,
    263           interpreter::Bytecodes::GetOperandType(bytecode_, operand_index));
    264       return BytecodeOperand(operand_index);
    265     case interpreter::OperandSize::kShort:
    266       DCHECK_EQ(
    267           interpreter::OperandType::kCount16,
    268           interpreter::Bytecodes::GetOperandType(bytecode_, operand_index));
    269       return BytecodeOperandShort(operand_index);
    270     default:
    271       UNREACHABLE();
    272       return nullptr;
    273   }
    274 }
    275 
    276 
    277 Node* InterpreterAssembler::BytecodeOperandImm(int operand_index) {
    278   DCHECK_EQ(interpreter::OperandType::kImm8,
    279             interpreter::Bytecodes::GetOperandType(bytecode_, operand_index));
    280   return BytecodeOperandSignExtended(operand_index);
    281 }
    282 
    283 
    284 Node* InterpreterAssembler::BytecodeOperandIdx(int operand_index) {
    285   switch (interpreter::Bytecodes::GetOperandSize(bytecode_, operand_index)) {
    286     case interpreter::OperandSize::kByte:
    287       DCHECK_EQ(
    288           interpreter::OperandType::kIdx8,
    289           interpreter::Bytecodes::GetOperandType(bytecode_, operand_index));
    290       return BytecodeOperand(operand_index);
    291     case interpreter::OperandSize::kShort:
    292       DCHECK_EQ(
    293           interpreter::OperandType::kIdx16,
    294           interpreter::Bytecodes::GetOperandType(bytecode_, operand_index));
    295       return BytecodeOperandShort(operand_index);
    296     default:
    297       UNREACHABLE();
    298       return nullptr;
    299   }
    300 }
    301 
    302 
    303 Node* InterpreterAssembler::BytecodeOperandReg(int operand_index) {
    304   switch (interpreter::Bytecodes::GetOperandType(bytecode_, operand_index)) {
    305     case interpreter::OperandType::kReg8:
    306     case interpreter::OperandType::kRegPair8:
    307     case interpreter::OperandType::kMaybeReg8:
    308       DCHECK_EQ(
    309           interpreter::OperandSize::kByte,
    310           interpreter::Bytecodes::GetOperandSize(bytecode_, operand_index));
    311       return BytecodeOperandSignExtended(operand_index);
    312     case interpreter::OperandType::kReg16:
    313       DCHECK_EQ(
    314           interpreter::OperandSize::kShort,
    315           interpreter::Bytecodes::GetOperandSize(bytecode_, operand_index));
    316       return BytecodeOperandShortSignExtended(operand_index);
    317     default:
    318       UNREACHABLE();
    319       return nullptr;
    320   }
    321 }
    322 
    323 
    324 Node* InterpreterAssembler::Int32Constant(int value) {
    325   return raw_assembler_->Int32Constant(value);
    326 }
    327 
    328 
    329 Node* InterpreterAssembler::IntPtrConstant(intptr_t value) {
    330   return raw_assembler_->IntPtrConstant(value);
    331 }
    332 
    333 
    334 Node* InterpreterAssembler::NumberConstant(double value) {
    335   return raw_assembler_->NumberConstant(value);
    336 }
    337 
    338 
    339 Node* InterpreterAssembler::HeapConstant(Handle<HeapObject> object) {
    340   return raw_assembler_->HeapConstant(object);
    341 }
    342 
    343 
    344 Node* InterpreterAssembler::BooleanConstant(bool value) {
    345   return raw_assembler_->BooleanConstant(value);
    346 }
    347 
    348 
    349 Node* InterpreterAssembler::SmiShiftBitsConstant() {
    350   return Int32Constant(kSmiShiftSize + kSmiTagSize);
    351 }
    352 
    353 
    354 Node* InterpreterAssembler::SmiTag(Node* value) {
    355   return raw_assembler_->WordShl(value, SmiShiftBitsConstant());
    356 }
    357 
    358 
    359 Node* InterpreterAssembler::SmiUntag(Node* value) {
    360   return raw_assembler_->WordSar(value, SmiShiftBitsConstant());
    361 }
    362 
    363 
    364 Node* InterpreterAssembler::IntPtrAdd(Node* a, Node* b) {
    365   return raw_assembler_->IntPtrAdd(a, b);
    366 }
    367 
    368 
    369 Node* InterpreterAssembler::IntPtrSub(Node* a, Node* b) {
    370   return raw_assembler_->IntPtrSub(a, b);
    371 }
    372 
    373 
    374 Node* InterpreterAssembler::WordShl(Node* value, int shift) {
    375   return raw_assembler_->WordShl(value, Int32Constant(shift));
    376 }
    377 
    378 
    379 Node* InterpreterAssembler::LoadConstantPoolEntry(Node* index) {
    380   Node* constant_pool = LoadObjectField(BytecodeArrayTaggedPointer(),
    381                                         BytecodeArray::kConstantPoolOffset);
    382   Node* entry_offset =
    383       IntPtrAdd(IntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag),
    384                 WordShl(index, kPointerSizeLog2));
    385   return raw_assembler_->Load(MachineType::AnyTagged(), constant_pool,
    386                               entry_offset);
    387 }
    388 
    389 
    390 Node* InterpreterAssembler::LoadFixedArrayElement(Node* fixed_array,
    391                                                   int index) {
    392   Node* entry_offset =
    393       IntPtrAdd(IntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag),
    394                 WordShl(Int32Constant(index), kPointerSizeLog2));
    395   return raw_assembler_->Load(MachineType::AnyTagged(), fixed_array,
    396                               entry_offset);
    397 }
    398 
    399 
    400 Node* InterpreterAssembler::LoadObjectField(Node* object, int offset) {
    401   return raw_assembler_->Load(MachineType::AnyTagged(), object,
    402                               IntPtrConstant(offset - kHeapObjectTag));
    403 }
    404 
    405 
    406 Node* InterpreterAssembler::LoadContextSlot(Node* context, int slot_index) {
    407   return raw_assembler_->Load(MachineType::AnyTagged(), context,
    408                               IntPtrConstant(Context::SlotOffset(slot_index)));
    409 }
    410 
    411 
    412 Node* InterpreterAssembler::LoadContextSlot(Node* context, Node* slot_index) {
    413   Node* offset =
    414       IntPtrAdd(WordShl(slot_index, kPointerSizeLog2),
    415                 Int32Constant(Context::kHeaderSize - kHeapObjectTag));
    416   return raw_assembler_->Load(MachineType::AnyTagged(), context, offset);
    417 }
    418 
    419 
    420 Node* InterpreterAssembler::StoreContextSlot(Node* context, Node* slot_index,
    421                                              Node* value) {
    422   Node* offset =
    423       IntPtrAdd(WordShl(slot_index, kPointerSizeLog2),
    424                 Int32Constant(Context::kHeaderSize - kHeapObjectTag));
    425   return raw_assembler_->Store(MachineRepresentation::kTagged, context, offset,
    426                                value, kFullWriteBarrier);
    427 }
    428 
    429 
    430 Node* InterpreterAssembler::LoadTypeFeedbackVector() {
    431   Node* function = raw_assembler_->Load(
    432       MachineType::AnyTagged(), RegisterFileRawPointer(),
    433       IntPtrConstant(InterpreterFrameConstants::kFunctionFromRegisterPointer));
    434   Node* shared_info =
    435       LoadObjectField(function, JSFunction::kSharedFunctionInfoOffset);
    436   Node* vector =
    437       LoadObjectField(shared_info, SharedFunctionInfo::kFeedbackVectorOffset);
    438   return vector;
    439 }
    440 
    441 
    442 Node* InterpreterAssembler::Projection(int index, Node* node) {
    443   return raw_assembler_->Projection(index, node);
    444 }
    445 
    446 
    447 Node* InterpreterAssembler::CallConstruct(Node* new_target, Node* constructor,
    448                                           Node* first_arg, Node* arg_count) {
    449   Callable callable = CodeFactory::InterpreterPushArgsAndConstruct(isolate());
    450   CallDescriptor* descriptor = Linkage::GetStubCallDescriptor(
    451       isolate(), zone(), callable.descriptor(), 0, CallDescriptor::kNoFlags);
    452 
    453   Node* code_target = HeapConstant(callable.code());
    454 
    455   Node** args = zone()->NewArray<Node*>(5);
    456   args[0] = arg_count;
    457   args[1] = new_target;
    458   args[2] = constructor;
    459   args[3] = first_arg;
    460   args[4] = GetContext();
    461 
    462   return CallN(descriptor, code_target, args);
    463 }
    464 
    465 
    466 void InterpreterAssembler::CallPrologue() {
    467   StoreRegister(SmiTag(bytecode_offset_),
    468                 InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer);
    469 }
    470 
    471 
    472 void InterpreterAssembler::CallEpilogue() {
    473   // Restore the bytecode offset from the stack frame.
    474   bytecode_offset_ = SmiUntag(LoadRegister(
    475       InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer));
    476 }
    477 
    478 
    479 Node* InterpreterAssembler::CallN(CallDescriptor* descriptor, Node* code_target,
    480                                   Node** args) {
    481   CallPrologue();
    482 
    483   Node* stack_pointer_before_call = nullptr;
    484   if (FLAG_debug_code) {
    485     stack_pointer_before_call = raw_assembler_->LoadStackPointer();
    486   }
    487   Node* return_val = raw_assembler_->CallN(descriptor, code_target, args);
    488   if (FLAG_debug_code) {
    489     Node* stack_pointer_after_call = raw_assembler_->LoadStackPointer();
    490     AbortIfWordNotEqual(stack_pointer_before_call, stack_pointer_after_call,
    491                         kUnexpectedStackPointer);
    492   }
    493 
    494   CallEpilogue();
    495   return return_val;
    496 }
    497 
    498 
    499 Node* InterpreterAssembler::CallJS(Node* function, Node* first_arg,
    500                                    Node* arg_count) {
    501   Callable callable = CodeFactory::InterpreterPushArgsAndCall(isolate());
    502   CallDescriptor* descriptor = Linkage::GetStubCallDescriptor(
    503       isolate(), zone(), callable.descriptor(), 0, CallDescriptor::kNoFlags);
    504 
    505   Node* code_target = HeapConstant(callable.code());
    506 
    507   Node** args = zone()->NewArray<Node*>(4);
    508   args[0] = arg_count;
    509   args[1] = first_arg;
    510   args[2] = function;
    511   args[3] = GetContext();
    512 
    513   return CallN(descriptor, code_target, args);
    514 }
    515 
    516 
    517 Node* InterpreterAssembler::CallIC(CallInterfaceDescriptor descriptor,
    518                                    Node* target, Node** args) {
    519   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
    520       isolate(), zone(), descriptor, 0, CallDescriptor::kNoFlags);
    521   return CallN(call_descriptor, target, args);
    522 }
    523 
    524 
    525 Node* InterpreterAssembler::CallIC(CallInterfaceDescriptor descriptor,
    526                                    Node* target, Node* arg1, Node* arg2,
    527                                    Node* arg3) {
    528   Node** args = zone()->NewArray<Node*>(4);
    529   args[0] = arg1;
    530   args[1] = arg2;
    531   args[2] = arg3;
    532   args[3] = GetContext();
    533   return CallIC(descriptor, target, args);
    534 }
    535 
    536 
    537 Node* InterpreterAssembler::CallIC(CallInterfaceDescriptor descriptor,
    538                                    Node* target, Node* arg1, Node* arg2,
    539                                    Node* arg3, Node* arg4) {
    540   Node** args = zone()->NewArray<Node*>(5);
    541   args[0] = arg1;
    542   args[1] = arg2;
    543   args[2] = arg3;
    544   args[3] = arg4;
    545   args[4] = GetContext();
    546   return CallIC(descriptor, target, args);
    547 }
    548 
    549 
    550 Node* InterpreterAssembler::CallIC(CallInterfaceDescriptor descriptor,
    551                                    Node* target, Node* arg1, Node* arg2,
    552                                    Node* arg3, Node* arg4, Node* arg5) {
    553   Node** args = zone()->NewArray<Node*>(6);
    554   args[0] = arg1;
    555   args[1] = arg2;
    556   args[2] = arg3;
    557   args[3] = arg4;
    558   args[4] = arg5;
    559   args[5] = GetContext();
    560   return CallIC(descriptor, target, args);
    561 }
    562 
    563 
    564 Node* InterpreterAssembler::CallRuntime(Node* function_id, Node* first_arg,
    565                                         Node* arg_count, int result_size) {
    566   Callable callable = CodeFactory::InterpreterCEntry(isolate(), result_size);
    567   CallDescriptor* descriptor = Linkage::GetStubCallDescriptor(
    568       isolate(), zone(), callable.descriptor(), 0, CallDescriptor::kNoFlags,
    569       Operator::kNoProperties, MachineType::AnyTagged(), result_size);
    570   Node* code_target = HeapConstant(callable.code());
    571 
    572   // Get the function entry from the function id.
    573   Node* function_table = raw_assembler_->ExternalConstant(
    574       ExternalReference::runtime_function_table_address(isolate()));
    575   Node* function_offset = raw_assembler_->Int32Mul(
    576       function_id, Int32Constant(sizeof(Runtime::Function)));
    577   Node* function = IntPtrAdd(function_table, function_offset);
    578   Node* function_entry =
    579       raw_assembler_->Load(MachineType::Pointer(), function,
    580                            Int32Constant(offsetof(Runtime::Function, entry)));
    581 
    582   Node** args = zone()->NewArray<Node*>(4);
    583   args[0] = arg_count;
    584   args[1] = first_arg;
    585   args[2] = function_entry;
    586   args[3] = GetContext();
    587 
    588   return CallN(descriptor, code_target, args);
    589 }
    590 
    591 
    592 Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id,
    593                                         Node* arg1) {
    594   CallPrologue();
    595   Node* return_val =
    596       raw_assembler_->CallRuntime1(function_id, arg1, GetContext());
    597   CallEpilogue();
    598   return return_val;
    599 }
    600 
    601 
    602 Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id,
    603                                         Node* arg1, Node* arg2) {
    604   CallPrologue();
    605   Node* return_val =
    606       raw_assembler_->CallRuntime2(function_id, arg1, arg2, GetContext());
    607   CallEpilogue();
    608   return return_val;
    609 }
    610 
    611 
    612 Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id,
    613                                         Node* arg1, Node* arg2, Node* arg3,
    614                                         Node* arg4) {
    615   CallPrologue();
    616   Node* return_val = raw_assembler_->CallRuntime4(function_id, arg1, arg2, arg3,
    617                                                   arg4, GetContext());
    618   CallEpilogue();
    619   return return_val;
    620 }
    621 
    622 
    623 void InterpreterAssembler::Return() {
    624   Node* exit_trampoline_code_object =
    625       HeapConstant(isolate()->builtins()->InterpreterExitTrampoline());
    626   // If the order of the parameters you need to change the call signature below.
    627   STATIC_ASSERT(0 == Linkage::kInterpreterAccumulatorParameter);
    628   STATIC_ASSERT(1 == Linkage::kInterpreterRegisterFileParameter);
    629   STATIC_ASSERT(2 == Linkage::kInterpreterBytecodeOffsetParameter);
    630   STATIC_ASSERT(3 == Linkage::kInterpreterBytecodeArrayParameter);
    631   STATIC_ASSERT(4 == Linkage::kInterpreterDispatchTableParameter);
    632   STATIC_ASSERT(5 == Linkage::kInterpreterContextParameter);
    633   Node* args[] = { GetAccumulator(),
    634                    RegisterFileRawPointer(),
    635                    BytecodeOffset(),
    636                    BytecodeArrayTaggedPointer(),
    637                    DispatchTableRawPointer(),
    638                    GetContext() };
    639   raw_assembler_->TailCallN(call_descriptor(), exit_trampoline_code_object,
    640                             args);
    641 }
    642 
    643 
    644 Node* InterpreterAssembler::Advance(int delta) {
    645   return IntPtrAdd(BytecodeOffset(), Int32Constant(delta));
    646 }
    647 
    648 
    649 Node* InterpreterAssembler::Advance(Node* delta) {
    650   return raw_assembler_->IntPtrAdd(BytecodeOffset(), delta);
    651 }
    652 
    653 
    654 void InterpreterAssembler::Jump(Node* delta) { DispatchTo(Advance(delta)); }
    655 
    656 
    657 void InterpreterAssembler::JumpIfWordEqual(Node* lhs, Node* rhs, Node* delta) {
    658   RawMachineLabel match, no_match;
    659   Node* condition = raw_assembler_->WordEqual(lhs, rhs);
    660   raw_assembler_->Branch(condition, &match, &no_match);
    661   raw_assembler_->Bind(&match);
    662   DispatchTo(Advance(delta));
    663   raw_assembler_->Bind(&no_match);
    664   Dispatch();
    665 }
    666 
    667 
    668 void InterpreterAssembler::Dispatch() {
    669   DispatchTo(Advance(interpreter::Bytecodes::Size(bytecode_)));
    670 }
    671 
    672 
    673 void InterpreterAssembler::DispatchTo(Node* new_bytecode_offset) {
    674   Node* target_bytecode = raw_assembler_->Load(
    675       MachineType::Uint8(), BytecodeArrayTaggedPointer(), new_bytecode_offset);
    676 
    677   // TODO(rmcilroy): Create a code target dispatch table to avoid conversion
    678   // from code object on every dispatch.
    679   Node* target_code_object = raw_assembler_->Load(
    680       MachineType::Pointer(), DispatchTableRawPointer(),
    681       raw_assembler_->Word32Shl(target_bytecode,
    682                                 Int32Constant(kPointerSizeLog2)));
    683 
    684   // If the order of the parameters you need to change the call signature below.
    685   STATIC_ASSERT(0 == Linkage::kInterpreterAccumulatorParameter);
    686   STATIC_ASSERT(1 == Linkage::kInterpreterRegisterFileParameter);
    687   STATIC_ASSERT(2 == Linkage::kInterpreterBytecodeOffsetParameter);
    688   STATIC_ASSERT(3 == Linkage::kInterpreterBytecodeArrayParameter);
    689   STATIC_ASSERT(4 == Linkage::kInterpreterDispatchTableParameter);
    690   STATIC_ASSERT(5 == Linkage::kInterpreterContextParameter);
    691   Node* args[] = { GetAccumulator(),
    692                    RegisterFileRawPointer(),
    693                    new_bytecode_offset,
    694                    BytecodeArrayTaggedPointer(),
    695                    DispatchTableRawPointer(),
    696                    GetContext() };
    697   raw_assembler_->TailCallN(call_descriptor(), target_code_object, args);
    698 }
    699 
    700 
    701 void InterpreterAssembler::Abort(BailoutReason bailout_reason) {
    702   Node* abort_id = SmiTag(Int32Constant(bailout_reason));
    703   Node* ret_value = CallRuntime(Runtime::kAbort, abort_id);
    704   // Unreached, but keeps turbofan happy.
    705   raw_assembler_->Return(ret_value);
    706 }
    707 
    708 
    709 void InterpreterAssembler::AbortIfWordNotEqual(Node* lhs, Node* rhs,
    710                                                BailoutReason bailout_reason) {
    711   RawMachineLabel match, no_match;
    712   Node* condition = raw_assembler_->WordEqual(lhs, rhs);
    713   raw_assembler_->Branch(condition, &match, &no_match);
    714   raw_assembler_->Bind(&no_match);
    715   Abort(bailout_reason);
    716   raw_assembler_->Bind(&match);
    717 }
    718 
    719 
    720 // static
    721 bool InterpreterAssembler::TargetSupportsUnalignedAccess() {
    722 #if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
    723   return false;
    724 #elif V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_PPC
    725   return CpuFeatures::IsSupported(UNALIGNED_ACCESSES);
    726 #elif V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_X87
    727   return true;
    728 #else
    729 #error "Unknown Architecture"
    730 #endif
    731 }
    732 
    733 
    734 // RawMachineAssembler delegate helpers:
    735 Isolate* InterpreterAssembler::isolate() { return raw_assembler_->isolate(); }
    736 
    737 
    738 Graph* InterpreterAssembler::graph() { return raw_assembler_->graph(); }
    739 
    740 
    741 CallDescriptor* InterpreterAssembler::call_descriptor() const {
    742   return raw_assembler_->call_descriptor();
    743 }
    744 
    745 
    746 Zone* InterpreterAssembler::zone() { return raw_assembler_->zone(); }
    747 
    748 
    749 }  // namespace compiler
    750 }  // namespace internal
    751 }  // namespace v8
    752