blob: 5084300dfee60294b3af19832d026410b5834c6f [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// Copyright 2015 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/interpreter/interpreter.h"
6
Ben Murdoch097c5b22016-05-18 11:27:45 +01007#include "src/ast/prettyprinter.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008#include "src/code-factory.h"
9#include "src/compiler.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010#include "src/factory.h"
11#include "src/interpreter/bytecode-generator.h"
12#include "src/interpreter/bytecodes.h"
Ben Murdoch097c5b22016-05-18 11:27:45 +010013#include "src/interpreter/interpreter-assembler.h"
Ben Murdochda12d292016-06-02 14:46:10 +010014#include "src/interpreter/interpreter-intrinsics.h"
15#include "src/log.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000016#include "src/zone.h"
17
18namespace v8 {
19namespace internal {
20namespace interpreter {
21
22using compiler::Node;
23
24#define __ assembler->
25
Ben Murdoch097c5b22016-05-18 11:27:45 +010026Interpreter::Interpreter(Isolate* isolate) : isolate_(isolate) {
Ben Murdochda12d292016-06-02 14:46:10 +010027 memset(dispatch_table_, 0, sizeof(dispatch_table_));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000028}
29
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000030void Interpreter::Initialize() {
31 DCHECK(FLAG_ignition);
Ben Murdoch097c5b22016-05-18 11:27:45 +010032 if (IsDispatchTableInitialized()) return;
Ben Murdochda12d292016-06-02 14:46:10 +010033 Zone zone(isolate_->allocator());
Ben Murdoch097c5b22016-05-18 11:27:45 +010034 HandleScope scope(isolate_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000035
Ben Murdochda12d292016-06-02 14:46:10 +010036 // Generate bytecode handlers for all bytecodes and scales.
37 for (OperandScale operand_scale = OperandScale::kSingle;
38 operand_scale <= OperandScale::kMaxValid;
39 operand_scale = Bytecodes::NextOperandScale(operand_scale)) {
40#define GENERATE_CODE(Name, ...) \
41 { \
42 if (Bytecodes::BytecodeHasHandler(Bytecode::k##Name, operand_scale)) { \
43 InterpreterAssembler assembler(isolate_, &zone, Bytecode::k##Name, \
44 operand_scale); \
45 Do##Name(&assembler); \
46 Handle<Code> code = assembler.GenerateCode(); \
47 size_t index = GetDispatchTableIndex(Bytecode::k##Name, operand_scale); \
48 dispatch_table_[index] = *code; \
49 TraceCodegen(code); \
50 LOG_CODE_EVENT( \
51 isolate_, \
52 CodeCreateEvent( \
53 Logger::BYTECODE_HANDLER_TAG, AbstractCode::cast(*code), \
54 Bytecodes::ToString(Bytecode::k##Name, operand_scale).c_str())); \
55 } \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000056 }
Ben Murdochda12d292016-06-02 14:46:10 +010057 BYTECODE_LIST(GENERATE_CODE)
Ben Murdoch097c5b22016-05-18 11:27:45 +010058#undef GENERATE_CODE
Ben Murdochda12d292016-06-02 14:46:10 +010059 }
60
61 // Fill unused entries will the illegal bytecode handler.
62 size_t illegal_index =
63 GetDispatchTableIndex(Bytecode::kIllegal, OperandScale::kSingle);
64 for (size_t index = 0; index < arraysize(dispatch_table_); ++index) {
65 if (dispatch_table_[index] == nullptr) {
66 dispatch_table_[index] = dispatch_table_[illegal_index];
67 }
68 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000069}
70
Ben Murdochda12d292016-06-02 14:46:10 +010071Code* Interpreter::GetBytecodeHandler(Bytecode bytecode,
72 OperandScale operand_scale) {
Ben Murdoch097c5b22016-05-18 11:27:45 +010073 DCHECK(IsDispatchTableInitialized());
Ben Murdochda12d292016-06-02 14:46:10 +010074 DCHECK(Bytecodes::BytecodeHasHandler(bytecode, operand_scale));
75 size_t index = GetDispatchTableIndex(bytecode, operand_scale);
76 return dispatch_table_[index];
77}
78
79// static
80size_t Interpreter::GetDispatchTableIndex(Bytecode bytecode,
81 OperandScale operand_scale) {
82 static const size_t kEntriesPerOperandScale = 1u << kBitsPerByte;
83 size_t index = static_cast<size_t>(bytecode);
84 OperandScale current_scale = OperandScale::kSingle;
85 while (current_scale != operand_scale) {
86 index += kEntriesPerOperandScale;
87 current_scale = Bytecodes::NextOperandScale(current_scale);
88 }
89 return index;
Ben Murdoch097c5b22016-05-18 11:27:45 +010090}
91
92void Interpreter::IterateDispatchTable(ObjectVisitor* v) {
93 v->VisitPointers(
94 reinterpret_cast<Object**>(&dispatch_table_[0]),
95 reinterpret_cast<Object**>(&dispatch_table_[0] + kDispatchTableSize));
96}
97
98// static
99int Interpreter::InterruptBudget() {
100 // TODO(ignition): Tune code size multiplier.
101 const int kCodeSizeMultiplier = 32;
102 return FLAG_interrupt_budget * kCodeSizeMultiplier;
103}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000104
105bool Interpreter::MakeBytecode(CompilationInfo* info) {
Ben Murdochda12d292016-06-02 14:46:10 +0100106 TimerEventScope<TimerEventCompileIgnition> timer(info->isolate());
107 TRACE_EVENT0("v8", "V8.CompileIgnition");
108
Ben Murdoch097c5b22016-05-18 11:27:45 +0100109 if (FLAG_print_bytecode || FLAG_print_source || FLAG_print_ast) {
110 OFStream os(stdout);
111 base::SmartArrayPointer<char> name = info->GetDebugName();
112 os << "[generating bytecode for function: " << info->GetDebugName().get()
113 << "]" << std::endl
114 << std::flush;
115 }
116
117#ifdef DEBUG
118 if (info->parse_info() && FLAG_print_source) {
119 OFStream os(stdout);
120 os << "--- Source from AST ---" << std::endl
121 << PrettyPrinter(info->isolate()).PrintProgram(info->literal())
122 << std::endl
123 << std::flush;
124 }
125
126 if (info->parse_info() && FLAG_print_ast) {
127 OFStream os(stdout);
128 os << "--- AST ---" << std::endl
129 << AstPrinter(info->isolate()).PrintProgram(info->literal()) << std::endl
130 << std::flush;
131 }
132#endif // DEBUG
133
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000134 BytecodeGenerator generator(info->isolate(), info->zone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000135 Handle<BytecodeArray> bytecodes = generator.MakeBytecode(info);
Ben Murdochda12d292016-06-02 14:46:10 +0100136
137 if (generator.HasStackOverflow()) return false;
138
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000139 if (FLAG_print_bytecode) {
140 OFStream os(stdout);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000141 bytecodes->Print(os);
142 os << std::flush;
143 }
144
145 info->SetBytecodeArray(bytecodes);
146 info->SetCode(info->isolate()->builtins()->InterpreterEntryTrampoline());
147 return true;
148}
149
Ben Murdoch097c5b22016-05-18 11:27:45 +0100150bool Interpreter::IsDispatchTableInitialized() {
Ben Murdochda12d292016-06-02 14:46:10 +0100151 if (FLAG_trace_ignition || FLAG_trace_ignition_codegen) {
152 // Regenerate table to add bytecode tracing operations
153 // or to print the assembly code generated by TurboFan.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100154 return false;
155 }
156 return dispatch_table_[0] != nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000157}
158
Ben Murdochda12d292016-06-02 14:46:10 +0100159void Interpreter::TraceCodegen(Handle<Code> code) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100160#ifdef ENABLE_DISASSEMBLER
161 if (FLAG_trace_ignition_codegen) {
162 OFStream os(stdout);
Ben Murdochda12d292016-06-02 14:46:10 +0100163 code->Disassemble(nullptr, os);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100164 os << std::flush;
165 }
166#endif // ENABLE_DISASSEMBLER
167}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000168
Ben Murdochda12d292016-06-02 14:46:10 +0100169const char* Interpreter::LookupNameOfBytecodeHandler(Code* code) {
170#ifdef ENABLE_DISASSEMBLER
171#define RETURN_NAME(Name, ...) \
172 if (dispatch_table_[Bytecodes::ToByte(Bytecode::k##Name)] == code) { \
173 return #Name; \
174 }
175 BYTECODE_LIST(RETURN_NAME)
176#undef RETURN_NAME
177#endif // ENABLE_DISASSEMBLER
178 return nullptr;
179}
180
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000181// LdaZero
182//
183// Load literal '0' into the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100184void Interpreter::DoLdaZero(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000185 Node* zero_value = __ NumberConstant(0.0);
186 __ SetAccumulator(zero_value);
187 __ Dispatch();
188}
189
Ben Murdochda12d292016-06-02 14:46:10 +0100190// LdaSmi <imm>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000191//
Ben Murdochda12d292016-06-02 14:46:10 +0100192// Load an integer literal into the accumulator as a Smi.
193void Interpreter::DoLdaSmi(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000194 Node* raw_int = __ BytecodeOperandImm(0);
195 Node* smi_int = __ SmiTag(raw_int);
196 __ SetAccumulator(smi_int);
197 __ Dispatch();
198}
199
Ben Murdoch097c5b22016-05-18 11:27:45 +0100200void Interpreter::DoLoadConstant(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000201 Node* index = __ BytecodeOperandIdx(0);
202 Node* constant = __ LoadConstantPoolEntry(index);
203 __ SetAccumulator(constant);
204 __ Dispatch();
205}
206
207
208// LdaConstant <idx>
209//
210// Load constant literal at |idx| in the constant pool into the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100211void Interpreter::DoLdaConstant(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000212 DoLoadConstant(assembler);
213}
214
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000215// LdaUndefined
216//
217// Load Undefined into the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100218void Interpreter::DoLdaUndefined(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000219 Node* undefined_value =
220 __ HeapConstant(isolate_->factory()->undefined_value());
221 __ SetAccumulator(undefined_value);
222 __ Dispatch();
223}
224
225
226// LdaNull
227//
228// Load Null into the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100229void Interpreter::DoLdaNull(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000230 Node* null_value = __ HeapConstant(isolate_->factory()->null_value());
231 __ SetAccumulator(null_value);
232 __ Dispatch();
233}
234
235
236// LdaTheHole
237//
238// Load TheHole into the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100239void Interpreter::DoLdaTheHole(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000240 Node* the_hole_value = __ HeapConstant(isolate_->factory()->the_hole_value());
241 __ SetAccumulator(the_hole_value);
242 __ Dispatch();
243}
244
245
246// LdaTrue
247//
248// Load True into the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100249void Interpreter::DoLdaTrue(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000250 Node* true_value = __ HeapConstant(isolate_->factory()->true_value());
251 __ SetAccumulator(true_value);
252 __ Dispatch();
253}
254
255
256// LdaFalse
257//
258// Load False into the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100259void Interpreter::DoLdaFalse(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000260 Node* false_value = __ HeapConstant(isolate_->factory()->false_value());
261 __ SetAccumulator(false_value);
262 __ Dispatch();
263}
264
265
266// Ldar <src>
267//
268// Load accumulator with value from register <src>.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100269void Interpreter::DoLdar(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000270 Node* reg_index = __ BytecodeOperandReg(0);
271 Node* value = __ LoadRegister(reg_index);
272 __ SetAccumulator(value);
273 __ Dispatch();
274}
275
276
277// Star <dst>
278//
279// Store accumulator to register <dst>.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100280void Interpreter::DoStar(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000281 Node* reg_index = __ BytecodeOperandReg(0);
282 Node* accumulator = __ GetAccumulator();
283 __ StoreRegister(accumulator, reg_index);
284 __ Dispatch();
285}
286
287
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000288// Mov <src> <dst>
289//
290// Stores the value of register <src> to register <dst>.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100291void Interpreter::DoMov(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000292 Node* src_index = __ BytecodeOperandReg(0);
293 Node* src_value = __ LoadRegister(src_index);
294 Node* dst_index = __ BytecodeOperandReg(1);
295 __ StoreRegister(src_value, dst_index);
296 __ Dispatch();
297}
298
299
Ben Murdoch097c5b22016-05-18 11:27:45 +0100300void Interpreter::DoLoadGlobal(Callable ic, InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000301 // Get the global object.
302 Node* context = __ GetContext();
303 Node* native_context =
304 __ LoadContextSlot(context, Context::NATIVE_CONTEXT_INDEX);
305 Node* global = __ LoadContextSlot(native_context, Context::EXTENSION_INDEX);
306
307 // Load the global via the LoadIC.
308 Node* code_target = __ HeapConstant(ic.code());
309 Node* constant_index = __ BytecodeOperandIdx(0);
310 Node* name = __ LoadConstantPoolEntry(constant_index);
311 Node* raw_slot = __ BytecodeOperandIdx(1);
312 Node* smi_slot = __ SmiTag(raw_slot);
313 Node* type_feedback_vector = __ LoadTypeFeedbackVector();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100314 Node* result = __ CallStub(ic.descriptor(), code_target, context, global,
315 name, smi_slot, type_feedback_vector);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000316 __ SetAccumulator(result);
317 __ Dispatch();
318}
319
Ben Murdoch097c5b22016-05-18 11:27:45 +0100320// LdaGlobal <name_index> <slot>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000321//
322// Load the global with name in constant pool entry <name_index> into the
Ben Murdoch097c5b22016-05-18 11:27:45 +0100323// accumulator using FeedBackVector slot <slot> outside of a typeof.
324void Interpreter::DoLdaGlobal(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000325 Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100326 UNINITIALIZED);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000327 DoLoadGlobal(ic, assembler);
328}
329
Ben Murdoch097c5b22016-05-18 11:27:45 +0100330// LdaGlobalInsideTypeof <name_index> <slot>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000331//
332// Load the global with name in constant pool entry <name_index> into the
Ben Murdoch097c5b22016-05-18 11:27:45 +0100333// accumulator using FeedBackVector slot <slot> inside of a typeof.
334void Interpreter::DoLdaGlobalInsideTypeof(InterpreterAssembler* assembler) {
335 Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, INSIDE_TYPEOF,
336 UNINITIALIZED);
337 DoLoadGlobal(ic, assembler);
338}
339
Ben Murdoch097c5b22016-05-18 11:27:45 +0100340void Interpreter::DoStoreGlobal(Callable ic, InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000341 // Get the global object.
342 Node* context = __ GetContext();
343 Node* native_context =
344 __ LoadContextSlot(context, Context::NATIVE_CONTEXT_INDEX);
345 Node* global = __ LoadContextSlot(native_context, Context::EXTENSION_INDEX);
346
347 // Store the global via the StoreIC.
348 Node* code_target = __ HeapConstant(ic.code());
349 Node* constant_index = __ BytecodeOperandIdx(0);
350 Node* name = __ LoadConstantPoolEntry(constant_index);
351 Node* value = __ GetAccumulator();
352 Node* raw_slot = __ BytecodeOperandIdx(1);
353 Node* smi_slot = __ SmiTag(raw_slot);
354 Node* type_feedback_vector = __ LoadTypeFeedbackVector();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100355 __ CallStub(ic.descriptor(), code_target, context, global, name, value,
356 smi_slot, type_feedback_vector);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000357 __ Dispatch();
358}
359
360
361// StaGlobalSloppy <name_index> <slot>
362//
363// Store the value in the accumulator into the global with name in constant pool
364// entry <name_index> using FeedBackVector slot <slot> in sloppy mode.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100365void Interpreter::DoStaGlobalSloppy(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000366 Callable ic =
367 CodeFactory::StoreICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED);
368 DoStoreGlobal(ic, assembler);
369}
370
371
372// StaGlobalStrict <name_index> <slot>
373//
374// Store the value in the accumulator into the global with name in constant pool
375// entry <name_index> using FeedBackVector slot <slot> in strict mode.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100376void Interpreter::DoStaGlobalStrict(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000377 Callable ic =
378 CodeFactory::StoreICInOptimizedCode(isolate_, STRICT, UNINITIALIZED);
379 DoStoreGlobal(ic, assembler);
380}
381
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000382// LdaContextSlot <context> <slot_index>
383//
384// Load the object in |slot_index| of |context| into the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100385void Interpreter::DoLdaContextSlot(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000386 Node* reg_index = __ BytecodeOperandReg(0);
387 Node* context = __ LoadRegister(reg_index);
388 Node* slot_index = __ BytecodeOperandIdx(1);
389 Node* result = __ LoadContextSlot(context, slot_index);
390 __ SetAccumulator(result);
391 __ Dispatch();
392}
393
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000394// StaContextSlot <context> <slot_index>
395//
396// Stores the object in the accumulator into |slot_index| of |context|.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100397void Interpreter::DoStaContextSlot(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000398 Node* value = __ GetAccumulator();
399 Node* reg_index = __ BytecodeOperandReg(0);
400 Node* context = __ LoadRegister(reg_index);
401 Node* slot_index = __ BytecodeOperandIdx(1);
402 __ StoreContextSlot(context, slot_index, value);
403 __ Dispatch();
404}
405
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000406void Interpreter::DoLoadLookupSlot(Runtime::FunctionId function_id,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100407 InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000408 Node* index = __ BytecodeOperandIdx(0);
409 Node* name = __ LoadConstantPoolEntry(index);
410 Node* context = __ GetContext();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100411 Node* result = __ CallRuntime(function_id, context, name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000412 __ SetAccumulator(result);
413 __ Dispatch();
414}
415
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000416// LdaLookupSlot <name_index>
417//
418// Lookup the object with the name in constant pool entry |name_index|
419// dynamically.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100420void Interpreter::DoLdaLookupSlot(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000421 DoLoadLookupSlot(Runtime::kLoadLookupSlot, assembler);
422}
423
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000424// LdaLookupSlotInsideTypeof <name_index>
425//
426// Lookup the object with the name in constant pool entry |name_index|
427// dynamically without causing a NoReferenceError.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100428void Interpreter::DoLdaLookupSlotInsideTypeof(InterpreterAssembler* assembler) {
429 DoLoadLookupSlot(Runtime::kLoadLookupSlotInsideTypeof, assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000430}
431
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000432void Interpreter::DoStoreLookupSlot(LanguageMode language_mode,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100433 InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000434 Node* value = __ GetAccumulator();
435 Node* index = __ BytecodeOperandIdx(0);
436 Node* name = __ LoadConstantPoolEntry(index);
437 Node* context = __ GetContext();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100438 Node* result = __ CallRuntime(is_strict(language_mode)
439 ? Runtime::kStoreLookupSlot_Strict
440 : Runtime::kStoreLookupSlot_Sloppy,
441 context, name, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000442 __ SetAccumulator(result);
443 __ Dispatch();
444}
445
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000446// StaLookupSlotSloppy <name_index>
447//
448// Store the object in accumulator to the object with the name in constant
449// pool entry |name_index| in sloppy mode.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100450void Interpreter::DoStaLookupSlotSloppy(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000451 DoStoreLookupSlot(LanguageMode::SLOPPY, assembler);
452}
453
454
455// StaLookupSlotStrict <name_index>
456//
457// Store the object in accumulator to the object with the name in constant
458// pool entry |name_index| in strict mode.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100459void Interpreter::DoStaLookupSlotStrict(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000460 DoStoreLookupSlot(LanguageMode::STRICT, assembler);
461}
462
Ben Murdoch097c5b22016-05-18 11:27:45 +0100463void Interpreter::DoLoadIC(Callable ic, InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000464 Node* code_target = __ HeapConstant(ic.code());
465 Node* register_index = __ BytecodeOperandReg(0);
466 Node* object = __ LoadRegister(register_index);
467 Node* constant_index = __ BytecodeOperandIdx(1);
468 Node* name = __ LoadConstantPoolEntry(constant_index);
469 Node* raw_slot = __ BytecodeOperandIdx(2);
470 Node* smi_slot = __ SmiTag(raw_slot);
471 Node* type_feedback_vector = __ LoadTypeFeedbackVector();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100472 Node* context = __ GetContext();
473 Node* result = __ CallStub(ic.descriptor(), code_target, context, object,
474 name, smi_slot, type_feedback_vector);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000475 __ SetAccumulator(result);
476 __ Dispatch();
477}
478
Ben Murdoch097c5b22016-05-18 11:27:45 +0100479// LoadIC <object> <name_index> <slot>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000480//
Ben Murdoch097c5b22016-05-18 11:27:45 +0100481// Calls the LoadIC at FeedBackVector slot <slot> for <object> and the name at
482// constant pool entry <name_index>.
483void Interpreter::DoLoadIC(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000484 Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100485 UNINITIALIZED);
486 DoLoadIC(ic, assembler);
487}
488
Ben Murdoch097c5b22016-05-18 11:27:45 +0100489void Interpreter::DoKeyedLoadIC(Callable ic, InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000490 Node* code_target = __ HeapConstant(ic.code());
491 Node* reg_index = __ BytecodeOperandReg(0);
492 Node* object = __ LoadRegister(reg_index);
493 Node* name = __ GetAccumulator();
494 Node* raw_slot = __ BytecodeOperandIdx(1);
495 Node* smi_slot = __ SmiTag(raw_slot);
496 Node* type_feedback_vector = __ LoadTypeFeedbackVector();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100497 Node* context = __ GetContext();
498 Node* result = __ CallStub(ic.descriptor(), code_target, context, object,
499 name, smi_slot, type_feedback_vector);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000500 __ SetAccumulator(result);
501 __ Dispatch();
502}
503
Ben Murdoch097c5b22016-05-18 11:27:45 +0100504// KeyedLoadIC <object> <slot>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000505//
Ben Murdoch097c5b22016-05-18 11:27:45 +0100506// Calls the KeyedLoadIC at FeedBackVector slot <slot> for <object> and the key
507// in the accumulator.
508void Interpreter::DoKeyedLoadIC(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000509 Callable ic =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100510 CodeFactory::KeyedLoadICInOptimizedCode(isolate_, UNINITIALIZED);
511 DoKeyedLoadIC(ic, assembler);
512}
513
Ben Murdoch097c5b22016-05-18 11:27:45 +0100514void Interpreter::DoStoreIC(Callable ic, InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000515 Node* code_target = __ HeapConstant(ic.code());
516 Node* object_reg_index = __ BytecodeOperandReg(0);
517 Node* object = __ LoadRegister(object_reg_index);
518 Node* constant_index = __ BytecodeOperandIdx(1);
519 Node* name = __ LoadConstantPoolEntry(constant_index);
520 Node* value = __ GetAccumulator();
521 Node* raw_slot = __ BytecodeOperandIdx(2);
522 Node* smi_slot = __ SmiTag(raw_slot);
523 Node* type_feedback_vector = __ LoadTypeFeedbackVector();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100524 Node* context = __ GetContext();
525 __ CallStub(ic.descriptor(), code_target, context, object, name, value,
526 smi_slot, type_feedback_vector);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000527 __ Dispatch();
528}
529
530
531// StoreICSloppy <object> <name_index> <slot>
532//
533// Calls the sloppy mode StoreIC at FeedBackVector slot <slot> for <object> and
534// the name in constant pool entry <name_index> with the value in the
535// accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100536void Interpreter::DoStoreICSloppy(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000537 Callable ic =
538 CodeFactory::StoreICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED);
539 DoStoreIC(ic, assembler);
540}
541
542
543// StoreICStrict <object> <name_index> <slot>
544//
545// Calls the strict mode StoreIC at FeedBackVector slot <slot> for <object> and
546// the name in constant pool entry <name_index> with the value in the
547// accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100548void Interpreter::DoStoreICStrict(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000549 Callable ic =
550 CodeFactory::StoreICInOptimizedCode(isolate_, STRICT, UNINITIALIZED);
551 DoStoreIC(ic, assembler);
552}
553
Ben Murdoch097c5b22016-05-18 11:27:45 +0100554void Interpreter::DoKeyedStoreIC(Callable ic, InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000555 Node* code_target = __ HeapConstant(ic.code());
556 Node* object_reg_index = __ BytecodeOperandReg(0);
557 Node* object = __ LoadRegister(object_reg_index);
558 Node* name_reg_index = __ BytecodeOperandReg(1);
559 Node* name = __ LoadRegister(name_reg_index);
560 Node* value = __ GetAccumulator();
561 Node* raw_slot = __ BytecodeOperandIdx(2);
562 Node* smi_slot = __ SmiTag(raw_slot);
563 Node* type_feedback_vector = __ LoadTypeFeedbackVector();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100564 Node* context = __ GetContext();
565 __ CallStub(ic.descriptor(), code_target, context, object, name, value,
566 smi_slot, type_feedback_vector);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000567 __ Dispatch();
568}
569
570
571// KeyedStoreICSloppy <object> <key> <slot>
572//
573// Calls the sloppy mode KeyStoreIC at FeedBackVector slot <slot> for <object>
574// and the key <key> with the value in the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100575void Interpreter::DoKeyedStoreICSloppy(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000576 Callable ic =
577 CodeFactory::KeyedStoreICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED);
578 DoKeyedStoreIC(ic, assembler);
579}
580
581
582// KeyedStoreICStore <object> <key> <slot>
583//
584// Calls the strict mode KeyStoreIC at FeedBackVector slot <slot> for <object>
585// and the key <key> with the value in the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100586void Interpreter::DoKeyedStoreICStrict(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000587 Callable ic =
588 CodeFactory::KeyedStoreICInOptimizedCode(isolate_, STRICT, UNINITIALIZED);
589 DoKeyedStoreIC(ic, assembler);
590}
591
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000592// PushContext <context>
593//
Ben Murdoch097c5b22016-05-18 11:27:45 +0100594// Saves the current context in <context>, and pushes the accumulator as the
595// new current context.
596void Interpreter::DoPushContext(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000597 Node* reg_index = __ BytecodeOperandReg(0);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100598 Node* new_context = __ GetAccumulator();
599 Node* old_context = __ GetContext();
600 __ StoreRegister(old_context, reg_index);
601 __ SetContext(new_context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000602 __ Dispatch();
603}
604
605
606// PopContext <context>
607//
608// Pops the current context and sets <context> as the new context.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100609void Interpreter::DoPopContext(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000610 Node* reg_index = __ BytecodeOperandReg(0);
611 Node* context = __ LoadRegister(reg_index);
612 __ SetContext(context);
613 __ Dispatch();
614}
615
Ben Murdochda12d292016-06-02 14:46:10 +0100616void Interpreter::DoBinaryOp(Callable callable,
617 InterpreterAssembler* assembler) {
618 // TODO(bmeurer): Collect definition side type feedback for various
619 // binary operations.
620 Node* target = __ HeapConstant(callable.code());
621 Node* reg_index = __ BytecodeOperandReg(0);
622 Node* lhs = __ LoadRegister(reg_index);
623 Node* rhs = __ GetAccumulator();
624 Node* context = __ GetContext();
625 Node* result = __ CallStub(callable.descriptor(), target, context, lhs, rhs);
626 __ SetAccumulator(result);
627 __ Dispatch();
628}
629
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000630void Interpreter::DoBinaryOp(Runtime::FunctionId function_id,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100631 InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000632 // TODO(rmcilroy): Call ICs which back-patch bytecode with type specialized
633 // operations, instead of calling builtins directly.
634 Node* reg_index = __ BytecodeOperandReg(0);
635 Node* lhs = __ LoadRegister(reg_index);
636 Node* rhs = __ GetAccumulator();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100637 Node* context = __ GetContext();
638 Node* result = __ CallRuntime(function_id, context, lhs, rhs);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000639 __ SetAccumulator(result);
640 __ Dispatch();
641}
642
643
644// Add <src>
645//
646// Add register <src> to accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100647void Interpreter::DoAdd(InterpreterAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +0100648 DoBinaryOp(CodeFactory::Add(isolate_), assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000649}
650
651
652// Sub <src>
653//
654// Subtract register <src> from accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100655void Interpreter::DoSub(InterpreterAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +0100656 DoBinaryOp(CodeFactory::Subtract(isolate_), assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000657}
658
659
660// Mul <src>
661//
662// Multiply accumulator by register <src>.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100663void Interpreter::DoMul(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000664 DoBinaryOp(Runtime::kMultiply, assembler);
665}
666
667
668// Div <src>
669//
670// Divide register <src> by accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100671void Interpreter::DoDiv(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000672 DoBinaryOp(Runtime::kDivide, assembler);
673}
674
675
676// Mod <src>
677//
678// Modulo register <src> by accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100679void Interpreter::DoMod(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000680 DoBinaryOp(Runtime::kModulus, assembler);
681}
682
683
684// BitwiseOr <src>
685//
686// BitwiseOr register <src> to accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100687void Interpreter::DoBitwiseOr(InterpreterAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +0100688 DoBinaryOp(CodeFactory::BitwiseOr(isolate_), assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000689}
690
691
692// BitwiseXor <src>
693//
694// BitwiseXor register <src> to accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100695void Interpreter::DoBitwiseXor(InterpreterAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +0100696 DoBinaryOp(CodeFactory::BitwiseXor(isolate_), assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000697}
698
699
700// BitwiseAnd <src>
701//
702// BitwiseAnd register <src> to accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100703void Interpreter::DoBitwiseAnd(InterpreterAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +0100704 DoBinaryOp(CodeFactory::BitwiseAnd(isolate_), assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000705}
706
707
708// ShiftLeft <src>
709//
710// Left shifts register <src> by the count specified in the accumulator.
711// Register <src> is converted to an int32 and the accumulator to uint32
712// before the operation. 5 lsb bits from the accumulator are used as count
713// i.e. <src> << (accumulator & 0x1F).
Ben Murdoch097c5b22016-05-18 11:27:45 +0100714void Interpreter::DoShiftLeft(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000715 DoBinaryOp(Runtime::kShiftLeft, assembler);
716}
717
718
719// ShiftRight <src>
720//
721// Right shifts register <src> by the count specified in the accumulator.
722// Result is sign extended. Register <src> is converted to an int32 and the
723// accumulator to uint32 before the operation. 5 lsb bits from the accumulator
724// are used as count i.e. <src> >> (accumulator & 0x1F).
Ben Murdoch097c5b22016-05-18 11:27:45 +0100725void Interpreter::DoShiftRight(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000726 DoBinaryOp(Runtime::kShiftRight, assembler);
727}
728
729
730// ShiftRightLogical <src>
731//
732// Right Shifts register <src> by the count specified in the accumulator.
733// Result is zero-filled. The accumulator and register <src> are converted to
734// uint32 before the operation 5 lsb bits from the accumulator are used as
735// count i.e. <src> << (accumulator & 0x1F).
Ben Murdoch097c5b22016-05-18 11:27:45 +0100736void Interpreter::DoShiftRightLogical(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000737 DoBinaryOp(Runtime::kShiftRightLogical, assembler);
738}
739
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000740void Interpreter::DoCountOp(Runtime::FunctionId function_id,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100741 InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000742 Node* value = __ GetAccumulator();
743 Node* one = __ NumberConstant(1);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100744 Node* context = __ GetContext();
745 Node* result = __ CallRuntime(function_id, context, value, one);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000746 __ SetAccumulator(result);
747 __ Dispatch();
748}
749
750
751// Inc
752//
753// Increments value in the accumulator by one.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100754void Interpreter::DoInc(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000755 DoCountOp(Runtime::kAdd, assembler);
756}
757
758
759// Dec
760//
761// Decrements value in the accumulator by one.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100762void Interpreter::DoDec(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000763 DoCountOp(Runtime::kSubtract, assembler);
764}
765
766
767// LogicalNot
768//
769// Perform logical-not on the accumulator, first casting the
770// accumulator to a boolean value if required.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100771void Interpreter::DoLogicalNot(InterpreterAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +0100772 Callable callable = CodeFactory::ToBoolean(isolate_);
773 Node* target = __ HeapConstant(callable.code());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000774 Node* accumulator = __ GetAccumulator();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100775 Node* context = __ GetContext();
Ben Murdochda12d292016-06-02 14:46:10 +0100776 Node* to_boolean_value =
777 __ CallStub(callable.descriptor(), target, context, accumulator);
778 InterpreterAssembler::Label if_true(assembler), if_false(assembler);
779 Node* true_value = __ BooleanConstant(true);
780 Node* false_value = __ BooleanConstant(false);
781 Node* condition = __ WordEqual(to_boolean_value, true_value);
782 __ Branch(condition, &if_true, &if_false);
783 __ Bind(&if_true);
784 {
785 __ SetAccumulator(false_value);
786 __ Dispatch();
787 }
788 __ Bind(&if_false);
789 {
790 __ SetAccumulator(true_value);
791 __ Dispatch();
792 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000793}
794
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000795// TypeOf
796//
797// Load the accumulator with the string representating type of the
798// object in the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100799void Interpreter::DoTypeOf(InterpreterAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +0100800 Callable callable = CodeFactory::Typeof(isolate_);
801 Node* target = __ HeapConstant(callable.code());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000802 Node* accumulator = __ GetAccumulator();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100803 Node* context = __ GetContext();
804 Node* result =
Ben Murdochda12d292016-06-02 14:46:10 +0100805 __ CallStub(callable.descriptor(), target, context, accumulator);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000806 __ SetAccumulator(result);
807 __ Dispatch();
808}
809
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000810void Interpreter::DoDelete(Runtime::FunctionId function_id,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100811 InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000812 Node* reg_index = __ BytecodeOperandReg(0);
813 Node* object = __ LoadRegister(reg_index);
814 Node* key = __ GetAccumulator();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100815 Node* context = __ GetContext();
816 Node* result = __ CallRuntime(function_id, context, object, key);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000817 __ SetAccumulator(result);
818 __ Dispatch();
819}
820
821
822// DeletePropertyStrict
823//
824// Delete the property specified in the accumulator from the object
825// referenced by the register operand following strict mode semantics.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100826void Interpreter::DoDeletePropertyStrict(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000827 DoDelete(Runtime::kDeleteProperty_Strict, assembler);
828}
829
830
831// DeletePropertySloppy
832//
833// Delete the property specified in the accumulator from the object
834// referenced by the register operand following sloppy mode semantics.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100835void Interpreter::DoDeletePropertySloppy(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000836 DoDelete(Runtime::kDeleteProperty_Sloppy, assembler);
837}
838
Ben Murdoch097c5b22016-05-18 11:27:45 +0100839void Interpreter::DoJSCall(InterpreterAssembler* assembler,
840 TailCallMode tail_call_mode) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000841 Node* function_reg = __ BytecodeOperandReg(0);
842 Node* function = __ LoadRegister(function_reg);
843 Node* receiver_reg = __ BytecodeOperandReg(1);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100844 Node* receiver_arg = __ RegisterLocation(receiver_reg);
845 Node* receiver_args_count = __ BytecodeOperandCount(2);
846 Node* receiver_count = __ Int32Constant(1);
847 Node* args_count = __ Int32Sub(receiver_args_count, receiver_count);
848 Node* context = __ GetContext();
849 // TODO(rmcilroy): Use the call type feedback slot to call via CallStub.
850 Node* result =
851 __ CallJS(function, context, receiver_arg, args_count, tail_call_mode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000852 __ SetAccumulator(result);
853 __ Dispatch();
854}
855
856
857// Call <callable> <receiver> <arg_count>
858//
859// Call a JSfunction or Callable in |callable| with the |receiver| and
860// |arg_count| arguments in subsequent registers.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100861void Interpreter::DoCall(InterpreterAssembler* assembler) {
862 DoJSCall(assembler, TailCallMode::kDisallow);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000863}
864
Ben Murdoch097c5b22016-05-18 11:27:45 +0100865// TailCall <callable> <receiver> <arg_count>
866//
867// Tail call a JSfunction or Callable in |callable| with the |receiver| and
868// |arg_count| arguments in subsequent registers.
869void Interpreter::DoTailCall(InterpreterAssembler* assembler) {
870 DoJSCall(assembler, TailCallMode::kAllow);
871}
872
Ben Murdoch097c5b22016-05-18 11:27:45 +0100873void Interpreter::DoCallRuntimeCommon(InterpreterAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +0100874 Node* function_id = __ BytecodeOperandRuntimeId(0);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100875 Node* first_arg_reg = __ BytecodeOperandReg(1);
876 Node* first_arg = __ RegisterLocation(first_arg_reg);
877 Node* args_count = __ BytecodeOperandCount(2);
878 Node* context = __ GetContext();
879 Node* result = __ CallRuntimeN(function_id, context, first_arg, args_count);
880 __ SetAccumulator(result);
881 __ Dispatch();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000882}
883
884
885// CallRuntime <function_id> <first_arg> <arg_count>
886//
887// Call the runtime function |function_id| with the first argument in
888// register |first_arg| and |arg_count| arguments in subsequent
889// registers.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100890void Interpreter::DoCallRuntime(InterpreterAssembler* assembler) {
891 DoCallRuntimeCommon(assembler);
892}
893
Ben Murdochda12d292016-06-02 14:46:10 +0100894// InvokeIntrinsic <function_id> <first_arg> <arg_count>
Ben Murdoch097c5b22016-05-18 11:27:45 +0100895//
Ben Murdochda12d292016-06-02 14:46:10 +0100896// Implements the semantic equivalent of calling the runtime function
897// |function_id| with the first argument in |first_arg| and |arg_count|
898// arguments in subsequent registers.
899void Interpreter::DoInvokeIntrinsic(InterpreterAssembler* assembler) {
900 Node* function_id = __ BytecodeOperandRuntimeId(0);
901 Node* first_arg_reg = __ BytecodeOperandReg(1);
902 Node* arg_count = __ BytecodeOperandCount(2);
903 Node* context = __ GetContext();
904 IntrinsicsHelper helper(assembler);
905 Node* result =
906 helper.InvokeIntrinsic(function_id, context, first_arg_reg, arg_count);
907 __ SetAccumulator(result);
908 __ Dispatch();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100909}
910
911void Interpreter::DoCallRuntimeForPairCommon(InterpreterAssembler* assembler) {
912 // Call the runtime function.
Ben Murdochda12d292016-06-02 14:46:10 +0100913 Node* function_id = __ BytecodeOperandRuntimeId(0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000914 Node* first_arg_reg = __ BytecodeOperandReg(1);
915 Node* first_arg = __ RegisterLocation(first_arg_reg);
916 Node* args_count = __ BytecodeOperandCount(2);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100917 Node* context = __ GetContext();
918 Node* result_pair =
919 __ CallRuntimeN(function_id, context, first_arg, args_count, 2);
920
921 // Store the results in <first_return> and <first_return + 1>
922 Node* first_return_reg = __ BytecodeOperandReg(3);
923 Node* second_return_reg = __ NextRegister(first_return_reg);
924 Node* result0 = __ Projection(0, result_pair);
925 Node* result1 = __ Projection(1, result_pair);
926 __ StoreRegister(result0, first_return_reg);
927 __ StoreRegister(result1, second_return_reg);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000928 __ Dispatch();
929}
930
931
932// CallRuntimeForPair <function_id> <first_arg> <arg_count> <first_return>
933//
934// Call the runtime function |function_id| which returns a pair, with the
935// first argument in register |first_arg| and |arg_count| arguments in
936// subsequent registers. Returns the result in <first_return> and
937// <first_return + 1>
Ben Murdoch097c5b22016-05-18 11:27:45 +0100938void Interpreter::DoCallRuntimeForPair(InterpreterAssembler* assembler) {
939 DoCallRuntimeForPairCommon(assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000940}
941
Ben Murdoch097c5b22016-05-18 11:27:45 +0100942void Interpreter::DoCallJSRuntimeCommon(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000943 Node* context_index = __ BytecodeOperandIdx(0);
944 Node* receiver_reg = __ BytecodeOperandReg(1);
945 Node* first_arg = __ RegisterLocation(receiver_reg);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100946 Node* receiver_args_count = __ BytecodeOperandCount(2);
947 Node* receiver_count = __ Int32Constant(1);
948 Node* args_count = __ Int32Sub(receiver_args_count, receiver_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000949
950 // Get the function to call from the native context.
951 Node* context = __ GetContext();
952 Node* native_context =
953 __ LoadContextSlot(context, Context::NATIVE_CONTEXT_INDEX);
954 Node* function = __ LoadContextSlot(native_context, context_index);
955
956 // Call the function.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100957 Node* result = __ CallJS(function, context, first_arg, args_count,
958 TailCallMode::kDisallow);
959 __ SetAccumulator(result);
960 __ Dispatch();
961}
962
963
964// CallJSRuntime <context_index> <receiver> <arg_count>
965//
966// Call the JS runtime function that has the |context_index| with the receiver
967// in register |receiver| and |arg_count| arguments in subsequent registers.
968void Interpreter::DoCallJSRuntime(InterpreterAssembler* assembler) {
969 DoCallJSRuntimeCommon(assembler);
970}
971
Ben Murdoch097c5b22016-05-18 11:27:45 +0100972void Interpreter::DoCallConstruct(InterpreterAssembler* assembler) {
973 Callable ic = CodeFactory::InterpreterPushArgsAndConstruct(isolate_);
974 Node* new_target = __ GetAccumulator();
975 Node* constructor_reg = __ BytecodeOperandReg(0);
976 Node* constructor = __ LoadRegister(constructor_reg);
977 Node* first_arg_reg = __ BytecodeOperandReg(1);
978 Node* first_arg = __ RegisterLocation(first_arg_reg);
979 Node* args_count = __ BytecodeOperandCount(2);
980 Node* context = __ GetContext();
981 Node* result =
982 __ CallConstruct(constructor, context, new_target, first_arg, args_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000983 __ SetAccumulator(result);
984 __ Dispatch();
985}
986
987
988// New <constructor> <first_arg> <arg_count>
989//
990// Call operator new with |constructor| and the first argument in
991// register |first_arg| and |arg_count| arguments in subsequent
Ben Murdoch097c5b22016-05-18 11:27:45 +0100992// registers. The new.target is in the accumulator.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000993//
Ben Murdoch097c5b22016-05-18 11:27:45 +0100994void Interpreter::DoNew(InterpreterAssembler* assembler) {
995 DoCallConstruct(assembler);
996}
997
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000998// TestEqual <src>
999//
1000// Test if the value in the <src> register equals the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001001void Interpreter::DoTestEqual(InterpreterAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +01001002 DoBinaryOp(CodeFactory::Equal(isolate_), assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001003}
1004
1005
1006// TestNotEqual <src>
1007//
1008// Test if the value in the <src> register is not equal to the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001009void Interpreter::DoTestNotEqual(InterpreterAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +01001010 DoBinaryOp(CodeFactory::NotEqual(isolate_), assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001011}
1012
1013
1014// TestEqualStrict <src>
1015//
1016// Test if the value in the <src> register is strictly equal to the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001017void Interpreter::DoTestEqualStrict(InterpreterAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +01001018 DoBinaryOp(CodeFactory::StrictEqual(isolate_), assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001019}
1020
1021
1022// TestLessThan <src>
1023//
1024// Test if the value in the <src> register is less than the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001025void Interpreter::DoTestLessThan(InterpreterAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +01001026 DoBinaryOp(CodeFactory::LessThan(isolate_), assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001027}
1028
1029
1030// TestGreaterThan <src>
1031//
1032// Test if the value in the <src> register is greater than the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001033void Interpreter::DoTestGreaterThan(InterpreterAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +01001034 DoBinaryOp(CodeFactory::GreaterThan(isolate_), assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001035}
1036
1037
1038// TestLessThanOrEqual <src>
1039//
1040// Test if the value in the <src> register is less than or equal to the
1041// accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001042void Interpreter::DoTestLessThanOrEqual(InterpreterAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +01001043 DoBinaryOp(CodeFactory::LessThanOrEqual(isolate_), assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001044}
1045
1046
1047// TestGreaterThanOrEqual <src>
1048//
1049// Test if the value in the <src> register is greater than or equal to the
1050// accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001051void Interpreter::DoTestGreaterThanOrEqual(InterpreterAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +01001052 DoBinaryOp(CodeFactory::GreaterThanOrEqual(isolate_), assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001053}
1054
1055
1056// TestIn <src>
1057//
1058// Test if the object referenced by the register operand is a property of the
1059// object referenced by the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001060void Interpreter::DoTestIn(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001061 DoBinaryOp(Runtime::kHasProperty, assembler);
1062}
1063
1064
1065// TestInstanceOf <src>
1066//
1067// Test if the object referenced by the <src> register is an an instance of type
1068// referenced by the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001069void Interpreter::DoTestInstanceOf(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001070 DoBinaryOp(Runtime::kInstanceOf, assembler);
1071}
1072
Ben Murdochda12d292016-06-02 14:46:10 +01001073void Interpreter::DoTypeConversionOp(Callable callable,
1074 InterpreterAssembler* assembler) {
1075 Node* target = __ HeapConstant(callable.code());
1076 Node* accumulator = __ GetAccumulator();
1077 Node* context = __ GetContext();
1078 Node* result =
1079 __ CallStub(callable.descriptor(), target, context, accumulator);
1080 __ SetAccumulator(result);
1081 __ Dispatch();
1082}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001083
1084// ToName
1085//
1086// Cast the object referenced by the accumulator to a name.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001087void Interpreter::DoToName(InterpreterAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +01001088 DoTypeConversionOp(CodeFactory::ToName(isolate_), assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001089}
1090
1091
1092// ToNumber
1093//
1094// Cast the object referenced by the accumulator to a number.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001095void Interpreter::DoToNumber(InterpreterAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +01001096 DoTypeConversionOp(CodeFactory::ToNumber(isolate_), assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001097}
1098
1099
1100// ToObject
1101//
1102// Cast the object referenced by the accumulator to a JSObject.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001103void Interpreter::DoToObject(InterpreterAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +01001104 DoTypeConversionOp(CodeFactory::ToObject(isolate_), assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001105}
1106
Ben Murdochda12d292016-06-02 14:46:10 +01001107// Jump <imm>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001108//
Ben Murdochda12d292016-06-02 14:46:10 +01001109// Jump by number of bytes represented by the immediate operand |imm|.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001110void Interpreter::DoJump(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001111 Node* relative_jump = __ BytecodeOperandImm(0);
1112 __ Jump(relative_jump);
1113}
1114
Ben Murdochda12d292016-06-02 14:46:10 +01001115// JumpConstant <idx>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001116//
Ben Murdochda12d292016-06-02 14:46:10 +01001117// Jump by number of bytes in the Smi in the |idx| entry in the constant pool.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001118void Interpreter::DoJumpConstant(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001119 Node* index = __ BytecodeOperandIdx(0);
1120 Node* constant = __ LoadConstantPoolEntry(index);
1121 Node* relative_jump = __ SmiUntag(constant);
1122 __ Jump(relative_jump);
1123}
1124
Ben Murdochda12d292016-06-02 14:46:10 +01001125// JumpIfTrue <imm>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001126//
1127// Jump by number of bytes represented by an immediate operand if the
1128// accumulator contains true.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001129void Interpreter::DoJumpIfTrue(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001130 Node* accumulator = __ GetAccumulator();
1131 Node* relative_jump = __ BytecodeOperandImm(0);
1132 Node* true_value = __ BooleanConstant(true);
1133 __ JumpIfWordEqual(accumulator, true_value, relative_jump);
1134}
1135
Ben Murdochda12d292016-06-02 14:46:10 +01001136// JumpIfTrueConstant <idx>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001137//
Ben Murdochda12d292016-06-02 14:46:10 +01001138// Jump by number of bytes in the Smi in the |idx| entry in the constant pool
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001139// if the accumulator contains true.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001140void Interpreter::DoJumpIfTrueConstant(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001141 Node* accumulator = __ GetAccumulator();
1142 Node* index = __ BytecodeOperandIdx(0);
1143 Node* constant = __ LoadConstantPoolEntry(index);
1144 Node* relative_jump = __ SmiUntag(constant);
1145 Node* true_value = __ BooleanConstant(true);
1146 __ JumpIfWordEqual(accumulator, true_value, relative_jump);
1147}
1148
Ben Murdochda12d292016-06-02 14:46:10 +01001149// JumpIfFalse <imm>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001150//
1151// Jump by number of bytes represented by an immediate operand if the
1152// accumulator contains false.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001153void Interpreter::DoJumpIfFalse(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001154 Node* accumulator = __ GetAccumulator();
1155 Node* relative_jump = __ BytecodeOperandImm(0);
1156 Node* false_value = __ BooleanConstant(false);
1157 __ JumpIfWordEqual(accumulator, false_value, relative_jump);
1158}
1159
Ben Murdochda12d292016-06-02 14:46:10 +01001160// JumpIfFalseConstant <idx>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001161//
Ben Murdochda12d292016-06-02 14:46:10 +01001162// Jump by number of bytes in the Smi in the |idx| entry in the constant pool
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001163// if the accumulator contains false.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001164void Interpreter::DoJumpIfFalseConstant(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001165 Node* accumulator = __ GetAccumulator();
1166 Node* index = __ BytecodeOperandIdx(0);
1167 Node* constant = __ LoadConstantPoolEntry(index);
1168 Node* relative_jump = __ SmiUntag(constant);
1169 Node* false_value = __ BooleanConstant(false);
1170 __ JumpIfWordEqual(accumulator, false_value, relative_jump);
1171}
1172
Ben Murdochda12d292016-06-02 14:46:10 +01001173// JumpIfToBooleanTrue <imm>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001174//
1175// Jump by number of bytes represented by an immediate operand if the object
1176// referenced by the accumulator is true when the object is cast to boolean.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001177void Interpreter::DoJumpIfToBooleanTrue(InterpreterAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +01001178 Callable callable = CodeFactory::ToBoolean(isolate_);
1179 Node* target = __ HeapConstant(callable.code());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001180 Node* accumulator = __ GetAccumulator();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001181 Node* context = __ GetContext();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001182 Node* to_boolean_value =
Ben Murdochda12d292016-06-02 14:46:10 +01001183 __ CallStub(callable.descriptor(), target, context, accumulator);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001184 Node* relative_jump = __ BytecodeOperandImm(0);
1185 Node* true_value = __ BooleanConstant(true);
1186 __ JumpIfWordEqual(to_boolean_value, true_value, relative_jump);
1187}
1188
Ben Murdochda12d292016-06-02 14:46:10 +01001189// JumpIfToBooleanTrueConstant <idx>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001190//
Ben Murdochda12d292016-06-02 14:46:10 +01001191// Jump by number of bytes in the Smi in the |idx| entry in the constant pool
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001192// if the object referenced by the accumulator is true when the object is cast
1193// to boolean.
1194void Interpreter::DoJumpIfToBooleanTrueConstant(
Ben Murdoch097c5b22016-05-18 11:27:45 +01001195 InterpreterAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +01001196 Callable callable = CodeFactory::ToBoolean(isolate_);
1197 Node* target = __ HeapConstant(callable.code());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001198 Node* accumulator = __ GetAccumulator();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001199 Node* context = __ GetContext();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001200 Node* to_boolean_value =
Ben Murdochda12d292016-06-02 14:46:10 +01001201 __ CallStub(callable.descriptor(), target, context, accumulator);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001202 Node* index = __ BytecodeOperandIdx(0);
1203 Node* constant = __ LoadConstantPoolEntry(index);
1204 Node* relative_jump = __ SmiUntag(constant);
1205 Node* true_value = __ BooleanConstant(true);
1206 __ JumpIfWordEqual(to_boolean_value, true_value, relative_jump);
1207}
1208
Ben Murdochda12d292016-06-02 14:46:10 +01001209// JumpIfToBooleanFalse <imm>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001210//
1211// Jump by number of bytes represented by an immediate operand if the object
1212// referenced by the accumulator is false when the object is cast to boolean.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001213void Interpreter::DoJumpIfToBooleanFalse(InterpreterAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +01001214 Callable callable = CodeFactory::ToBoolean(isolate_);
1215 Node* target = __ HeapConstant(callable.code());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001216 Node* accumulator = __ GetAccumulator();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001217 Node* context = __ GetContext();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001218 Node* to_boolean_value =
Ben Murdochda12d292016-06-02 14:46:10 +01001219 __ CallStub(callable.descriptor(), target, context, accumulator);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001220 Node* relative_jump = __ BytecodeOperandImm(0);
1221 Node* false_value = __ BooleanConstant(false);
1222 __ JumpIfWordEqual(to_boolean_value, false_value, relative_jump);
1223}
1224
Ben Murdochda12d292016-06-02 14:46:10 +01001225// JumpIfToBooleanFalseConstant <idx>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001226//
Ben Murdochda12d292016-06-02 14:46:10 +01001227// Jump by number of bytes in the Smi in the |idx| entry in the constant pool
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001228// if the object referenced by the accumulator is false when the object is cast
1229// to boolean.
1230void Interpreter::DoJumpIfToBooleanFalseConstant(
Ben Murdoch097c5b22016-05-18 11:27:45 +01001231 InterpreterAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +01001232 Callable callable = CodeFactory::ToBoolean(isolate_);
1233 Node* target = __ HeapConstant(callable.code());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001234 Node* accumulator = __ GetAccumulator();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001235 Node* context = __ GetContext();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001236 Node* to_boolean_value =
Ben Murdochda12d292016-06-02 14:46:10 +01001237 __ CallStub(callable.descriptor(), target, context, accumulator);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001238 Node* index = __ BytecodeOperandIdx(0);
1239 Node* constant = __ LoadConstantPoolEntry(index);
1240 Node* relative_jump = __ SmiUntag(constant);
1241 Node* false_value = __ BooleanConstant(false);
1242 __ JumpIfWordEqual(to_boolean_value, false_value, relative_jump);
1243}
1244
Ben Murdochda12d292016-06-02 14:46:10 +01001245// JumpIfNull <imm>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001246//
1247// Jump by number of bytes represented by an immediate operand if the object
1248// referenced by the accumulator is the null constant.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001249void Interpreter::DoJumpIfNull(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001250 Node* accumulator = __ GetAccumulator();
1251 Node* null_value = __ HeapConstant(isolate_->factory()->null_value());
1252 Node* relative_jump = __ BytecodeOperandImm(0);
1253 __ JumpIfWordEqual(accumulator, null_value, relative_jump);
1254}
1255
Ben Murdochda12d292016-06-02 14:46:10 +01001256// JumpIfNullConstant <idx>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001257//
Ben Murdochda12d292016-06-02 14:46:10 +01001258// Jump by number of bytes in the Smi in the |idx| entry in the constant pool
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001259// if the object referenced by the accumulator is the null constant.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001260void Interpreter::DoJumpIfNullConstant(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001261 Node* accumulator = __ GetAccumulator();
1262 Node* null_value = __ HeapConstant(isolate_->factory()->null_value());
1263 Node* index = __ BytecodeOperandIdx(0);
1264 Node* constant = __ LoadConstantPoolEntry(index);
1265 Node* relative_jump = __ SmiUntag(constant);
1266 __ JumpIfWordEqual(accumulator, null_value, relative_jump);
1267}
1268
Ben Murdochda12d292016-06-02 14:46:10 +01001269// JumpIfUndefined <imm>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001270//
1271// Jump by number of bytes represented by an immediate operand if the object
1272// referenced by the accumulator is the undefined constant.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001273void Interpreter::DoJumpIfUndefined(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001274 Node* accumulator = __ GetAccumulator();
1275 Node* undefined_value =
1276 __ HeapConstant(isolate_->factory()->undefined_value());
1277 Node* relative_jump = __ BytecodeOperandImm(0);
1278 __ JumpIfWordEqual(accumulator, undefined_value, relative_jump);
1279}
1280
Ben Murdochda12d292016-06-02 14:46:10 +01001281// JumpIfUndefinedConstant <idx>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001282//
Ben Murdochda12d292016-06-02 14:46:10 +01001283// Jump by number of bytes in the Smi in the |idx| entry in the constant pool
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001284// if the object referenced by the accumulator is the undefined constant.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001285void Interpreter::DoJumpIfUndefinedConstant(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001286 Node* accumulator = __ GetAccumulator();
1287 Node* undefined_value =
1288 __ HeapConstant(isolate_->factory()->undefined_value());
1289 Node* index = __ BytecodeOperandIdx(0);
1290 Node* constant = __ LoadConstantPoolEntry(index);
1291 Node* relative_jump = __ SmiUntag(constant);
1292 __ JumpIfWordEqual(accumulator, undefined_value, relative_jump);
1293}
1294
Ben Murdochda12d292016-06-02 14:46:10 +01001295// JumpIfNotHole <imm>
Ben Murdoch097c5b22016-05-18 11:27:45 +01001296//
1297// Jump by number of bytes represented by an immediate operand if the object
1298// referenced by the accumulator is the hole.
1299void Interpreter::DoJumpIfNotHole(InterpreterAssembler* assembler) {
1300 Node* accumulator = __ GetAccumulator();
1301 Node* the_hole_value = __ HeapConstant(isolate_->factory()->the_hole_value());
1302 Node* relative_jump = __ BytecodeOperandImm(0);
1303 __ JumpIfWordNotEqual(accumulator, the_hole_value, relative_jump);
1304}
1305
Ben Murdochda12d292016-06-02 14:46:10 +01001306// JumpIfNotHoleConstant <idx>
Ben Murdoch097c5b22016-05-18 11:27:45 +01001307//
Ben Murdochda12d292016-06-02 14:46:10 +01001308// Jump by number of bytes in the Smi in the |idx| entry in the constant pool
Ben Murdoch097c5b22016-05-18 11:27:45 +01001309// if the object referenced by the accumulator is the hole constant.
1310void Interpreter::DoJumpIfNotHoleConstant(InterpreterAssembler* assembler) {
1311 Node* accumulator = __ GetAccumulator();
1312 Node* the_hole_value = __ HeapConstant(isolate_->factory()->the_hole_value());
1313 Node* index = __ BytecodeOperandIdx(0);
1314 Node* constant = __ LoadConstantPoolEntry(index);
1315 Node* relative_jump = __ SmiUntag(constant);
1316 __ JumpIfWordNotEqual(accumulator, the_hole_value, relative_jump);
1317}
1318
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001319void Interpreter::DoCreateLiteral(Runtime::FunctionId function_id,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001320 InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001321 Node* index = __ BytecodeOperandIdx(0);
1322 Node* constant_elements = __ LoadConstantPoolEntry(index);
1323 Node* literal_index_raw = __ BytecodeOperandIdx(1);
1324 Node* literal_index = __ SmiTag(literal_index_raw);
Ben Murdochda12d292016-06-02 14:46:10 +01001325 Node* flags_raw = __ BytecodeOperandFlag(2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001326 Node* flags = __ SmiTag(flags_raw);
1327 Node* closure = __ LoadRegister(Register::function_closure());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001328 Node* context = __ GetContext();
1329 Node* result = __ CallRuntime(function_id, context, closure, literal_index,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001330 constant_elements, flags);
1331 __ SetAccumulator(result);
1332 __ Dispatch();
1333}
1334
1335
1336// CreateRegExpLiteral <pattern_idx> <literal_idx> <flags>
1337//
1338// Creates a regular expression literal for literal index <literal_idx> with
1339// <flags> and the pattern in <pattern_idx>.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001340void Interpreter::DoCreateRegExpLiteral(InterpreterAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +01001341 Callable callable = CodeFactory::FastCloneRegExp(isolate_);
1342 Node* target = __ HeapConstant(callable.code());
1343 Node* index = __ BytecodeOperandIdx(0);
1344 Node* pattern = __ LoadConstantPoolEntry(index);
1345 Node* literal_index_raw = __ BytecodeOperandIdx(1);
1346 Node* literal_index = __ SmiTag(literal_index_raw);
1347 Node* flags_raw = __ BytecodeOperandFlag(2);
1348 Node* flags = __ SmiTag(flags_raw);
1349 Node* closure = __ LoadRegister(Register::function_closure());
1350 Node* context = __ GetContext();
1351 Node* result = __ CallStub(callable.descriptor(), target, context, closure,
1352 literal_index, pattern, flags);
1353 __ SetAccumulator(result);
1354 __ Dispatch();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001355}
1356
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001357// CreateArrayLiteral <element_idx> <literal_idx> <flags>
1358//
1359// Creates an array literal for literal index <literal_idx> with flags <flags>
1360// and constant elements in <element_idx>.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001361void Interpreter::DoCreateArrayLiteral(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001362 DoCreateLiteral(Runtime::kCreateArrayLiteral, assembler);
1363}
1364
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001365// CreateObjectLiteral <element_idx> <literal_idx> <flags>
1366//
1367// Creates an object literal for literal index <literal_idx> with flags <flags>
1368// and constant elements in <element_idx>.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001369void Interpreter::DoCreateObjectLiteral(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001370 DoCreateLiteral(Runtime::kCreateObjectLiteral, assembler);
1371}
1372
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001373// CreateClosure <index> <tenured>
1374//
1375// Creates a new closure for SharedFunctionInfo at position |index| in the
1376// constant pool and with the PretenureFlag <tenured>.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001377void Interpreter::DoCreateClosure(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001378 // TODO(rmcilroy): Possibly call FastNewClosureStub when possible instead of
1379 // calling into the runtime.
1380 Node* index = __ BytecodeOperandIdx(0);
1381 Node* shared = __ LoadConstantPoolEntry(index);
Ben Murdochda12d292016-06-02 14:46:10 +01001382 Node* tenured_raw = __ BytecodeOperandFlag(1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001383 Node* tenured = __ SmiTag(tenured_raw);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001384 Node* context = __ GetContext();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001385 Node* result =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001386 __ CallRuntime(Runtime::kInterpreterNewClosure, context, shared, tenured);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001387 __ SetAccumulator(result);
1388 __ Dispatch();
1389}
1390
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001391// CreateMappedArguments
1392//
1393// Creates a new mapped arguments object.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001394void Interpreter::DoCreateMappedArguments(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001395 Node* closure = __ LoadRegister(Register::function_closure());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001396 Node* context = __ GetContext();
1397 Node* result =
1398 __ CallRuntime(Runtime::kNewSloppyArguments_Generic, context, closure);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001399 __ SetAccumulator(result);
1400 __ Dispatch();
1401}
1402
1403
1404// CreateUnmappedArguments
1405//
1406// Creates a new unmapped arguments object.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001407void Interpreter::DoCreateUnmappedArguments(InterpreterAssembler* assembler) {
1408 Callable callable = CodeFactory::FastNewStrictArguments(isolate_);
1409 Node* target = __ HeapConstant(callable.code());
1410 Node* context = __ GetContext();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001411 Node* closure = __ LoadRegister(Register::function_closure());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001412 Node* result = __ CallStub(callable.descriptor(), target, context, closure);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001413 __ SetAccumulator(result);
1414 __ Dispatch();
1415}
1416
Ben Murdoch097c5b22016-05-18 11:27:45 +01001417// CreateRestParameter
1418//
1419// Creates a new rest parameter array.
1420void Interpreter::DoCreateRestParameter(InterpreterAssembler* assembler) {
1421 Callable callable = CodeFactory::FastNewRestParameter(isolate_);
1422 Node* target = __ HeapConstant(callable.code());
1423 Node* closure = __ LoadRegister(Register::function_closure());
1424 Node* context = __ GetContext();
1425 Node* result = __ CallStub(callable.descriptor(), target, context, closure);
1426 __ SetAccumulator(result);
1427 __ Dispatch();
1428}
1429
1430// StackCheck
1431//
1432// Performs a stack guard check.
1433void Interpreter::DoStackCheck(InterpreterAssembler* assembler) {
1434 __ StackCheck();
1435 __ Dispatch();
1436}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001437
1438// Throw
1439//
1440// Throws the exception in the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001441void Interpreter::DoThrow(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001442 Node* exception = __ GetAccumulator();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001443 Node* context = __ GetContext();
1444 __ CallRuntime(Runtime::kThrow, context, exception);
1445 // We shouldn't ever return from a throw.
1446 __ Abort(kUnexpectedReturnFromThrow);
1447}
1448
1449
1450// ReThrow
1451//
1452// Re-throws the exception in the accumulator.
1453void Interpreter::DoReThrow(InterpreterAssembler* assembler) {
1454 Node* exception = __ GetAccumulator();
1455 Node* context = __ GetContext();
1456 __ CallRuntime(Runtime::kReThrow, context, exception);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001457 // We shouldn't ever return from a throw.
1458 __ Abort(kUnexpectedReturnFromThrow);
1459}
1460
1461
1462// Return
1463//
1464// Return the value in the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001465void Interpreter::DoReturn(InterpreterAssembler* assembler) {
1466 __ InterpreterReturn();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001467}
1468
Ben Murdoch097c5b22016-05-18 11:27:45 +01001469// Debugger
1470//
1471// Call runtime to handle debugger statement.
1472void Interpreter::DoDebugger(InterpreterAssembler* assembler) {
1473 Node* context = __ GetContext();
1474 __ CallRuntime(Runtime::kHandleDebuggerStatement, context);
1475 __ Dispatch();
1476}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001477
Ben Murdoch097c5b22016-05-18 11:27:45 +01001478// DebugBreak
1479//
1480// Call runtime to handle a debug break.
Ben Murdochda12d292016-06-02 14:46:10 +01001481#define DEBUG_BREAK(Name, ...) \
1482 void Interpreter::Do##Name(InterpreterAssembler* assembler) { \
1483 Node* context = __ GetContext(); \
1484 Node* accumulator = __ GetAccumulator(); \
1485 Node* original_handler = \
1486 __ CallRuntime(Runtime::kDebugBreakOnBytecode, context, accumulator); \
1487 __ DispatchToBytecodeHandler(original_handler); \
Ben Murdoch097c5b22016-05-18 11:27:45 +01001488 }
1489DEBUG_BREAK_BYTECODE_LIST(DEBUG_BREAK);
1490#undef DEBUG_BREAK
1491
1492// ForInPrepare <cache_info_triple>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001493//
1494// Returns state for for..in loop execution based on the object in the
Ben Murdoch097c5b22016-05-18 11:27:45 +01001495// accumulator. The result is output in registers |cache_info_triple| to
1496// |cache_info_triple + 2|, with the registers holding cache_type, cache_array,
1497// and cache_length respectively.
1498void Interpreter::DoForInPrepare(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001499 Node* object = __ GetAccumulator();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001500 Node* context = __ GetContext();
1501 Node* result_triple = __ CallRuntime(Runtime::kForInPrepare, context, object);
1502
1503 // Set output registers:
1504 // 0 == cache_type, 1 == cache_array, 2 == cache_length
1505 Node* output_register = __ BytecodeOperandReg(0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001506 for (int i = 0; i < 3; i++) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001507 Node* cache_info = __ Projection(i, result_triple);
1508 __ StoreRegister(cache_info, output_register);
1509 output_register = __ NextRegister(output_register);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001510 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001511 __ Dispatch();
1512}
1513
Ben Murdoch097c5b22016-05-18 11:27:45 +01001514// ForInNext <receiver> <index> <cache_info_pair>
1515//
1516// Returns the next enumerable property in the the accumulator.
1517void Interpreter::DoForInNext(InterpreterAssembler* assembler) {
1518 Node* receiver_reg = __ BytecodeOperandReg(0);
1519 Node* receiver = __ LoadRegister(receiver_reg);
1520 Node* index_reg = __ BytecodeOperandReg(1);
1521 Node* index = __ LoadRegister(index_reg);
1522 Node* cache_type_reg = __ BytecodeOperandReg(2);
1523 Node* cache_type = __ LoadRegister(cache_type_reg);
1524 Node* cache_array_reg = __ NextRegister(cache_type_reg);
1525 Node* cache_array = __ LoadRegister(cache_array_reg);
Ben Murdochda12d292016-06-02 14:46:10 +01001526
1527 // Load the next key from the enumeration array.
1528 Node* key = __ LoadFixedArrayElementSmiIndex(cache_array, index);
1529
1530 // Check if we can use the for-in fast path potentially using the enum cache.
1531 InterpreterAssembler::Label if_fast(assembler), if_slow(assembler);
1532 Node* receiver_map = __ LoadObjectField(receiver, HeapObject::kMapOffset);
1533 Node* condition = __ WordEqual(receiver_map, cache_type);
1534 __ Branch(condition, &if_fast, &if_slow);
1535 __ Bind(&if_fast);
1536 {
1537 // Enum cache in use for {receiver}, the {key} is definitely valid.
1538 __ SetAccumulator(key);
1539 __ Dispatch();
1540 }
1541 __ Bind(&if_slow);
1542 {
1543 // Record the fact that we hit the for-in slow path.
1544 Node* vector_index = __ BytecodeOperandIdx(3);
1545 Node* type_feedback_vector = __ LoadTypeFeedbackVector();
1546 Node* megamorphic_sentinel =
1547 __ HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate_));
1548 __ StoreFixedArrayElementNoWriteBarrier(type_feedback_vector, vector_index,
1549 megamorphic_sentinel);
1550
1551 // Need to filter the {key} for the {receiver}.
1552 Node* context = __ GetContext();
1553 Node* result =
1554 __ CallRuntime(Runtime::kForInFilter, context, receiver, key);
1555 __ SetAccumulator(result);
1556 __ Dispatch();
1557 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001558}
1559
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001560// ForInDone <index> <cache_length>
1561//
1562// Returns true if the end of the enumerable properties has been reached.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001563void Interpreter::DoForInDone(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001564 Node* index_reg = __ BytecodeOperandReg(0);
1565 Node* index = __ LoadRegister(index_reg);
1566 Node* cache_length_reg = __ BytecodeOperandReg(1);
1567 Node* cache_length = __ LoadRegister(cache_length_reg);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001568
Ben Murdochda12d292016-06-02 14:46:10 +01001569 // Check if {index} is at {cache_length} already.
1570 InterpreterAssembler::Label if_true(assembler), if_false(assembler);
1571 Node* condition = __ WordEqual(index, cache_length);
1572 __ Branch(condition, &if_true, &if_false);
1573 __ Bind(&if_true);
1574 {
1575 Node* result = __ BooleanConstant(true);
1576 __ SetAccumulator(result);
1577 __ Dispatch();
1578 }
1579 __ Bind(&if_false);
1580 {
1581 Node* result = __ BooleanConstant(false);
1582 __ SetAccumulator(result);
1583 __ Dispatch();
1584 }
1585}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001586
1587// ForInStep <index>
1588//
1589// Increments the loop counter in register |index| and stores the result
1590// in the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001591void Interpreter::DoForInStep(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001592 Node* index_reg = __ BytecodeOperandReg(0);
1593 Node* index = __ LoadRegister(index_reg);
Ben Murdochda12d292016-06-02 14:46:10 +01001594 Node* one = __ SmiConstant(Smi::FromInt(1));
1595 Node* result = __ SmiAdd(index, one);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001596 __ SetAccumulator(result);
1597 __ Dispatch();
1598}
1599
Ben Murdochda12d292016-06-02 14:46:10 +01001600// Wide
1601//
1602// Prefix bytecode indicating next bytecode has wide (16-bit) operands.
1603void Interpreter::DoWide(InterpreterAssembler* assembler) {
1604 __ DispatchWide(OperandScale::kDouble);
1605}
1606
1607// ExtraWide
1608//
1609// Prefix bytecode indicating next bytecode has extra-wide (32-bit) operands.
1610void Interpreter::DoExtraWide(InterpreterAssembler* assembler) {
1611 __ DispatchWide(OperandScale::kQuadruple);
1612}
1613
1614// Illegal
1615//
1616// An invalid bytecode aborting execution if dispatched.
1617void Interpreter::DoIllegal(InterpreterAssembler* assembler) {
1618 __ Abort(kInvalidBytecode);
1619}
1620
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001621} // namespace interpreter
1622} // namespace internal
1623} // namespace v8