diff options
Diffstat (limited to 'deps/v8/src/interpreter/interpreter.cc')
-rw-r--r-- | deps/v8/src/interpreter/interpreter.cc | 795 |
1 files changed, 287 insertions, 508 deletions
diff --git a/deps/v8/src/interpreter/interpreter.cc b/deps/v8/src/interpreter/interpreter.cc index eb883427bb..5084300dfe 100644 --- a/deps/v8/src/interpreter/interpreter.cc +++ b/deps/v8/src/interpreter/interpreter.cc @@ -11,6 +11,8 @@ #include "src/interpreter/bytecode-generator.h" #include "src/interpreter/bytecodes.h" #include "src/interpreter/interpreter-assembler.h" +#include "src/interpreter/interpreter-intrinsics.h" +#include "src/log.h" #include "src/zone.h" namespace v8 { @@ -22,30 +24,69 @@ using compiler::Node; #define __ assembler-> Interpreter::Interpreter(Isolate* isolate) : isolate_(isolate) { - memset(&dispatch_table_, 0, sizeof(dispatch_table_)); + memset(dispatch_table_, 0, sizeof(dispatch_table_)); } void Interpreter::Initialize() { DCHECK(FLAG_ignition); if (IsDispatchTableInitialized()) return; - Zone zone; + Zone zone(isolate_->allocator()); HandleScope scope(isolate_); -#define GENERATE_CODE(Name, ...) \ - { \ - InterpreterAssembler assembler(isolate_, &zone, Bytecode::k##Name); \ - Do##Name(&assembler); \ - Handle<Code> code = assembler.GenerateCode(); \ - TraceCodegen(code, #Name); \ - dispatch_table_[Bytecodes::ToByte(Bytecode::k##Name)] = *code; \ + // Generate bytecode handlers for all bytecodes and scales. + for (OperandScale operand_scale = OperandScale::kSingle; + operand_scale <= OperandScale::kMaxValid; + operand_scale = Bytecodes::NextOperandScale(operand_scale)) { +#define GENERATE_CODE(Name, ...) \ + { \ + if (Bytecodes::BytecodeHasHandler(Bytecode::k##Name, operand_scale)) { \ + InterpreterAssembler assembler(isolate_, &zone, Bytecode::k##Name, \ + operand_scale); \ + Do##Name(&assembler); \ + Handle<Code> code = assembler.GenerateCode(); \ + size_t index = GetDispatchTableIndex(Bytecode::k##Name, operand_scale); \ + dispatch_table_[index] = *code; \ + TraceCodegen(code); \ + LOG_CODE_EVENT( \ + isolate_, \ + CodeCreateEvent( \ + Logger::BYTECODE_HANDLER_TAG, AbstractCode::cast(*code), \ + Bytecodes::ToString(Bytecode::k##Name, operand_scale).c_str())); \ + } \ } - BYTECODE_LIST(GENERATE_CODE) + BYTECODE_LIST(GENERATE_CODE) #undef GENERATE_CODE + } + + // Fill unused entries will the illegal bytecode handler. + size_t illegal_index = + GetDispatchTableIndex(Bytecode::kIllegal, OperandScale::kSingle); + for (size_t index = 0; index < arraysize(dispatch_table_); ++index) { + if (dispatch_table_[index] == nullptr) { + dispatch_table_[index] = dispatch_table_[illegal_index]; + } + } } -Code* Interpreter::GetBytecodeHandler(Bytecode bytecode) { +Code* Interpreter::GetBytecodeHandler(Bytecode bytecode, + OperandScale operand_scale) { DCHECK(IsDispatchTableInitialized()); - return dispatch_table_[Bytecodes::ToByte(bytecode)]; + DCHECK(Bytecodes::BytecodeHasHandler(bytecode, operand_scale)); + size_t index = GetDispatchTableIndex(bytecode, operand_scale); + return dispatch_table_[index]; +} + +// static +size_t Interpreter::GetDispatchTableIndex(Bytecode bytecode, + OperandScale operand_scale) { + static const size_t kEntriesPerOperandScale = 1u << kBitsPerByte; + size_t index = static_cast<size_t>(bytecode); + OperandScale current_scale = OperandScale::kSingle; + while (current_scale != operand_scale) { + index += kEntriesPerOperandScale; + current_scale = Bytecodes::NextOperandScale(current_scale); + } + return index; } void Interpreter::IterateDispatchTable(ObjectVisitor* v) { @@ -62,6 +103,9 @@ int Interpreter::InterruptBudget() { } bool Interpreter::MakeBytecode(CompilationInfo* info) { + TimerEventScope<TimerEventCompileIgnition> timer(info->isolate()); + TRACE_EVENT0("v8", "V8.CompileIgnition"); + if (FLAG_print_bytecode || FLAG_print_source || FLAG_print_ast) { OFStream os(stdout); base::SmartArrayPointer<char> name = info->GetDebugName(); @@ -88,8 +132,10 @@ bool Interpreter::MakeBytecode(CompilationInfo* info) { #endif // DEBUG BytecodeGenerator generator(info->isolate(), info->zone()); - info->EnsureFeedbackVector(); Handle<BytecodeArray> bytecodes = generator.MakeBytecode(info); + + if (generator.HasStackOverflow()) return false; + if (FLAG_print_bytecode) { OFStream os(stdout); bytecodes->Print(os); @@ -102,23 +148,36 @@ bool Interpreter::MakeBytecode(CompilationInfo* info) { } bool Interpreter::IsDispatchTableInitialized() { - if (FLAG_trace_ignition) { - // Regenerate table to add bytecode tracing operations. + if (FLAG_trace_ignition || FLAG_trace_ignition_codegen) { + // Regenerate table to add bytecode tracing operations + // or to print the assembly code generated by TurboFan. return false; } return dispatch_table_[0] != nullptr; } -void Interpreter::TraceCodegen(Handle<Code> code, const char* name) { +void Interpreter::TraceCodegen(Handle<Code> code) { #ifdef ENABLE_DISASSEMBLER if (FLAG_trace_ignition_codegen) { OFStream os(stdout); - code->Disassemble(name, os); + code->Disassemble(nullptr, os); os << std::flush; } #endif // ENABLE_DISASSEMBLER } +const char* Interpreter::LookupNameOfBytecodeHandler(Code* code) { +#ifdef ENABLE_DISASSEMBLER +#define RETURN_NAME(Name, ...) \ + if (dispatch_table_[Bytecodes::ToByte(Bytecode::k##Name)] == code) { \ + return #Name; \ + } + BYTECODE_LIST(RETURN_NAME) +#undef RETURN_NAME +#endif // ENABLE_DISASSEMBLER + return nullptr; +} + // LdaZero // // Load literal '0' into the accumulator. @@ -128,11 +187,10 @@ void Interpreter::DoLdaZero(InterpreterAssembler* assembler) { __ Dispatch(); } - -// LdaSmi8 <imm8> +// LdaSmi <imm> // -// Load an 8-bit integer literal into the accumulator as a Smi. -void Interpreter::DoLdaSmi8(InterpreterAssembler* assembler) { +// Load an integer literal into the accumulator as a Smi. +void Interpreter::DoLdaSmi(InterpreterAssembler* assembler) { Node* raw_int = __ BytecodeOperandImm(0); Node* smi_int = __ SmiTag(raw_int); __ SetAccumulator(smi_int); @@ -154,15 +212,6 @@ void Interpreter::DoLdaConstant(InterpreterAssembler* assembler) { DoLoadConstant(assembler); } - -// LdaConstantWide <idx> -// -// Load constant literal at |idx| in the constant pool into the accumulator. -void Interpreter::DoLdaConstantWide(InterpreterAssembler* assembler) { - DoLoadConstant(assembler); -} - - // LdaUndefined // // Load Undefined into the accumulator. @@ -248,13 +297,6 @@ void Interpreter::DoMov(InterpreterAssembler* assembler) { } -// MovWide <src> <dst> -// -// Stores the value of register <src> to register <dst>. -void Interpreter::DoMovWide(InterpreterAssembler* assembler) { - DoMov(assembler); -} - void Interpreter::DoLoadGlobal(Callable ic, InterpreterAssembler* assembler) { // Get the global object. Node* context = __ GetContext(); @@ -295,27 +337,6 @@ void Interpreter::DoLdaGlobalInsideTypeof(InterpreterAssembler* assembler) { DoLoadGlobal(ic, assembler); } -// LdaGlobalWide <name_index> <slot> -// -// Load the global with name in constant pool entry <name_index> into the -// accumulator using FeedBackVector slot <slot> outside of a typeof. -void Interpreter::DoLdaGlobalWide(InterpreterAssembler* assembler) { - Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF, - UNINITIALIZED); - DoLoadGlobal(ic, assembler); -} - -// LdaGlobalInsideTypeofWide <name_index> <slot> -// -// Load the global with name in constant pool entry <name_index> into the -// accumulator using FeedBackVector slot <slot> inside of a typeof. -void Interpreter::DoLdaGlobalInsideTypeofWide(InterpreterAssembler* assembler) { - Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, INSIDE_TYPEOF, - UNINITIALIZED); - DoLoadGlobal(ic, assembler); -} - - void Interpreter::DoStoreGlobal(Callable ic, InterpreterAssembler* assembler) { // Get the global object. Node* context = __ GetContext(); @@ -333,7 +354,6 @@ void Interpreter::DoStoreGlobal(Callable ic, InterpreterAssembler* assembler) { Node* type_feedback_vector = __ LoadTypeFeedbackVector(); __ CallStub(ic.descriptor(), code_target, context, global, name, value, smi_slot, type_feedback_vector); - __ Dispatch(); } @@ -359,29 +379,6 @@ void Interpreter::DoStaGlobalStrict(InterpreterAssembler* assembler) { DoStoreGlobal(ic, assembler); } - -// StaGlobalSloppyWide <name_index> <slot> -// -// Store the value in the accumulator into the global with name in constant pool -// entry <name_index> using FeedBackVector slot <slot> in sloppy mode. -void Interpreter::DoStaGlobalSloppyWide(InterpreterAssembler* assembler) { - Callable ic = - CodeFactory::StoreICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED); - DoStoreGlobal(ic, assembler); -} - - -// StaGlobalStrictWide <name_index> <slot> -// -// Store the value in the accumulator into the global with name in constant pool -// entry <name_index> using FeedBackVector slot <slot> in strict mode. -void Interpreter::DoStaGlobalStrictWide(InterpreterAssembler* assembler) { - Callable ic = - CodeFactory::StoreICInOptimizedCode(isolate_, STRICT, UNINITIALIZED); - DoStoreGlobal(ic, assembler); -} - - // LdaContextSlot <context> <slot_index> // // Load the object in |slot_index| of |context| into the accumulator. @@ -394,15 +391,6 @@ void Interpreter::DoLdaContextSlot(InterpreterAssembler* assembler) { __ Dispatch(); } - -// LdaContextSlotWide <context> <slot_index> -// -// Load the object in |slot_index| of |context| into the accumulator. -void Interpreter::DoLdaContextSlotWide(InterpreterAssembler* assembler) { - DoLdaContextSlot(assembler); -} - - // StaContextSlot <context> <slot_index> // // Stores the object in the accumulator into |slot_index| of |context|. @@ -415,14 +403,6 @@ void Interpreter::DoStaContextSlot(InterpreterAssembler* assembler) { __ Dispatch(); } - -// StaContextSlot <context> <slot_index> -// -// Stores the object in the accumulator into |slot_index| of |context|. -void Interpreter::DoStaContextSlotWide(InterpreterAssembler* assembler) { - DoStaContextSlot(assembler); -} - void Interpreter::DoLoadLookupSlot(Runtime::FunctionId function_id, InterpreterAssembler* assembler) { Node* index = __ BytecodeOperandIdx(0); @@ -433,7 +413,6 @@ void Interpreter::DoLoadLookupSlot(Runtime::FunctionId function_id, __ Dispatch(); } - // LdaLookupSlot <name_index> // // Lookup the object with the name in constant pool entry |name_index| @@ -442,7 +421,6 @@ void Interpreter::DoLdaLookupSlot(InterpreterAssembler* assembler) { DoLoadLookupSlot(Runtime::kLoadLookupSlot, assembler); } - // LdaLookupSlotInsideTypeof <name_index> // // Lookup the object with the name in constant pool entry |name_index| @@ -451,25 +429,6 @@ void Interpreter::DoLdaLookupSlotInsideTypeof(InterpreterAssembler* assembler) { DoLoadLookupSlot(Runtime::kLoadLookupSlotInsideTypeof, assembler); } - -// LdaLookupSlotWide <name_index> -// -// Lookup the object with the name in constant pool entry |name_index| -// dynamically. -void Interpreter::DoLdaLookupSlotWide(InterpreterAssembler* assembler) { - DoLdaLookupSlot(assembler); -} - - -// LdaLookupSlotInsideTypeofWide <name_index> -// -// Lookup the object with the name in constant pool entry |name_index| -// dynamically without causing a NoReferenceError. -void Interpreter::DoLdaLookupSlotInsideTypeofWide( - InterpreterAssembler* assembler) { - DoLdaLookupSlotInsideTypeof(assembler); -} - void Interpreter::DoStoreLookupSlot(LanguageMode language_mode, InterpreterAssembler* assembler) { Node* value = __ GetAccumulator(); @@ -484,7 +443,6 @@ void Interpreter::DoStoreLookupSlot(LanguageMode language_mode, __ Dispatch(); } - // StaLookupSlotSloppy <name_index> // // Store the object in accumulator to the object with the name in constant @@ -502,24 +460,6 @@ void Interpreter::DoStaLookupSlotStrict(InterpreterAssembler* assembler) { DoStoreLookupSlot(LanguageMode::STRICT, assembler); } - -// StaLookupSlotSloppyWide <name_index> -// -// Store the object in accumulator to the object with the name in constant -// pool entry |name_index| in sloppy mode. -void Interpreter::DoStaLookupSlotSloppyWide(InterpreterAssembler* assembler) { - DoStaLookupSlotSloppy(assembler); -} - - -// StaLookupSlotStrictWide <name_index> -// -// Store the object in accumulator to the object with the name in constant -// pool entry |name_index| in strict mode. -void Interpreter::DoStaLookupSlotStrictWide(InterpreterAssembler* assembler) { - DoStaLookupSlotStrict(assembler); -} - void Interpreter::DoLoadIC(Callable ic, InterpreterAssembler* assembler) { Node* code_target = __ HeapConstant(ic.code()); Node* register_index = __ BytecodeOperandReg(0); @@ -546,17 +486,6 @@ void Interpreter::DoLoadIC(InterpreterAssembler* assembler) { DoLoadIC(ic, assembler); } -// LoadICWide <object> <name_index> <slot> -// -// Calls the LoadIC at FeedBackVector slot <slot> for <object> and the name at -// constant pool entry <name_index>. -void Interpreter::DoLoadICWide(InterpreterAssembler* assembler) { - Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF, - UNINITIALIZED); - DoLoadIC(ic, assembler); -} - - void Interpreter::DoKeyedLoadIC(Callable ic, InterpreterAssembler* assembler) { Node* code_target = __ HeapConstant(ic.code()); Node* reg_index = __ BytecodeOperandReg(0); @@ -582,17 +511,6 @@ void Interpreter::DoKeyedLoadIC(InterpreterAssembler* assembler) { DoKeyedLoadIC(ic, assembler); } -// KeyedLoadICWide <object> <slot> -// -// Calls the KeyedLoadIC at FeedBackVector slot <slot> for <object> and the key -// in the accumulator. -void Interpreter::DoKeyedLoadICWide(InterpreterAssembler* assembler) { - Callable ic = - CodeFactory::KeyedLoadICInOptimizedCode(isolate_, UNINITIALIZED); - DoKeyedLoadIC(ic, assembler); -} - - void Interpreter::DoStoreIC(Callable ic, InterpreterAssembler* assembler) { Node* code_target = __ HeapConstant(ic.code()); Node* object_reg_index = __ BytecodeOperandReg(0); @@ -633,30 +551,6 @@ void Interpreter::DoStoreICStrict(InterpreterAssembler* assembler) { DoStoreIC(ic, assembler); } - -// StoreICSloppyWide <object> <name_index> <slot> -// -// Calls the sloppy mode StoreIC at FeedBackVector slot <slot> for <object> and -// the name in constant pool entry <name_index> with the value in the -// accumulator. -void Interpreter::DoStoreICSloppyWide(InterpreterAssembler* assembler) { - Callable ic = - CodeFactory::StoreICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED); - DoStoreIC(ic, assembler); -} - - -// StoreICStrictWide <object> <name_index> <slot> -// -// Calls the strict mode StoreIC at FeedBackVector slot <slot> for <object> and -// the name in constant pool entry <name_index> with the value in the -// accumulator. -void Interpreter::DoStoreICStrictWide(InterpreterAssembler* assembler) { - Callable ic = - CodeFactory::StoreICInOptimizedCode(isolate_, STRICT, UNINITIALIZED); - DoStoreIC(ic, assembler); -} - void Interpreter::DoKeyedStoreIC(Callable ic, InterpreterAssembler* assembler) { Node* code_target = __ HeapConstant(ic.code()); Node* object_reg_index = __ BytecodeOperandReg(0); @@ -695,28 +589,6 @@ void Interpreter::DoKeyedStoreICStrict(InterpreterAssembler* assembler) { DoKeyedStoreIC(ic, assembler); } - -// KeyedStoreICSloppyWide <object> <key> <slot> -// -// Calls the sloppy mode KeyStoreIC at FeedBackVector slot <slot> for <object> -// and the key <key> with the value in the accumulator. -void Interpreter::DoKeyedStoreICSloppyWide(InterpreterAssembler* assembler) { - Callable ic = - CodeFactory::KeyedStoreICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED); - DoKeyedStoreIC(ic, assembler); -} - - -// KeyedStoreICStoreWide <object> <key> <slot> -// -// Calls the strict mode KeyStoreIC at FeedBackVector slot <slot> for <object> -// and the key <key> with the value in the accumulator. -void Interpreter::DoKeyedStoreICStrictWide(InterpreterAssembler* assembler) { - Callable ic = - CodeFactory::KeyedStoreICInOptimizedCode(isolate_, STRICT, UNINITIALIZED); - DoKeyedStoreIC(ic, assembler); -} - // PushContext <context> // // Saves the current context in <context>, and pushes the accumulator as the @@ -741,6 +613,20 @@ void Interpreter::DoPopContext(InterpreterAssembler* assembler) { __ Dispatch(); } +void Interpreter::DoBinaryOp(Callable callable, + InterpreterAssembler* assembler) { + // TODO(bmeurer): Collect definition side type feedback for various + // binary operations. + Node* target = __ HeapConstant(callable.code()); + Node* reg_index = __ BytecodeOperandReg(0); + Node* lhs = __ LoadRegister(reg_index); + Node* rhs = __ GetAccumulator(); + Node* context = __ GetContext(); + Node* result = __ CallStub(callable.descriptor(), target, context, lhs, rhs); + __ SetAccumulator(result); + __ Dispatch(); +} + void Interpreter::DoBinaryOp(Runtime::FunctionId function_id, InterpreterAssembler* assembler) { // TODO(rmcilroy): Call ICs which back-patch bytecode with type specialized @@ -759,7 +645,7 @@ void Interpreter::DoBinaryOp(Runtime::FunctionId function_id, // // Add register <src> to accumulator. void Interpreter::DoAdd(InterpreterAssembler* assembler) { - DoBinaryOp(Runtime::kAdd, assembler); + DoBinaryOp(CodeFactory::Add(isolate_), assembler); } @@ -767,7 +653,7 @@ void Interpreter::DoAdd(InterpreterAssembler* assembler) { // // Subtract register <src> from accumulator. void Interpreter::DoSub(InterpreterAssembler* assembler) { - DoBinaryOp(Runtime::kSubtract, assembler); + DoBinaryOp(CodeFactory::Subtract(isolate_), assembler); } @@ -799,7 +685,7 @@ void Interpreter::DoMod(InterpreterAssembler* assembler) { // // BitwiseOr register <src> to accumulator. void Interpreter::DoBitwiseOr(InterpreterAssembler* assembler) { - DoBinaryOp(Runtime::kBitwiseOr, assembler); + DoBinaryOp(CodeFactory::BitwiseOr(isolate_), assembler); } @@ -807,7 +693,7 @@ void Interpreter::DoBitwiseOr(InterpreterAssembler* assembler) { // // BitwiseXor register <src> to accumulator. void Interpreter::DoBitwiseXor(InterpreterAssembler* assembler) { - DoBinaryOp(Runtime::kBitwiseXor, assembler); + DoBinaryOp(CodeFactory::BitwiseXor(isolate_), assembler); } @@ -815,7 +701,7 @@ void Interpreter::DoBitwiseXor(InterpreterAssembler* assembler) { // // BitwiseAnd register <src> to accumulator. void Interpreter::DoBitwiseAnd(InterpreterAssembler* assembler) { - DoBinaryOp(Runtime::kBitwiseAnd, assembler); + DoBinaryOp(CodeFactory::BitwiseAnd(isolate_), assembler); } @@ -883,24 +769,40 @@ void Interpreter::DoDec(InterpreterAssembler* assembler) { // Perform logical-not on the accumulator, first casting the // accumulator to a boolean value if required. void Interpreter::DoLogicalNot(InterpreterAssembler* assembler) { + Callable callable = CodeFactory::ToBoolean(isolate_); + Node* target = __ HeapConstant(callable.code()); Node* accumulator = __ GetAccumulator(); Node* context = __ GetContext(); - Node* result = - __ CallRuntime(Runtime::kInterpreterLogicalNot, context, accumulator); - __ SetAccumulator(result); - __ Dispatch(); + Node* to_boolean_value = + __ CallStub(callable.descriptor(), target, context, accumulator); + InterpreterAssembler::Label if_true(assembler), if_false(assembler); + Node* true_value = __ BooleanConstant(true); + Node* false_value = __ BooleanConstant(false); + Node* condition = __ WordEqual(to_boolean_value, true_value); + __ Branch(condition, &if_true, &if_false); + __ Bind(&if_true); + { + __ SetAccumulator(false_value); + __ Dispatch(); + } + __ Bind(&if_false); + { + __ SetAccumulator(true_value); + __ Dispatch(); + } } - // TypeOf // // Load the accumulator with the string representating type of the // object in the accumulator. void Interpreter::DoTypeOf(InterpreterAssembler* assembler) { + Callable callable = CodeFactory::Typeof(isolate_); + Node* target = __ HeapConstant(callable.code()); Node* accumulator = __ GetAccumulator(); Node* context = __ GetContext(); Node* result = - __ CallRuntime(Runtime::kInterpreterTypeOf, context, accumulator); + __ CallStub(callable.descriptor(), target, context, accumulator); __ SetAccumulator(result); __ Dispatch(); } @@ -960,15 +862,6 @@ void Interpreter::DoCall(InterpreterAssembler* assembler) { DoJSCall(assembler, TailCallMode::kDisallow); } - -// CallWide <callable> <receiver> <arg_count> -// -// Call a JSfunction or Callable in |callable| with the |receiver| and -// |arg_count| arguments in subsequent registers. -void Interpreter::DoCallWide(InterpreterAssembler* assembler) { - DoJSCall(assembler, TailCallMode::kDisallow); -} - // TailCall <callable> <receiver> <arg_count> // // Tail call a JSfunction or Callable in |callable| with the |receiver| and @@ -977,16 +870,8 @@ void Interpreter::DoTailCall(InterpreterAssembler* assembler) { DoJSCall(assembler, TailCallMode::kAllow); } -// TailCallWide <callable> <receiver> <arg_count> -// -// Tail call a JSfunction or Callable in |callable| with the |receiver| and -// |arg_count| arguments in subsequent registers. -void Interpreter::DoTailCallWide(InterpreterAssembler* assembler) { - DoJSCall(assembler, TailCallMode::kAllow); -} - void Interpreter::DoCallRuntimeCommon(InterpreterAssembler* assembler) { - Node* function_id = __ BytecodeOperandIdx(0); + Node* function_id = __ BytecodeOperandRuntimeId(0); Node* first_arg_reg = __ BytecodeOperandReg(1); Node* first_arg = __ RegisterLocation(first_arg_reg); Node* args_count = __ BytecodeOperandCount(2); @@ -1006,19 +891,26 @@ void Interpreter::DoCallRuntime(InterpreterAssembler* assembler) { DoCallRuntimeCommon(assembler); } - -// CallRuntime <function_id> <first_arg> <arg_count> +// InvokeIntrinsic <function_id> <first_arg> <arg_count> // -// Call the runtime function |function_id| with the first argument in -// register |first_arg| and |arg_count| arguments in subsequent -// registers. -void Interpreter::DoCallRuntimeWide(InterpreterAssembler* assembler) { - DoCallRuntimeCommon(assembler); +// Implements the semantic equivalent of calling the runtime function +// |function_id| with the first argument in |first_arg| and |arg_count| +// arguments in subsequent registers. +void Interpreter::DoInvokeIntrinsic(InterpreterAssembler* assembler) { + Node* function_id = __ BytecodeOperandRuntimeId(0); + Node* first_arg_reg = __ BytecodeOperandReg(1); + Node* arg_count = __ BytecodeOperandCount(2); + Node* context = __ GetContext(); + IntrinsicsHelper helper(assembler); + Node* result = + helper.InvokeIntrinsic(function_id, context, first_arg_reg, arg_count); + __ SetAccumulator(result); + __ Dispatch(); } void Interpreter::DoCallRuntimeForPairCommon(InterpreterAssembler* assembler) { // Call the runtime function. - Node* function_id = __ BytecodeOperandIdx(0); + Node* function_id = __ BytecodeOperandRuntimeId(0); Node* first_arg_reg = __ BytecodeOperandReg(1); Node* first_arg = __ RegisterLocation(first_arg_reg); Node* args_count = __ BytecodeOperandCount(2); @@ -1047,17 +939,6 @@ void Interpreter::DoCallRuntimeForPair(InterpreterAssembler* assembler) { DoCallRuntimeForPairCommon(assembler); } - -// CallRuntimeForPairWide <function_id> <first_arg> <arg_count> <first_return> -// -// 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 <first_return> and -// <first_return + 1> -void Interpreter::DoCallRuntimeForPairWide(InterpreterAssembler* assembler) { - DoCallRuntimeForPairCommon(assembler); -} - void Interpreter::DoCallJSRuntimeCommon(InterpreterAssembler* assembler) { Node* context_index = __ BytecodeOperandIdx(0); Node* receiver_reg = __ BytecodeOperandReg(1); @@ -1088,15 +969,6 @@ void Interpreter::DoCallJSRuntime(InterpreterAssembler* assembler) { DoCallJSRuntimeCommon(assembler); } - -// CallJSRuntimeWide <context_index> <receiver> <arg_count> -// -// 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::DoCallJSRuntimeWide(InterpreterAssembler* assembler) { - DoCallJSRuntimeCommon(assembler); -} - void Interpreter::DoCallConstruct(InterpreterAssembler* assembler) { Callable ic = CodeFactory::InterpreterPushArgsAndConstruct(isolate_); Node* new_target = __ GetAccumulator(); @@ -1123,23 +995,11 @@ void Interpreter::DoNew(InterpreterAssembler* assembler) { DoCallConstruct(assembler); } - -// NewWide <constructor> <first_arg> <arg_count> -// -// Call operator new with |constructor| and the first argument in -// register |first_arg| and |arg_count| arguments in subsequent -// registers. The new.target is in the accumulator. -// -void Interpreter::DoNewWide(InterpreterAssembler* assembler) { - DoCallConstruct(assembler); -} - - // TestEqual <src> // // Test if the value in the <src> register equals the accumulator. void Interpreter::DoTestEqual(InterpreterAssembler* assembler) { - DoBinaryOp(Runtime::kEqual, assembler); + DoBinaryOp(CodeFactory::Equal(isolate_), assembler); } @@ -1147,7 +1007,7 @@ void Interpreter::DoTestEqual(InterpreterAssembler* assembler) { // // Test if the value in the <src> register is not equal to the accumulator. void Interpreter::DoTestNotEqual(InterpreterAssembler* assembler) { - DoBinaryOp(Runtime::kNotEqual, assembler); + DoBinaryOp(CodeFactory::NotEqual(isolate_), assembler); } @@ -1155,16 +1015,7 @@ void Interpreter::DoTestNotEqual(InterpreterAssembler* assembler) { // // Test if the value in the <src> register is strictly equal to the accumulator. void Interpreter::DoTestEqualStrict(InterpreterAssembler* assembler) { - DoBinaryOp(Runtime::kStrictEqual, assembler); -} - - -// TestNotEqualStrict <src> -// -// Test if the value in the <src> register is not strictly equal to the -// accumulator. -void Interpreter::DoTestNotEqualStrict(InterpreterAssembler* assembler) { - DoBinaryOp(Runtime::kStrictNotEqual, assembler); + DoBinaryOp(CodeFactory::StrictEqual(isolate_), assembler); } @@ -1172,7 +1023,7 @@ void Interpreter::DoTestNotEqualStrict(InterpreterAssembler* assembler) { // // Test if the value in the <src> register is less than the accumulator. void Interpreter::DoTestLessThan(InterpreterAssembler* assembler) { - DoBinaryOp(Runtime::kLessThan, assembler); + DoBinaryOp(CodeFactory::LessThan(isolate_), assembler); } @@ -1180,7 +1031,7 @@ void Interpreter::DoTestLessThan(InterpreterAssembler* assembler) { // // Test if the value in the <src> register is greater than the accumulator. void Interpreter::DoTestGreaterThan(InterpreterAssembler* assembler) { - DoBinaryOp(Runtime::kGreaterThan, assembler); + DoBinaryOp(CodeFactory::GreaterThan(isolate_), assembler); } @@ -1189,7 +1040,7 @@ void Interpreter::DoTestGreaterThan(InterpreterAssembler* assembler) { // Test if the value in the <src> register is less than or equal to the // accumulator. void Interpreter::DoTestLessThanOrEqual(InterpreterAssembler* assembler) { - DoBinaryOp(Runtime::kLessThanOrEqual, assembler); + DoBinaryOp(CodeFactory::LessThanOrEqual(isolate_), assembler); } @@ -1198,7 +1049,7 @@ void Interpreter::DoTestLessThanOrEqual(InterpreterAssembler* assembler) { // Test if the value in the <src> register is greater than or equal to the // accumulator. void Interpreter::DoTestGreaterThanOrEqual(InterpreterAssembler* assembler) { - DoBinaryOp(Runtime::kGreaterThanOrEqual, assembler); + DoBinaryOp(CodeFactory::GreaterThanOrEqual(isolate_), assembler); } @@ -1219,16 +1070,22 @@ void Interpreter::DoTestInstanceOf(InterpreterAssembler* assembler) { DoBinaryOp(Runtime::kInstanceOf, assembler); } +void Interpreter::DoTypeConversionOp(Callable callable, + InterpreterAssembler* assembler) { + Node* target = __ HeapConstant(callable.code()); + Node* accumulator = __ GetAccumulator(); + Node* context = __ GetContext(); + Node* result = + __ CallStub(callable.descriptor(), target, context, accumulator); + __ SetAccumulator(result); + __ Dispatch(); +} // ToName // // Cast the object referenced by the accumulator to a name. void Interpreter::DoToName(InterpreterAssembler* assembler) { - Node* accumulator = __ GetAccumulator(); - Node* context = __ GetContext(); - Node* result = __ CallRuntime(Runtime::kToName, context, accumulator); - __ SetAccumulator(result); - __ Dispatch(); + DoTypeConversionOp(CodeFactory::ToName(isolate_), assembler); } @@ -1236,11 +1093,7 @@ void Interpreter::DoToName(InterpreterAssembler* assembler) { // // Cast the object referenced by the accumulator to a number. void Interpreter::DoToNumber(InterpreterAssembler* assembler) { - Node* accumulator = __ GetAccumulator(); - Node* context = __ GetContext(); - Node* result = __ CallRuntime(Runtime::kToNumber, context, accumulator); - __ SetAccumulator(result); - __ Dispatch(); + DoTypeConversionOp(CodeFactory::ToNumber(isolate_), assembler); } @@ -1248,26 +1101,20 @@ void Interpreter::DoToNumber(InterpreterAssembler* assembler) { // // Cast the object referenced by the accumulator to a JSObject. void Interpreter::DoToObject(InterpreterAssembler* assembler) { - Node* accumulator = __ GetAccumulator(); - Node* context = __ GetContext(); - Node* result = __ CallRuntime(Runtime::kToObject, context, accumulator); - __ SetAccumulator(result); - __ Dispatch(); + DoTypeConversionOp(CodeFactory::ToObject(isolate_), assembler); } - -// Jump <imm8> +// Jump <imm> // -// Jump by number of bytes represented by the immediate operand |imm8|. +// Jump by number of bytes represented by the immediate operand |imm|. void Interpreter::DoJump(InterpreterAssembler* assembler) { Node* relative_jump = __ BytecodeOperandImm(0); __ Jump(relative_jump); } - -// JumpConstant <idx8> +// JumpConstant <idx> // -// Jump by number of bytes in the Smi in the |idx8| entry in the constant pool. +// Jump by number of bytes in the Smi in the |idx| entry in the constant pool. void Interpreter::DoJumpConstant(InterpreterAssembler* assembler) { Node* index = __ BytecodeOperandIdx(0); Node* constant = __ LoadConstantPoolEntry(index); @@ -1275,17 +1122,7 @@ void Interpreter::DoJumpConstant(InterpreterAssembler* assembler) { __ Jump(relative_jump); } - -// JumpConstantWide <idx16> -// -// Jump by number of bytes in the Smi in the |idx16| entry in the -// constant pool. -void Interpreter::DoJumpConstantWide(InterpreterAssembler* assembler) { - DoJumpConstant(assembler); -} - - -// JumpIfTrue <imm8> +// JumpIfTrue <imm> // // Jump by number of bytes represented by an immediate operand if the // accumulator contains true. @@ -1296,10 +1133,9 @@ void Interpreter::DoJumpIfTrue(InterpreterAssembler* assembler) { __ JumpIfWordEqual(accumulator, true_value, relative_jump); } - -// JumpIfTrueConstant <idx8> +// JumpIfTrueConstant <idx> // -// Jump by number of bytes in the Smi in the |idx8| entry in the constant pool +// Jump by number of bytes in the Smi in the |idx| entry in the constant pool // if the accumulator contains true. void Interpreter::DoJumpIfTrueConstant(InterpreterAssembler* assembler) { Node* accumulator = __ GetAccumulator(); @@ -1310,17 +1146,7 @@ void Interpreter::DoJumpIfTrueConstant(InterpreterAssembler* assembler) { __ JumpIfWordEqual(accumulator, true_value, relative_jump); } - -// JumpIfTrueConstantWide <idx16> -// -// Jump by number of bytes in the Smi in the |idx16| entry in the constant pool -// if the accumulator contains true. -void Interpreter::DoJumpIfTrueConstantWide(InterpreterAssembler* assembler) { - DoJumpIfTrueConstant(assembler); -} - - -// JumpIfFalse <imm8> +// JumpIfFalse <imm> // // Jump by number of bytes represented by an immediate operand if the // accumulator contains false. @@ -1331,10 +1157,9 @@ void Interpreter::DoJumpIfFalse(InterpreterAssembler* assembler) { __ JumpIfWordEqual(accumulator, false_value, relative_jump); } - -// JumpIfFalseConstant <idx8> +// JumpIfFalseConstant <idx> // -// Jump by number of bytes in the Smi in the |idx8| entry in the constant pool +// Jump by number of bytes in the Smi in the |idx| entry in the constant pool // if the accumulator contains false. void Interpreter::DoJumpIfFalseConstant(InterpreterAssembler* assembler) { Node* accumulator = __ GetAccumulator(); @@ -1345,42 +1170,35 @@ void Interpreter::DoJumpIfFalseConstant(InterpreterAssembler* assembler) { __ JumpIfWordEqual(accumulator, false_value, relative_jump); } - -// JumpIfFalseConstant <idx16> -// -// Jump by number of bytes in the Smi in the |idx16| entry in the constant pool -// if the accumulator contains false. -void Interpreter::DoJumpIfFalseConstantWide(InterpreterAssembler* assembler) { - DoJumpIfFalseConstant(assembler); -} - - -// JumpIfToBooleanTrue <imm8> +// JumpIfToBooleanTrue <imm> // // Jump by number of bytes represented by an immediate operand if the object // referenced by the accumulator is true when the object is cast to boolean. void Interpreter::DoJumpIfToBooleanTrue(InterpreterAssembler* assembler) { + Callable callable = CodeFactory::ToBoolean(isolate_); + Node* target = __ HeapConstant(callable.code()); Node* accumulator = __ GetAccumulator(); Node* context = __ GetContext(); Node* to_boolean_value = - __ CallRuntime(Runtime::kInterpreterToBoolean, context, accumulator); + __ CallStub(callable.descriptor(), target, context, accumulator); Node* relative_jump = __ BytecodeOperandImm(0); Node* true_value = __ BooleanConstant(true); __ JumpIfWordEqual(to_boolean_value, true_value, relative_jump); } - -// JumpIfToBooleanTrueConstant <idx8> +// JumpIfToBooleanTrueConstant <idx> // -// Jump by number of bytes in the Smi in the |idx8| entry in the constant pool +// Jump by number of bytes in the Smi in the |idx| entry in the constant pool // if the object referenced by the accumulator is true when the object is cast // to boolean. void Interpreter::DoJumpIfToBooleanTrueConstant( InterpreterAssembler* assembler) { + Callable callable = CodeFactory::ToBoolean(isolate_); + Node* target = __ HeapConstant(callable.code()); Node* accumulator = __ GetAccumulator(); Node* context = __ GetContext(); Node* to_boolean_value = - __ CallRuntime(Runtime::kInterpreterToBoolean, context, accumulator); + __ CallStub(callable.descriptor(), target, context, accumulator); Node* index = __ BytecodeOperandIdx(0); Node* constant = __ LoadConstantPoolEntry(index); Node* relative_jump = __ SmiUntag(constant); @@ -1388,44 +1206,35 @@ void Interpreter::DoJumpIfToBooleanTrueConstant( __ JumpIfWordEqual(to_boolean_value, true_value, relative_jump); } - -// JumpIfToBooleanTrueConstantWide <idx16> -// -// Jump by number of bytes in the Smi in the |idx16| entry in the constant pool -// if the object referenced by the accumulator is true when the object is cast -// to boolean. -void Interpreter::DoJumpIfToBooleanTrueConstantWide( - InterpreterAssembler* assembler) { - DoJumpIfToBooleanTrueConstant(assembler); -} - - -// JumpIfToBooleanFalse <imm8> +// JumpIfToBooleanFalse <imm> // // Jump by number of bytes represented by an immediate operand if the object // referenced by the accumulator is false when the object is cast to boolean. void Interpreter::DoJumpIfToBooleanFalse(InterpreterAssembler* assembler) { + Callable callable = CodeFactory::ToBoolean(isolate_); + Node* target = __ HeapConstant(callable.code()); Node* accumulator = __ GetAccumulator(); Node* context = __ GetContext(); Node* to_boolean_value = - __ CallRuntime(Runtime::kInterpreterToBoolean, context, accumulator); + __ CallStub(callable.descriptor(), target, context, accumulator); Node* relative_jump = __ BytecodeOperandImm(0); Node* false_value = __ BooleanConstant(false); __ JumpIfWordEqual(to_boolean_value, false_value, relative_jump); } - -// JumpIfToBooleanFalseConstant <idx8> +// JumpIfToBooleanFalseConstant <idx> // -// Jump by number of bytes in the Smi in the |idx8| entry in the constant pool +// Jump by number of bytes in the Smi in the |idx| entry in the constant pool // if the object referenced by the accumulator is false when the object is cast // to boolean. void Interpreter::DoJumpIfToBooleanFalseConstant( InterpreterAssembler* assembler) { + Callable callable = CodeFactory::ToBoolean(isolate_); + Node* target = __ HeapConstant(callable.code()); Node* accumulator = __ GetAccumulator(); Node* context = __ GetContext(); Node* to_boolean_value = - __ CallRuntime(Runtime::kInterpreterToBoolean, context, accumulator); + __ CallStub(callable.descriptor(), target, context, accumulator); Node* index = __ BytecodeOperandIdx(0); Node* constant = __ LoadConstantPoolEntry(index); Node* relative_jump = __ SmiUntag(constant); @@ -1433,19 +1242,7 @@ void Interpreter::DoJumpIfToBooleanFalseConstant( __ JumpIfWordEqual(to_boolean_value, false_value, relative_jump); } - -// JumpIfToBooleanFalseConstantWide <idx16> -// -// Jump by number of bytes in the Smi in the |idx16| entry in the constant pool -// if the object referenced by the accumulator is false when the object is cast -// to boolean. -void Interpreter::DoJumpIfToBooleanFalseConstantWide( - InterpreterAssembler* assembler) { - DoJumpIfToBooleanFalseConstant(assembler); -} - - -// JumpIfNull <imm8> +// JumpIfNull <imm> // // Jump by number of bytes represented by an immediate operand if the object // referenced by the accumulator is the null constant. @@ -1456,10 +1253,9 @@ void Interpreter::DoJumpIfNull(InterpreterAssembler* assembler) { __ JumpIfWordEqual(accumulator, null_value, relative_jump); } - -// JumpIfNullConstant <idx8> +// JumpIfNullConstant <idx> // -// Jump by number of bytes in the Smi in the |idx8| entry in the constant pool +// Jump by number of bytes in the Smi in the |idx| entry in the constant pool // if the object referenced by the accumulator is the null constant. void Interpreter::DoJumpIfNullConstant(InterpreterAssembler* assembler) { Node* accumulator = __ GetAccumulator(); @@ -1470,16 +1266,7 @@ void Interpreter::DoJumpIfNullConstant(InterpreterAssembler* assembler) { __ JumpIfWordEqual(accumulator, null_value, relative_jump); } - -// JumpIfNullConstantWide <idx16> -// -// Jump by number of bytes in the Smi in the |idx16| entry in the constant pool -// if the object referenced by the accumulator is the null constant. -void Interpreter::DoJumpIfNullConstantWide(InterpreterAssembler* assembler) { - DoJumpIfNullConstant(assembler); -} - -// JumpIfUndefined <imm8> +// JumpIfUndefined <imm> // // Jump by number of bytes represented by an immediate operand if the object // referenced by the accumulator is the undefined constant. @@ -1491,10 +1278,9 @@ void Interpreter::DoJumpIfUndefined(InterpreterAssembler* assembler) { __ JumpIfWordEqual(accumulator, undefined_value, relative_jump); } - -// JumpIfUndefinedConstant <idx8> +// JumpIfUndefinedConstant <idx> // -// Jump by number of bytes in the Smi in the |idx8| entry in the constant pool +// Jump by number of bytes in the Smi in the |idx| entry in the constant pool // if the object referenced by the accumulator is the undefined constant. void Interpreter::DoJumpIfUndefinedConstant(InterpreterAssembler* assembler) { Node* accumulator = __ GetAccumulator(); @@ -1506,17 +1292,7 @@ void Interpreter::DoJumpIfUndefinedConstant(InterpreterAssembler* assembler) { __ JumpIfWordEqual(accumulator, undefined_value, relative_jump); } - -// JumpIfUndefinedConstantWide <idx16> -// -// Jump by number of bytes in the Smi in the |idx16| entry in the constant pool -// if the object referenced by the accumulator is the undefined constant. -void Interpreter::DoJumpIfUndefinedConstantWide( - InterpreterAssembler* assembler) { - DoJumpIfUndefinedConstant(assembler); -} - -// JumpIfNotHole <imm8> +// JumpIfNotHole <imm> // // Jump by number of bytes represented by an immediate operand if the object // referenced by the accumulator is the hole. @@ -1527,9 +1303,9 @@ void Interpreter::DoJumpIfNotHole(InterpreterAssembler* assembler) { __ JumpIfWordNotEqual(accumulator, the_hole_value, relative_jump); } -// JumpIfNotHoleConstant <idx8> +// JumpIfNotHoleConstant <idx> // -// Jump by number of bytes in the Smi in the |idx8| entry in the constant pool +// Jump by number of bytes in the Smi in the |idx| entry in the constant pool // if the object referenced by the accumulator is the hole constant. void Interpreter::DoJumpIfNotHoleConstant(InterpreterAssembler* assembler) { Node* accumulator = __ GetAccumulator(); @@ -1540,21 +1316,13 @@ void Interpreter::DoJumpIfNotHoleConstant(InterpreterAssembler* assembler) { __ JumpIfWordNotEqual(accumulator, the_hole_value, relative_jump); } -// JumpIfNotHoleConstantWide <idx16> -// -// Jump by number of bytes in the Smi in the |idx16| entry in the constant pool -// if the object referenced by the accumulator is the hole constant. -void Interpreter::DoJumpIfNotHoleConstantWide(InterpreterAssembler* assembler) { - DoJumpIfNotHoleConstant(assembler); -} - void Interpreter::DoCreateLiteral(Runtime::FunctionId function_id, InterpreterAssembler* assembler) { Node* index = __ BytecodeOperandIdx(0); Node* constant_elements = __ LoadConstantPoolEntry(index); Node* literal_index_raw = __ BytecodeOperandIdx(1); Node* literal_index = __ SmiTag(literal_index_raw); - Node* flags_raw = __ BytecodeOperandImm(2); + Node* flags_raw = __ BytecodeOperandFlag(2); Node* flags = __ SmiTag(flags_raw); Node* closure = __ LoadRegister(Register::function_closure()); Node* context = __ GetContext(); @@ -1570,19 +1338,22 @@ void Interpreter::DoCreateLiteral(Runtime::FunctionId function_id, // Creates a regular expression literal for literal index <literal_idx> with // <flags> and the pattern in <pattern_idx>. void Interpreter::DoCreateRegExpLiteral(InterpreterAssembler* assembler) { - DoCreateLiteral(Runtime::kCreateRegExpLiteral, assembler); -} - - -// CreateRegExpLiteralWide <pattern_idx> <literal_idx> <flags> -// -// Creates a regular expression literal for literal index <literal_idx> with -// <flags> and the pattern in <pattern_idx>. -void Interpreter::DoCreateRegExpLiteralWide(InterpreterAssembler* assembler) { - DoCreateLiteral(Runtime::kCreateRegExpLiteral, assembler); + Callable callable = CodeFactory::FastCloneRegExp(isolate_); + Node* target = __ HeapConstant(callable.code()); + Node* index = __ BytecodeOperandIdx(0); + Node* pattern = __ LoadConstantPoolEntry(index); + Node* literal_index_raw = __ BytecodeOperandIdx(1); + Node* literal_index = __ SmiTag(literal_index_raw); + Node* flags_raw = __ BytecodeOperandFlag(2); + Node* flags = __ SmiTag(flags_raw); + Node* closure = __ LoadRegister(Register::function_closure()); + Node* context = __ GetContext(); + Node* result = __ CallStub(callable.descriptor(), target, context, closure, + literal_index, pattern, flags); + __ SetAccumulator(result); + __ Dispatch(); } - // CreateArrayLiteral <element_idx> <literal_idx> <flags> // // Creates an array literal for literal index <literal_idx> with flags <flags> @@ -1591,16 +1362,6 @@ void Interpreter::DoCreateArrayLiteral(InterpreterAssembler* assembler) { DoCreateLiteral(Runtime::kCreateArrayLiteral, assembler); } - -// CreateArrayLiteralWide <element_idx> <literal_idx> <flags> -// -// Creates an array literal for literal index <literal_idx> with flags <flags> -// and constant elements in <element_idx>. -void Interpreter::DoCreateArrayLiteralWide(InterpreterAssembler* assembler) { - DoCreateLiteral(Runtime::kCreateArrayLiteral, assembler); -} - - // CreateObjectLiteral <element_idx> <literal_idx> <flags> // // Creates an object literal for literal index <literal_idx> with flags <flags> @@ -1609,16 +1370,6 @@ void Interpreter::DoCreateObjectLiteral(InterpreterAssembler* assembler) { DoCreateLiteral(Runtime::kCreateObjectLiteral, assembler); } - -// CreateObjectLiteralWide <element_idx> <literal_idx> <flags> -// -// Creates an object literal for literal index <literal_idx> with flags <flags> -// and constant elements in <element_idx>. -void Interpreter::DoCreateObjectLiteralWide(InterpreterAssembler* assembler) { - DoCreateLiteral(Runtime::kCreateObjectLiteral, assembler); -} - - // CreateClosure <index> <tenured> // // Creates a new closure for SharedFunctionInfo at position |index| in the @@ -1628,7 +1379,7 @@ void Interpreter::DoCreateClosure(InterpreterAssembler* assembler) { // calling into the runtime. Node* index = __ BytecodeOperandIdx(0); Node* shared = __ LoadConstantPoolEntry(index); - Node* tenured_raw = __ BytecodeOperandImm(1); + Node* tenured_raw = __ BytecodeOperandFlag(1); Node* tenured = __ SmiTag(tenured_raw); Node* context = __ GetContext(); Node* result = @@ -1637,16 +1388,6 @@ void Interpreter::DoCreateClosure(InterpreterAssembler* assembler) { __ Dispatch(); } - -// CreateClosureWide <index> <tenured> -// -// Creates a new closure for SharedFunctionInfo at position |index| in the -// constant pool and with the PretenureFlag <tenured>. -void Interpreter::DoCreateClosureWide(InterpreterAssembler* assembler) { - return DoCreateClosure(assembler); -} - - // CreateMappedArguments // // Creates a new mapped arguments object. @@ -1737,11 +1478,13 @@ void Interpreter::DoDebugger(InterpreterAssembler* assembler) { // DebugBreak // // Call runtime to handle a debug break. -#define DEBUG_BREAK(Name, ...) \ - void Interpreter::Do##Name(InterpreterAssembler* assembler) { \ - Node* context = __ GetContext(); \ - Node* original_handler = __ CallRuntime(Runtime::kDebugBreak, context); \ - __ DispatchToBytecodeHandler(original_handler); \ +#define DEBUG_BREAK(Name, ...) \ + void Interpreter::Do##Name(InterpreterAssembler* assembler) { \ + Node* context = __ GetContext(); \ + Node* accumulator = __ GetAccumulator(); \ + Node* original_handler = \ + __ CallRuntime(Runtime::kDebugBreakOnBytecode, context, accumulator); \ + __ DispatchToBytecodeHandler(original_handler); \ } DEBUG_BREAK_BYTECODE_LIST(DEBUG_BREAK); #undef DEBUG_BREAK @@ -1768,18 +1511,6 @@ void Interpreter::DoForInPrepare(InterpreterAssembler* assembler) { __ Dispatch(); } - -// ForInPrepareWide <cache_info_triple> -// -// Returns state for for..in loop execution based on the object in the -// accumulator. The result is output in registers |cache_info_triple| to -// |cache_info_triple + 2|, with the registers holding cache_type, cache_array, -// and cache_length respectively. -void Interpreter::DoForInPrepareWide(InterpreterAssembler* assembler) { - DoForInPrepare(assembler); -} - - // ForInNext <receiver> <index> <cache_info_pair> // // Returns the next enumerable property in the the accumulator. @@ -1792,53 +1523,101 @@ void Interpreter::DoForInNext(InterpreterAssembler* assembler) { Node* cache_type = __ LoadRegister(cache_type_reg); Node* cache_array_reg = __ NextRegister(cache_type_reg); Node* cache_array = __ LoadRegister(cache_array_reg); - Node* context = __ GetContext(); - Node* result = __ CallRuntime(Runtime::kForInNext, context, receiver, - cache_array, cache_type, index); - __ SetAccumulator(result); - __ Dispatch(); -} - -// ForInNextWide <receiver> <index> <cache_info_pair> -// -// Returns the next enumerable property in the the accumulator. -void Interpreter::DoForInNextWide(InterpreterAssembler* assembler) { - return DoForInNext(assembler); + // Load the next key from the enumeration array. + Node* key = __ LoadFixedArrayElementSmiIndex(cache_array, index); + + // Check if we can use the for-in fast path potentially using the enum cache. + InterpreterAssembler::Label if_fast(assembler), if_slow(assembler); + Node* receiver_map = __ LoadObjectField(receiver, HeapObject::kMapOffset); + Node* condition = __ WordEqual(receiver_map, cache_type); + __ Branch(condition, &if_fast, &if_slow); + __ Bind(&if_fast); + { + // Enum cache in use for {receiver}, the {key} is definitely valid. + __ SetAccumulator(key); + __ Dispatch(); + } + __ Bind(&if_slow); + { + // Record the fact that we hit the for-in slow path. + Node* vector_index = __ BytecodeOperandIdx(3); + Node* type_feedback_vector = __ LoadTypeFeedbackVector(); + Node* megamorphic_sentinel = + __ HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate_)); + __ StoreFixedArrayElementNoWriteBarrier(type_feedback_vector, vector_index, + megamorphic_sentinel); + + // Need to filter the {key} for the {receiver}. + Node* context = __ GetContext(); + Node* result = + __ CallRuntime(Runtime::kForInFilter, context, receiver, key); + __ SetAccumulator(result); + __ Dispatch(); + } } - // ForInDone <index> <cache_length> // // Returns true if the end of the enumerable properties has been reached. void Interpreter::DoForInDone(InterpreterAssembler* assembler) { - // TODO(oth): Implement directly rather than making a runtime call. Node* index_reg = __ BytecodeOperandReg(0); Node* index = __ LoadRegister(index_reg); Node* cache_length_reg = __ BytecodeOperandReg(1); Node* cache_length = __ LoadRegister(cache_length_reg); - Node* context = __ GetContext(); - Node* result = - __ CallRuntime(Runtime::kForInDone, context, index, cache_length); - __ SetAccumulator(result); - __ Dispatch(); -} + // Check if {index} is at {cache_length} already. + InterpreterAssembler::Label if_true(assembler), if_false(assembler); + Node* condition = __ WordEqual(index, cache_length); + __ Branch(condition, &if_true, &if_false); + __ Bind(&if_true); + { + Node* result = __ BooleanConstant(true); + __ SetAccumulator(result); + __ Dispatch(); + } + __ Bind(&if_false); + { + Node* result = __ BooleanConstant(false); + __ SetAccumulator(result); + __ Dispatch(); + } +} // ForInStep <index> // // Increments the loop counter in register |index| and stores the result // in the accumulator. void Interpreter::DoForInStep(InterpreterAssembler* assembler) { - // TODO(oth): Implement directly rather than making a runtime call. Node* index_reg = __ BytecodeOperandReg(0); Node* index = __ LoadRegister(index_reg); - Node* context = __ GetContext(); - Node* result = __ CallRuntime(Runtime::kForInStep, context, index); + Node* one = __ SmiConstant(Smi::FromInt(1)); + Node* result = __ SmiAdd(index, one); __ SetAccumulator(result); __ Dispatch(); } +// Wide +// +// Prefix bytecode indicating next bytecode has wide (16-bit) operands. +void Interpreter::DoWide(InterpreterAssembler* assembler) { + __ DispatchWide(OperandScale::kDouble); +} + +// ExtraWide +// +// Prefix bytecode indicating next bytecode has extra-wide (32-bit) operands. +void Interpreter::DoExtraWide(InterpreterAssembler* assembler) { + __ DispatchWide(OperandScale::kQuadruple); +} + +// Illegal +// +// An invalid bytecode aborting execution if dispatched. +void Interpreter::DoIllegal(InterpreterAssembler* assembler) { + __ Abort(kInvalidBytecode); +} + } // namespace interpreter } // namespace internal } // namespace v8 |