aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/interpreter/interpreter.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/interpreter/interpreter.cc')
-rw-r--r--deps/v8/src/interpreter/interpreter.cc795
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