code = assembler.GenerateCode(); \ handler_table->set(static_cast(Bytecode::k##Name), *code); \ } BYTECODE_LIST(GENERATE_CODE) #undef GENERATE_CODE } } bool Interpreter::MakeBytecode(CompilationInfo* info) { BytecodeGenerator generator(info->isolate(), info->zone()); info->EnsureFeedbackVector(); Handle bytecodes = generator.MakeBytecode(info); if (FLAG_print_bytecode) { OFStream os(stdout); os << "Function: " << info->GetDebugName().get() << std::endl; bytecodes->Print(os); os << std::flush; } info->SetBytecodeArray(bytecodes); info->SetCode(info->isolate()->builtins()->InterpreterEntryTrampoline()); return true; } bool Interpreter::IsInterpreterTableInitialized( Handle handler_table) { DCHECK(handler_table->length() == static_cast(Bytecode::kLast) + 1); return handler_table->get(0) != isolate_->heap()->undefined_value(); } // LdaZero // // Load literal '0' into the accumulator. void Interpreter::DoLdaZero(compiler::InterpreterAssembler* assembler) { Node* zero_value = __ NumberConstant(0.0); __ SetAccumulator(zero_value); __ Dispatch(); } // LdaSmi8 // // Load an 8-bit integer literal into the accumulator as a Smi. void Interpreter::DoLdaSmi8(compiler::InterpreterAssembler* assembler) { Node* raw_int = __ BytecodeOperandImm(0); Node* smi_int = __ SmiTag(raw_int); __ SetAccumulator(smi_int); __ Dispatch(); } void Interpreter::DoLoadConstant(compiler::InterpreterAssembler* assembler) { Node* index = __ BytecodeOperandIdx(0); Node* constant = __ LoadConstantPoolEntry(index); __ SetAccumulator(constant); __ Dispatch(); } // LdaConstant // // Load constant literal at |idx| in the constant pool into the accumulator. void Interpreter::DoLdaConstant(compiler::InterpreterAssembler* assembler) { DoLoadConstant(assembler); } // LdaConstantWide // // Load constant literal at |idx| in the constant pool into the accumulator. void Interpreter::DoLdaConstantWide(compiler::InterpreterAssembler* assembler) { DoLoadConstant(assembler); } // LdaUndefined // // Load Undefined into the accumulator. void Interpreter::DoLdaUndefined(compiler::InterpreterAssembler* assembler) { Node* undefined_value = __ HeapConstant(isolate_->factory()->undefined_value()); __ SetAccumulator(undefined_value); __ Dispatch(); } // LdaNull // // Load Null into the accumulator. void Interpreter::DoLdaNull(compiler::InterpreterAssembler* assembler) { Node* null_value = __ HeapConstant(isolate_->factory()->null_value()); __ SetAccumulator(null_value); __ Dispatch(); } // LdaTheHole // // Load TheHole into the accumulator. void Interpreter::DoLdaTheHole(compiler::InterpreterAssembler* assembler) { Node* the_hole_value = __ HeapConstant(isolate_->factory()->the_hole_value()); __ SetAccumulator(the_hole_value); __ Dispatch(); } // LdaTrue // // Load True into the accumulator. void Interpreter::DoLdaTrue(compiler::InterpreterAssembler* assembler) { Node* true_value = __ HeapConstant(isolate_->factory()->true_value()); __ SetAccumulator(true_value); __ Dispatch(); } // LdaFalse // // Load False into the accumulator. void Interpreter::DoLdaFalse(compiler::InterpreterAssembler* assembler) { Node* false_value = __ HeapConstant(isolate_->factory()->false_value()); __ SetAccumulator(false_value); __ Dispatch(); } // Ldar // // Load accumulator with value from register . void Interpreter::DoLdar(compiler::InterpreterAssembler* assembler) { Node* reg_index = __ BytecodeOperandReg(0); Node* value = __ LoadRegister(reg_index); __ SetAccumulator(value); __ Dispatch(); } // Star // // Store accumulator to register . void Interpreter::DoStar(compiler::InterpreterAssembler* assembler) { Node* reg_index = __ BytecodeOperandReg(0); Node* accumulator = __ GetAccumulator(); __ StoreRegister(accumulator, reg_index); __ Dispatch(); } // Exchange // // Exchange two registers. void Interpreter::DoExchange(compiler::InterpreterAssembler* assembler) { Node* reg0_index = __ BytecodeOperandReg(0); Node* reg1_index = __ BytecodeOperandReg(1); Node* reg0_value = __ LoadRegister(reg0_index); Node* reg1_value = __ LoadRegister(reg1_index); __ StoreRegister(reg1_value, reg0_index); __ StoreRegister(reg0_value, reg1_index); __ Dispatch(); } // ExchangeWide // // Exchange two registers. void Interpreter::DoExchangeWide(compiler::InterpreterAssembler* assembler) { return DoExchange(assembler); } // Mov // // Stores the value of register to register . void Interpreter::DoMov(compiler::InterpreterAssembler* assembler) { Node* src_index = __ BytecodeOperandReg(0); Node* src_value = __ LoadRegister(src_index); Node* dst_index = __ BytecodeOperandReg(1); __ StoreRegister(src_value, dst_index); __ Dispatch(); } void Interpreter::DoLoadGlobal(Callable ic, compiler::InterpreterAssembler* assembler) { // Get the global object. Node* context = __ GetContext(); Node* native_context = __ LoadContextSlot(context, Context::NATIVE_CONTEXT_INDEX); Node* global = __ LoadContextSlot(native_context, Context::EXTENSION_INDEX); // Load the global via the LoadIC. Node* code_target = __ HeapConstant(ic.code()); Node* constant_index = __ BytecodeOperandIdx(0); Node* name = __ LoadConstantPoolEntry(constant_index); Node* raw_slot = __ BytecodeOperandIdx(1); Node* smi_slot = __ SmiTag(raw_slot); Node* type_feedback_vector = __ LoadTypeFeedbackVector(); Node* result = __ CallIC(ic.descriptor(), code_target, global, name, smi_slot, type_feedback_vector); __ SetAccumulator(result); __ Dispatch(); } // LdaGlobalSloppy // // Load the global with name in constant pool entry into the // accumulator using FeedBackVector slot in sloppy mode. void Interpreter::DoLdaGlobalSloppy(compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF, SLOPPY, UNINITIALIZED); DoLoadGlobal(ic, assembler); } // LdaGlobalSloppy // // Load the global with name in constant pool entry into the // accumulator using FeedBackVector slot in strict mode. void Interpreter::DoLdaGlobalStrict(compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF, STRICT, UNINITIALIZED); DoLoadGlobal(ic, assembler); } // LdaGlobalInsideTypeofSloppy // // Load the global with name in constant pool entry into the // accumulator using FeedBackVector slot in sloppy mode. void Interpreter::DoLdaGlobalInsideTypeofSloppy( compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, INSIDE_TYPEOF, SLOPPY, UNINITIALIZED); DoLoadGlobal(ic, assembler); } // LdaGlobalInsideTypeofStrict // // Load the global with name in constant pool entry into the // accumulator using FeedBackVector slot in strict mode. void Interpreter::DoLdaGlobalInsideTypeofStrict( compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, INSIDE_TYPEOF, STRICT, UNINITIALIZED); DoLoadGlobal(ic, assembler); } // LdaGlobalSloppyWide // // Load the global with name in constant pool entry into the // accumulator using FeedBackVector slot in sloppy mode. void Interpreter::DoLdaGlobalSloppyWide( compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF, SLOPPY, UNINITIALIZED); DoLoadGlobal(ic, assembler); } // LdaGlobalSloppyWide // // Load the global with name in constant pool entry into the // accumulator using FeedBackVector slot in strict mode. void Interpreter::DoLdaGlobalStrictWide( compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF, STRICT, UNINITIALIZED); DoLoadGlobal(ic, assembler); } // LdaGlobalInsideTypeofSloppyWide // // Load the global with name in constant pool entry into the // accumulator using FeedBackVector slot in sloppy mode. void Interpreter::DoLdaGlobalInsideTypeofSloppyWide( compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, INSIDE_TYPEOF, SLOPPY, UNINITIALIZED); DoLoadGlobal(ic, assembler); } // LdaGlobalInsideTypeofSloppyWide // // Load the global with name in constant pool entry into the // accumulator using FeedBackVector slot in strict mode. void Interpreter::DoLdaGlobalInsideTypeofStrictWide( compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, INSIDE_TYPEOF, STRICT, UNINITIALIZED); DoLoadGlobal(ic, assembler); } void Interpreter::DoStoreGlobal(Callable ic, compiler::InterpreterAssembler* assembler) { // Get the global object. Node* context = __ GetContext(); Node* native_context = __ LoadContextSlot(context, Context::NATIVE_CONTEXT_INDEX); Node* global = __ LoadContextSlot(native_context, Context::EXTENSION_INDEX); // Store the global via the StoreIC. Node* code_target = __ HeapConstant(ic.code()); Node* constant_index = __ BytecodeOperandIdx(0); Node* name = __ LoadConstantPoolEntry(constant_index); Node* value = __ GetAccumulator(); Node* raw_slot = __ BytecodeOperandIdx(1); Node* smi_slot = __ SmiTag(raw_slot); Node* type_feedback_vector = __ LoadTypeFeedbackVector(); __ CallIC(ic.descriptor(), code_target, global, name, value, smi_slot, type_feedback_vector); __ Dispatch(); } // StaGlobalSloppy // // Store the value in the accumulator into the global with name in constant pool // entry using FeedBackVector slot in sloppy mode. void Interpreter::DoStaGlobalSloppy(compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::StoreICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED); DoStoreGlobal(ic, assembler); } // StaGlobalStrict // // Store the value in the accumulator into the global with name in constant pool // entry using FeedBackVector slot in strict mode. void Interpreter::DoStaGlobalStrict(compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::StoreICInOptimizedCode(isolate_, STRICT, UNINITIALIZED); DoStoreGlobal(ic, assembler); } // StaGlobalSloppyWide // // Store the value in the accumulator into the global with name in constant pool // entry using FeedBackVector slot in sloppy mode. void Interpreter::DoStaGlobalSloppyWide( compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::StoreICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED); DoStoreGlobal(ic, assembler); } // StaGlobalStrictWide // // Store the value in the accumulator into the global with name in constant pool // entry using FeedBackVector slot in strict mode. void Interpreter::DoStaGlobalStrictWide( compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::StoreICInOptimizedCode(isolate_, STRICT, UNINITIALIZED); DoStoreGlobal(ic, assembler); } // LdaContextSlot // // Load the object in |slot_index| of |context| into the accumulator. void Interpreter::DoLdaContextSlot(compiler::InterpreterAssembler* assembler) { Node* reg_index = __ BytecodeOperandReg(0); Node* context = __ LoadRegister(reg_index); Node* slot_index = __ BytecodeOperandIdx(1); Node* result = __ LoadContextSlot(context, slot_index); __ SetAccumulator(result); __ Dispatch(); } // LdaContextSlotWide // // Load the object in |slot_index| of |context| into the accumulator. void Interpreter::DoLdaContextSlotWide( compiler::InterpreterAssembler* assembler) { DoLdaContextSlot(assembler); } // StaContextSlot // // Stores the object in the accumulator into |slot_index| of |context|. void Interpreter::DoStaContextSlot(compiler::InterpreterAssembler* assembler) { Node* value = __ GetAccumulator(); Node* reg_index = __ BytecodeOperandReg(0); Node* context = __ LoadRegister(reg_index); Node* slot_index = __ BytecodeOperandIdx(1); __ StoreContextSlot(context, slot_index, value); __ Dispatch(); } // StaContextSlot // // Stores the object in the accumulator into |slot_index| of |context|. void Interpreter::DoStaContextSlotWide( compiler::InterpreterAssembler* assembler) { DoStaContextSlot(assembler); } void Interpreter::DoLoadLookupSlot(Runtime::FunctionId function_id, compiler::InterpreterAssembler* assembler) { Node* index = __ BytecodeOperandIdx(0); Node* name = __ LoadConstantPoolEntry(index); Node* context = __ GetContext(); Node* result_pair = __ CallRuntime(function_id, context, name); Node* result = __ Projection(0, result_pair); __ SetAccumulator(result); __ Dispatch(); } // LdaLookupSlot // // Lookup the object with the name in constant pool entry |name_index| // dynamically. void Interpreter::DoLdaLookupSlot(compiler::InterpreterAssembler* assembler) { DoLoadLookupSlot(Runtime::kLoadLookupSlot, assembler); } // LdaLookupSlotInsideTypeof // // Lookup the object with the name in constant pool entry |name_index| // dynamically without causing a NoReferenceError. void Interpreter::DoLdaLookupSlotInsideTypeof( compiler::InterpreterAssembler* assembler) { DoLoadLookupSlot(Runtime::kLoadLookupSlotNoReferenceError, assembler); } // LdaLookupSlotWide // // Lookup the object with the name in constant pool entry |name_index| // dynamically. void Interpreter::DoLdaLookupSlotWide( compiler::InterpreterAssembler* assembler) { DoLdaLookupSlot(assembler); } // LdaLookupSlotInsideTypeofWide // // Lookup the object with the name in constant pool entry |name_index| // dynamically without causing a NoReferenceError. void Interpreter::DoLdaLookupSlotInsideTypeofWide( compiler::InterpreterAssembler* assembler) { DoLdaLookupSlotInsideTypeof(assembler); } void Interpreter::DoStoreLookupSlot(LanguageMode language_mode, compiler::InterpreterAssembler* assembler) { Node* value = __ GetAccumulator(); Node* index = __ BytecodeOperandIdx(0); Node* name = __ LoadConstantPoolEntry(index); Node* context = __ GetContext(); Node* language_mode_node = __ NumberConstant(language_mode); Node* result = __ CallRuntime(Runtime::kStoreLookupSlot, value, context, name, language_mode_node); __ SetAccumulator(result); __ Dispatch(); } // StaLookupSlotSloppy // // Store the object in accumulator to the object with the name in constant // pool entry |name_index| in sloppy mode. void Interpreter::DoStaLookupSlotSloppy( compiler::InterpreterAssembler* assembler) { DoStoreLookupSlot(LanguageMode::SLOPPY, assembler); } // StaLookupSlotStrict // // Store the object in accumulator to the object with the name in constant // pool entry |name_index| in strict mode. void Interpreter::DoStaLookupSlotStrict( compiler::InterpreterAssembler* assembler) { DoStoreLookupSlot(LanguageMode::STRICT, assembler); } // StaLookupSlotSloppyWide // // Store the object in accumulator to the object with the name in constant // pool entry |name_index| in sloppy mode. void Interpreter::DoStaLookupSlotSloppyWide( compiler::InterpreterAssembler* assembler) { DoStaLookupSlotSloppy(assembler); } // StaLookupSlotStrictWide // // Store the object in accumulator to the object with the name in constant // pool entry |name_index| in strict mode. void Interpreter::DoStaLookupSlotStrictWide( compiler::InterpreterAssembler* assembler) { DoStaLookupSlotStrict(assembler); } void Interpreter::DoLoadIC(Callable ic, compiler::InterpreterAssembler* assembler) { Node* code_target = __ HeapConstant(ic.code()); Node* register_index = __ BytecodeOperandReg(0); Node* object = __ LoadRegister(register_index); Node* constant_index = __ BytecodeOperandIdx(1); Node* name = __ LoadConstantPoolEntry(constant_index); Node* raw_slot = __ BytecodeOperandIdx(2); Node* smi_slot = __ SmiTag(raw_slot); Node* type_feedback_vector = __ LoadTypeFeedbackVector(); Node* result = __ CallIC(ic.descriptor(), code_target, object, name, smi_slot, type_feedback_vector); __ SetAccumulator(result); __ Dispatch(); } // LoadICSloppy // // Calls the sloppy mode LoadIC at FeedBackVector slot for and // the name at constant pool entry . void Interpreter::DoLoadICSloppy(compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF, SLOPPY, UNINITIALIZED); DoLoadIC(ic, assembler); } // LoadICStrict // // Calls the sloppy mode LoadIC at FeedBackVector slot for and // the name at constant pool entry . void Interpreter::DoLoadICStrict(compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF, STRICT, UNINITIALIZED); DoLoadIC(ic, assembler); } // LoadICSloppyWide // // Calls the sloppy mode LoadIC at FeedBackVector slot for and // the name at constant pool entry . void Interpreter::DoLoadICSloppyWide( compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF, SLOPPY, UNINITIALIZED); DoLoadIC(ic, assembler); } // LoadICStrictWide // // Calls the sloppy mode LoadIC at FeedBackVector slot for and // the name at constant pool entry . void Interpreter::DoLoadICStrictWide( compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF, STRICT, UNINITIALIZED); DoLoadIC(ic, assembler); } void Interpreter::DoKeyedLoadIC(Callable ic, compiler::InterpreterAssembler* assembler) { Node* code_target = __ HeapConstant(ic.code()); Node* reg_index = __ BytecodeOperandReg(0); Node* object = __ LoadRegister(reg_index); Node* name = __ GetAccumulator(); Node* raw_slot = __ BytecodeOperandIdx(1); Node* smi_slot = __ SmiTag(raw_slot); Node* type_feedback_vector = __ LoadTypeFeedbackVector(); Node* result = __ CallIC(ic.descriptor(), code_target, object, name, smi_slot, type_feedback_vector); __ SetAccumulator(result); __ Dispatch(); } // KeyedLoadICSloppy // // Calls the sloppy mode KeyedLoadIC at FeedBackVector slot for // and the key in the accumulator. void Interpreter::DoKeyedLoadICSloppy( compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED); DoKeyedLoadIC(ic, assembler); } // KeyedLoadICStrict // // Calls the strict mode KeyedLoadIC at FeedBackVector slot for // and the key in the accumulator. void Interpreter::DoKeyedLoadICStrict( compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate_, STRICT, UNINITIALIZED); DoKeyedLoadIC(ic, assembler); } // KeyedLoadICSloppyWide // // Calls the sloppy mode KeyedLoadIC at FeedBackVector slot for // and the key in the accumulator. void Interpreter::DoKeyedLoadICSloppyWide( compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED); DoKeyedLoadIC(ic, assembler); } // KeyedLoadICStrictWide // // Calls the strict mode KeyedLoadIC at FeedBackVector slot for // and the key in the accumulator. void Interpreter::DoKeyedLoadICStrictWide( compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate_, STRICT, UNINITIALIZED); DoKeyedLoadIC(ic, assembler); } void Interpreter::DoStoreIC(Callable ic, compiler::InterpreterAssembler* assembler) { Node* code_target = __ HeapConstant(ic.code()); Node* object_reg_index = __ BytecodeOperandReg(0); Node* object = __ LoadRegister(object_reg_index); Node* constant_index = __ BytecodeOperandIdx(1); Node* name = __ LoadConstantPoolEntry(constant_index); Node* value = __ GetAccumulator(); Node* raw_slot = __ BytecodeOperandIdx(2); Node* smi_slot = __ SmiTag(raw_slot); Node* type_feedback_vector = __ LoadTypeFeedbackVector(); __ CallIC(ic.descriptor(), code_target, object, name, value, smi_slot, type_feedback_vector); __ Dispatch(); } // StoreICSloppy // // Calls the sloppy mode StoreIC at FeedBackVector slot for and // the name in constant pool entry with the value in the // accumulator. void Interpreter::DoStoreICSloppy(compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::StoreICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED); DoStoreIC(ic, assembler); } // StoreICStrict // // Calls the strict mode StoreIC at FeedBackVector slot for and // the name in constant pool entry with the value in the // accumulator. void Interpreter::DoStoreICStrict(compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::StoreICInOptimizedCode(isolate_, STRICT, UNINITIALIZED); DoStoreIC(ic, assembler); } // StoreICSloppyWide // // Calls the sloppy mode StoreIC at FeedBackVector slot for and // the name in constant pool entry with the value in the // accumulator. void Interpreter::DoStoreICSloppyWide( compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::StoreICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED); DoStoreIC(ic, assembler); } // StoreICStrictWide // // Calls the strict mode StoreIC at FeedBackVector slot for and // the name in constant pool entry with the value in the // accumulator. void Interpreter::DoStoreICStrictWide( compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::StoreICInOptimizedCode(isolate_, STRICT, UNINITIALIZED); DoStoreIC(ic, assembler); } void Interpreter::DoKeyedStoreIC(Callable ic, compiler::InterpreterAssembler* assembler) { Node* code_target = __ HeapConstant(ic.code()); Node* object_reg_index = __ BytecodeOperandReg(0); Node* object = __ LoadRegister(object_reg_index); Node* name_reg_index = __ BytecodeOperandReg(1); Node* name = __ LoadRegister(name_reg_index); Node* value = __ GetAccumulator(); Node* raw_slot = __ BytecodeOperandIdx(2); Node* smi_slot = __ SmiTag(raw_slot); Node* type_feedback_vector = __ LoadTypeFeedbackVector(); __ CallIC(ic.descriptor(), code_target, object, name, value, smi_slot, type_feedback_vector); __ Dispatch(); } // KeyedStoreICSloppy // // Calls the sloppy mode KeyStoreIC at FeedBackVector slot for // and the key with the value in the accumulator. void Interpreter::DoKeyedStoreICSloppy( compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::KeyedStoreICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED); DoKeyedStoreIC(ic, assembler); } // KeyedStoreICStore // // Calls the strict mode KeyStoreIC at FeedBackVector slot for // and the key with the value in the accumulator. void Interpreter::DoKeyedStoreICStrict( compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::KeyedStoreICInOptimizedCode(isolate_, STRICT, UNINITIALIZED); DoKeyedStoreIC(ic, assembler); } // KeyedStoreICSloppyWide // // Calls the sloppy mode KeyStoreIC at FeedBackVector slot for // and the key with the value in the accumulator. void Interpreter::DoKeyedStoreICSloppyWide( compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::KeyedStoreICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED); DoKeyedStoreIC(ic, assembler); } // KeyedStoreICStoreWide // // Calls the strict mode KeyStoreIC at FeedBackVector slot for // and the key with the value in the accumulator. void Interpreter::DoKeyedStoreICStrictWide( compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::KeyedStoreICInOptimizedCode(isolate_, STRICT, UNINITIALIZED); DoKeyedStoreIC(ic, assembler); } // PushContext // // Pushes the accumulator as the current context, and saves it in void Interpreter::DoPushContext(compiler::InterpreterAssembler* assembler) { Node* reg_index = __ BytecodeOperandReg(0); Node* context = __ GetAccumulator(); __ SetContext(context); __ StoreRegister(context, reg_index); __ Dispatch(); } // PopContext // // Pops the current context and sets as the new context. void Interpreter::DoPopContext(compiler::InterpreterAssembler* assembler) { Node* reg_index = __ BytecodeOperandReg(0); Node* context = __ LoadRegister(reg_index); __ SetContext(context); __ Dispatch(); } void Interpreter::DoBinaryOp(Runtime::FunctionId function_id, compiler::InterpreterAssembler* assembler) { // TODO(rmcilroy): Call ICs which back-patch bytecode with type specialized // operations, instead of calling builtins directly. Node* reg_index = __ BytecodeOperandReg(0); Node* lhs = __ LoadRegister(reg_index); Node* rhs = __ GetAccumulator(); Node* result = __ CallRuntime(function_id, lhs, rhs); __ SetAccumulator(result); __ Dispatch(); } // Add // // Add register to accumulator. void Interpreter::DoAdd(compiler::InterpreterAssembler* assembler) { DoBinaryOp(Runtime::kAdd, assembler); } // Sub // // Subtract register from accumulator. void Interpreter::DoSub(compiler::InterpreterAssembler* assembler) { DoBinaryOp(Runtime::kSubtract, assembler); } // Mul // // Multiply accumulator by register . void Interpreter::DoMul(compiler::InterpreterAssembler* assembler) { DoBinaryOp(Runtime::kMultiply, assembler); } // Div // // Divide register by accumulator. void Interpreter::DoDiv(compiler::InterpreterAssembler* assembler) { DoBinaryOp(Runtime::kDivide, assembler); } // Mod // // Modulo register by accumulator. void Interpreter::DoMod(compiler::InterpreterAssembler* assembler) { DoBinaryOp(Runtime::kModulus, assembler); } // BitwiseOr // // BitwiseOr register to accumulator. void Interpreter::DoBitwiseOr(compiler::InterpreterAssembler* assembler) { DoBinaryOp(Runtime::kBitwiseOr, assembler); } // BitwiseXor // // BitwiseXor register to accumulator. void Interpreter::DoBitwiseXor(compiler::InterpreterAssembler* assembler) { DoBinaryOp(Runtime::kBitwiseXor, assembler); } // BitwiseAnd // // BitwiseAnd register to accumulator. void Interpreter::DoBitwiseAnd(compiler::InterpreterAssembler* assembler) { DoBinaryOp(Runtime::kBitwiseAnd, assembler); } // ShiftLeft // // Left shifts register by the count specified in the accumulator. // Register is converted to an int32 and the accumulator to uint32 // before the operation. 5 lsb bits from the accumulator are used as count // i.e. << (accumulator & 0x1F). void Interpreter::DoShiftLeft(compiler::InterpreterAssembler* assembler) { DoBinaryOp(Runtime::kShiftLeft, assembler); } // ShiftRight // // Right shifts register by the count specified in the accumulator. // Result is sign extended. Register is converted to an int32 and the // accumulator to uint32 before the operation. 5 lsb bits from the accumulator // are used as count i.e. >> (accumulator & 0x1F). void Interpreter::DoShiftRight(compiler::InterpreterAssembler* assembler) { DoBinaryOp(Runtime::kShiftRight, assembler); } // ShiftRightLogical // // Right Shifts register by the count specified in the accumulator. // Result is zero-filled. The accumulator and register are converted to // uint32 before the operation 5 lsb bits from the accumulator are used as // count i.e. << (accumulator & 0x1F). void Interpreter::DoShiftRightLogical( compiler::InterpreterAssembler* assembler) { DoBinaryOp(Runtime::kShiftRightLogical, assembler); } void Interpreter::DoCountOp(Runtime::FunctionId function_id, compiler::InterpreterAssembler* assembler) { Node* value = __ GetAccumulator(); Node* one = __ NumberConstant(1); Node* result = __ CallRuntime(function_id, value, one); __ SetAccumulator(result); __ Dispatch(); } // Inc // // Increments value in the accumulator by one. void Interpreter::DoInc(compiler::InterpreterAssembler* assembler) { DoCountOp(Runtime::kAdd, assembler); } // Dec // // Decrements value in the accumulator by one. void Interpreter::DoDec(compiler::InterpreterAssembler* assembler) { DoCountOp(Runtime::kSubtract, assembler); } // LogicalNot // // Perform logical-not on the accumulator, first casting the // accumulator to a boolean value if required. void Interpreter::DoLogicalNot(compiler::InterpreterAssembler* assembler) { Node* accumulator = __ GetAccumulator(); Node* result = __ CallRuntime(Runtime::kInterpreterLogicalNot, accumulator); __ SetAccumulator(result); __ Dispatch(); } // TypeOf // // Load the accumulator with the string representating type of the // object in the accumulator. void Interpreter::DoTypeOf(compiler::InterpreterAssembler* assembler) { Node* accumulator = __ GetAccumulator(); Node* result = __ CallRuntime(Runtime::kInterpreterTypeOf, accumulator); __ SetAccumulator(result); __ Dispatch(); } void Interpreter::DoDelete(Runtime::FunctionId function_id, compiler::InterpreterAssembler* assembler) { Node* reg_index = __ BytecodeOperandReg(0); Node* object = __ LoadRegister(reg_index); Node* key = __ GetAccumulator(); Node* result = __ CallRuntime(function_id, object, key); __ SetAccumulator(result); __ Dispatch(); } // DeletePropertyStrict // // Delete the property specified in the accumulator from the object // referenced by the register operand following strict mode semantics. void Interpreter::DoDeletePropertyStrict( compiler::InterpreterAssembler* assembler) { DoDelete(Runtime::kDeleteProperty_Strict, assembler); } // DeletePropertySloppy // // Delete the property specified in the accumulator from the object // referenced by the register operand following sloppy mode semantics. void Interpreter::DoDeletePropertySloppy( compiler::InterpreterAssembler* assembler) { DoDelete(Runtime::kDeleteProperty_Sloppy, assembler); } // DeleteLookupSlot // // Delete the variable with the name specified in the accumulator by dynamically // looking it up. void Interpreter::DoDeleteLookupSlot( compiler::InterpreterAssembler* assembler) { Node* name = __ GetAccumulator(); Node* context = __ GetContext(); Node* result = __ CallRuntime(Runtime::kDeleteLookupSlot, context, name); __ SetAccumulator(result); __ Dispatch(); } void Interpreter::DoJSCall(compiler::InterpreterAssembler* assembler) { Node* function_reg = __ BytecodeOperandReg(0); Node* function = __ LoadRegister(function_reg); Node* receiver_reg = __ BytecodeOperandReg(1); Node* first_arg = __ RegisterLocation(receiver_reg); Node* args_count = __ BytecodeOperandCount(2); // TODO(rmcilroy): Use the call type feedback slot to call via CallIC. Node* result = __ CallJS(function, first_arg, args_count); __ SetAccumulator(result); __ Dispatch(); } // Call // // Call a JSfunction or Callable in |callable| with the |receiver| and // |arg_count| arguments in subsequent registers. void Interpreter::DoCall(compiler::InterpreterAssembler* assembler) { DoJSCall(assembler); } // CallWide // // Call a JSfunction or Callable in |callable| with the |receiver| and // |arg_count| arguments in subsequent registers. void Interpreter::DoCallWide(compiler::InterpreterAssembler* assembler) { DoJSCall(assembler); } // CallRuntime // // Call the runtime function |function_id| with the first argument in // register |first_arg| and |arg_count| arguments in subsequent // registers. void Interpreter::DoCallRuntime(compiler::InterpreterAssembler* assembler) { Node* function_id = __ BytecodeOperandIdx(0); Node* first_arg_reg = __ BytecodeOperandReg(1); Node* first_arg = __ RegisterLocation(first_arg_reg); Node* args_count = __ BytecodeOperandCount(2); Node* result = __ CallRuntime(function_id, first_arg, args_count); __ SetAccumulator(result); __ Dispatch(); } // CallRuntimeForPair // // Call the runtime function |function_id| which returns a pair, with the // first argument in register |first_arg| and |arg_count| arguments in // subsequent registers. Returns the result in and // void Interpreter::DoCallRuntimeForPair( compiler::InterpreterAssembler* assembler) { // Call the runtime function. Node* function_id = __ BytecodeOperandIdx(0); Node* first_arg_reg = __ BytecodeOperandReg(1); Node* first_arg = __ RegisterLocation(first_arg_reg); Node* args_count = __ BytecodeOperandCount(2); Node* result_pair = __ CallRuntime(function_id, first_arg, args_count, 2); // Store the results in and Node* first_return_reg = __ BytecodeOperandReg(3); Node* second_return_reg = __ NextRegister(first_return_reg); Node* result0 = __ Projection(0, result_pair); Node* result1 = __ Projection(1, result_pair); __ StoreRegister(result0, first_return_reg); __ StoreRegister(result1, second_return_reg); __ Dispatch(); } // CallJSRuntime // // Call the JS runtime function that has the |context_index| with the receiver // in register |receiver| and |arg_count| arguments in subsequent registers. void Interpreter::DoCallJSRuntime(compiler::InterpreterAssembler* assembler) { Node* context_index = __ BytecodeOperandIdx(0); Node* receiver_reg = __ BytecodeOperandReg(1); Node* first_arg = __ RegisterLocation(receiver_reg); Node* args_count = __ BytecodeOperandCount(2); // Get the function to call from the native context. Node* context = __ GetContext(); Node* native_context = __ LoadContextSlot(context, Context::NATIVE_CONTEXT_INDEX); Node* function = __ LoadContextSlot(native_context, context_index); // Call the function. Node* result = __ CallJS(function, first_arg, args_count); __ SetAccumulator(result); __ Dispatch(); } // New // // Call operator new with |constructor| and the first argument in // register |first_arg| and |arg_count| arguments in subsequent // void Interpreter::DoNew(compiler::InterpreterAssembler* assembler) { Callable ic = CodeFactory::InterpreterPushArgsAndConstruct(isolate_); Node* constructor_reg = __ BytecodeOperandReg(0); Node* constructor = __ LoadRegister(constructor_reg); Node* first_arg_reg = __ BytecodeOperandReg(1); Node* first_arg = __ RegisterLocation(first_arg_reg); Node* args_count = __ BytecodeOperandCount(2); Node* result = __ CallConstruct(constructor, constructor, first_arg, args_count); __ SetAccumulator(result); __ Dispatch(); } // TestEqual // // Test if the value in the register equals the accumulator. void Interpreter::DoTestEqual(compiler::InterpreterAssembler* assembler) { DoBinaryOp(Runtime::kInterpreterEquals, assembler); } // TestNotEqual // // Test if the value in the register is not equal to the accumulator. void Interpreter::DoTestNotEqual(compiler::InterpreterAssembler* assembler) { DoBinaryOp(Runtime::kInterpreterNotEquals, assembler); } // TestEqualStrict // // Test if the value in the register is strictly equal to the accumulator. void Interpreter::DoTestEqualStrict(compiler::InterpreterAssembler* assembler) { DoBinaryOp(Runtime::kInterpreterStrictEquals, assembler); } // TestNotEqualStrict // // Test if the value in the register is not strictly equal to the // accumulator. void Interpreter::DoTestNotEqualStrict( compiler::InterpreterAssembler* assembler) { DoBinaryOp(Runtime::kInterpreterStrictNotEquals, assembler); } // TestLessThan // // Test if the value in the register is less than the accumulator. void Interpreter::DoTestLessThan(compiler::InterpreterAssembler* assembler) { DoBinaryOp(Runtime::kInterpreterLessThan, assembler); } // TestGreaterThan // // Test if the value in the register is greater than the accumulator. void Interpreter::DoTestGreaterThan(compiler::InterpreterAssembler* assembler) { DoBinaryOp(Runtime::kInterpreterGreaterThan, assembler); } // TestLessThanOrEqual // // Test if the value in the register is less than or equal to the // accumulator. void Interpreter::DoTestLessThanOrEqual( compiler::InterpreterAssembler* assembler) { DoBinaryOp(Runtime::kInterpreterLessThanOrEqual, assembler); } // TestGreaterThanOrEqual // // Test if the value in the register is greater than or equal to the // accumulator. void Interpreter::DoTestGreaterThanOrEqual( compiler::InterpreterAssembler* assembler) { DoBinaryOp(Runtime::kInterpreterGreaterThanOrEqual, assembler); } // TestIn // // Test if the object referenced by the register operand is a property of the // object referenced by the accumulator. void Interpreter::DoTestIn(compiler::InterpreterAssembler* assembler) { DoBinaryOp(Runtime::kHasProperty, assembler); } // TestInstanceOf // // Test if the object referenced by the register is an an instance of type // referenced by the accumulator. void Interpreter::DoTestInstanceOf(compiler::InterpreterAssembler* assembler) { DoBinaryOp(Runtime::kInstanceOf, assembler); } // ToName // // Cast the object referenced by the accumulator to a name. void Interpreter::DoToName(compiler::InterpreterAssembler* assembler) { Node* accumulator = __ GetAccumulator(); Node* result = __ CallRuntime(Runtime::kToName, accumulator); __ SetAccumulator(result); __ Dispatch(); } // ToNumber // // Cast the object referenced by the accumulator to a number. void Interpreter::DoToNumber(compiler::InterpreterAssembler* assembler) { Node* accumulator = __ GetAccumulator(); Node* result = __ CallRuntime(Runtime::kToNumber, accumulator); __ SetAccumulator(result); __ Dispatch(); } // ToObject // // Cast the object referenced by the accumulator to a JSObject. void Interpreter::DoToObject(compiler::InterpreterAssembler* assembler) { Node* accumulator = __ GetAccumulator(); Node* result = __ CallRuntime(Runtime::kToObject, accumulator); __ SetAccumulator(result); __ Dispatch(); } // Jump // // Jump by number of bytes represented by the immediate operand |imm8|. void Interpreter::DoJump(compiler::InterpreterAssembler* assembler) { Node* relative_jump = __ BytecodeOperandImm(0); __ Jump(relative_jump); } // JumpConstant // // Jump by number of bytes in the Smi in the |idx8| entry in the constant pool. void Interpreter::DoJumpConstant(compiler::InterpreterAssembler* assembler) { Node* index = __ BytecodeOperandIdx(0); Node* constant = __ LoadConstantPoolEntry(index); Node* relative_jump = __ SmiUntag(constant); __ Jump(relative_jump); } // JumpConstantWide // // Jump by number of bytes in the Smi in the |idx16| entry in the // constant pool. void Interpreter::DoJumpConstantWide( compiler::InterpreterAssembler* assembler) { DoJumpConstant(assembler); } // JumpIfTrue