blob: 8a05777818ded7d37187c4f91ab4ba7da9b3d584 [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 Murdochc5610432016-08-08 18:44:38 +01007#include <fstream>
8
Ben Murdoch097c5b22016-05-18 11:27:45 +01009#include "src/ast/prettyprinter.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010#include "src/code-factory.h"
11#include "src/compiler.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012#include "src/factory.h"
13#include "src/interpreter/bytecode-generator.h"
14#include "src/interpreter/bytecodes.h"
Ben Murdoch097c5b22016-05-18 11:27:45 +010015#include "src/interpreter/interpreter-assembler.h"
Ben Murdochda12d292016-06-02 14:46:10 +010016#include "src/interpreter/interpreter-intrinsics.h"
17#include "src/log.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018#include "src/zone.h"
19
20namespace v8 {
21namespace internal {
22namespace interpreter {
23
24using compiler::Node;
Ben Murdochc5610432016-08-08 18:44:38 +010025typedef CodeStubAssembler::Label Label;
26typedef CodeStubAssembler::Variable Variable;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000027
28#define __ assembler->
29
Ben Murdoch097c5b22016-05-18 11:27:45 +010030Interpreter::Interpreter(Isolate* isolate) : isolate_(isolate) {
Ben Murdochda12d292016-06-02 14:46:10 +010031 memset(dispatch_table_, 0, sizeof(dispatch_table_));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000032}
33
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000034void Interpreter::Initialize() {
Ben Murdoch097c5b22016-05-18 11:27:45 +010035 if (IsDispatchTableInitialized()) return;
Ben Murdochda12d292016-06-02 14:46:10 +010036 Zone zone(isolate_->allocator());
Ben Murdoch097c5b22016-05-18 11:27:45 +010037 HandleScope scope(isolate_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000038
Ben Murdochc5610432016-08-08 18:44:38 +010039 if (FLAG_trace_ignition_dispatches) {
40 static const int kBytecodeCount = static_cast<int>(Bytecode::kLast) + 1;
41 bytecode_dispatch_counters_table_.Reset(
42 new uintptr_t[kBytecodeCount * kBytecodeCount]);
43 memset(bytecode_dispatch_counters_table_.get(), 0,
44 sizeof(uintptr_t) * kBytecodeCount * kBytecodeCount);
45 }
46
Ben Murdochda12d292016-06-02 14:46:10 +010047 // Generate bytecode handlers for all bytecodes and scales.
Ben Murdochc5610432016-08-08 18:44:38 +010048 const OperandScale kOperandScales[] = {
49#define VALUE(Name, _) OperandScale::k##Name,
50 OPERAND_SCALE_LIST(VALUE)
51#undef VALUE
52 };
53
54 for (OperandScale operand_scale : kOperandScales) {
Ben Murdochda12d292016-06-02 14:46:10 +010055#define GENERATE_CODE(Name, ...) \
56 { \
57 if (Bytecodes::BytecodeHasHandler(Bytecode::k##Name, operand_scale)) { \
58 InterpreterAssembler assembler(isolate_, &zone, Bytecode::k##Name, \
59 operand_scale); \
60 Do##Name(&assembler); \
61 Handle<Code> code = assembler.GenerateCode(); \
62 size_t index = GetDispatchTableIndex(Bytecode::k##Name, operand_scale); \
Ben Murdochc5610432016-08-08 18:44:38 +010063 dispatch_table_[index] = code->entry(); \
Ben Murdochda12d292016-06-02 14:46:10 +010064 TraceCodegen(code); \
Ben Murdoch61f157c2016-09-16 13:49:30 +010065 PROFILE( \
Ben Murdochda12d292016-06-02 14:46:10 +010066 isolate_, \
67 CodeCreateEvent( \
Ben Murdoch61f157c2016-09-16 13:49:30 +010068 CodeEventListener::BYTECODE_HANDLER_TAG, \
69 AbstractCode::cast(*code), \
Ben Murdochda12d292016-06-02 14:46:10 +010070 Bytecodes::ToString(Bytecode::k##Name, operand_scale).c_str())); \
71 } \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000072 }
Ben Murdochda12d292016-06-02 14:46:10 +010073 BYTECODE_LIST(GENERATE_CODE)
Ben Murdoch097c5b22016-05-18 11:27:45 +010074#undef GENERATE_CODE
Ben Murdochda12d292016-06-02 14:46:10 +010075 }
76
77 // Fill unused entries will the illegal bytecode handler.
78 size_t illegal_index =
79 GetDispatchTableIndex(Bytecode::kIllegal, OperandScale::kSingle);
80 for (size_t index = 0; index < arraysize(dispatch_table_); ++index) {
81 if (dispatch_table_[index] == nullptr) {
82 dispatch_table_[index] = dispatch_table_[illegal_index];
83 }
84 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000085}
86
Ben Murdochda12d292016-06-02 14:46:10 +010087Code* Interpreter::GetBytecodeHandler(Bytecode bytecode,
88 OperandScale operand_scale) {
Ben Murdoch097c5b22016-05-18 11:27:45 +010089 DCHECK(IsDispatchTableInitialized());
Ben Murdochda12d292016-06-02 14:46:10 +010090 DCHECK(Bytecodes::BytecodeHasHandler(bytecode, operand_scale));
91 size_t index = GetDispatchTableIndex(bytecode, operand_scale);
Ben Murdochc5610432016-08-08 18:44:38 +010092 Address code_entry = dispatch_table_[index];
93 return Code::GetCodeFromTargetAddress(code_entry);
Ben Murdochda12d292016-06-02 14:46:10 +010094}
95
96// static
97size_t Interpreter::GetDispatchTableIndex(Bytecode bytecode,
98 OperandScale operand_scale) {
99 static const size_t kEntriesPerOperandScale = 1u << kBitsPerByte;
100 size_t index = static_cast<size_t>(bytecode);
Ben Murdochc5610432016-08-08 18:44:38 +0100101 switch (operand_scale) {
102 case OperandScale::kSingle:
103 return index;
104 case OperandScale::kDouble:
105 return index + kEntriesPerOperandScale;
106 case OperandScale::kQuadruple:
107 return index + 2 * kEntriesPerOperandScale;
Ben Murdochda12d292016-06-02 14:46:10 +0100108 }
Ben Murdochc5610432016-08-08 18:44:38 +0100109 UNREACHABLE();
110 return 0;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100111}
112
113void Interpreter::IterateDispatchTable(ObjectVisitor* v) {
Ben Murdochc5610432016-08-08 18:44:38 +0100114 for (int i = 0; i < kDispatchTableSize; i++) {
115 Address code_entry = dispatch_table_[i];
116 Object* code = code_entry == nullptr
117 ? nullptr
118 : Code::GetCodeFromTargetAddress(code_entry);
119 Object* old_code = code;
120 v->VisitPointer(&code);
121 if (code != old_code) {
122 dispatch_table_[i] = reinterpret_cast<Code*>(code)->entry();
123 }
124 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100125}
126
127// static
128int Interpreter::InterruptBudget() {
129 // TODO(ignition): Tune code size multiplier.
130 const int kCodeSizeMultiplier = 32;
131 return FLAG_interrupt_budget * kCodeSizeMultiplier;
132}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000133
134bool Interpreter::MakeBytecode(CompilationInfo* info) {
Ben Murdochc5610432016-08-08 18:44:38 +0100135 RuntimeCallTimerScope runtimeTimer(info->isolate(),
136 &RuntimeCallStats::CompileIgnition);
Ben Murdochda12d292016-06-02 14:46:10 +0100137 TimerEventScope<TimerEventCompileIgnition> timer(info->isolate());
138 TRACE_EVENT0("v8", "V8.CompileIgnition");
139
Ben Murdoch097c5b22016-05-18 11:27:45 +0100140 if (FLAG_print_bytecode || FLAG_print_source || FLAG_print_ast) {
141 OFStream os(stdout);
142 base::SmartArrayPointer<char> name = info->GetDebugName();
143 os << "[generating bytecode for function: " << info->GetDebugName().get()
144 << "]" << std::endl
145 << std::flush;
146 }
147
148#ifdef DEBUG
149 if (info->parse_info() && FLAG_print_source) {
150 OFStream os(stdout);
151 os << "--- Source from AST ---" << std::endl
152 << PrettyPrinter(info->isolate()).PrintProgram(info->literal())
153 << std::endl
154 << std::flush;
155 }
156
157 if (info->parse_info() && FLAG_print_ast) {
158 OFStream os(stdout);
159 os << "--- AST ---" << std::endl
160 << AstPrinter(info->isolate()).PrintProgram(info->literal()) << std::endl
161 << std::flush;
162 }
163#endif // DEBUG
164
Ben Murdochc5610432016-08-08 18:44:38 +0100165 BytecodeGenerator generator(info);
166 Handle<BytecodeArray> bytecodes = generator.MakeBytecode();
Ben Murdochda12d292016-06-02 14:46:10 +0100167
168 if (generator.HasStackOverflow()) return false;
169
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000170 if (FLAG_print_bytecode) {
171 OFStream os(stdout);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000172 bytecodes->Print(os);
173 os << std::flush;
174 }
175
176 info->SetBytecodeArray(bytecodes);
177 info->SetCode(info->isolate()->builtins()->InterpreterEntryTrampoline());
178 return true;
179}
180
Ben Murdoch097c5b22016-05-18 11:27:45 +0100181bool Interpreter::IsDispatchTableInitialized() {
Ben Murdochc5610432016-08-08 18:44:38 +0100182 if (FLAG_trace_ignition || FLAG_trace_ignition_codegen ||
183 FLAG_trace_ignition_dispatches) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100184 // Regenerate table to add bytecode tracing operations, print the assembly
185 // code generated by TurboFan or instrument handlers with dispatch counters.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100186 return false;
187 }
188 return dispatch_table_[0] != nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000189}
190
Ben Murdochda12d292016-06-02 14:46:10 +0100191void Interpreter::TraceCodegen(Handle<Code> code) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100192#ifdef ENABLE_DISASSEMBLER
193 if (FLAG_trace_ignition_codegen) {
194 OFStream os(stdout);
Ben Murdochda12d292016-06-02 14:46:10 +0100195 code->Disassemble(nullptr, os);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100196 os << std::flush;
197 }
198#endif // ENABLE_DISASSEMBLER
199}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000200
Ben Murdochda12d292016-06-02 14:46:10 +0100201const char* Interpreter::LookupNameOfBytecodeHandler(Code* code) {
202#ifdef ENABLE_DISASSEMBLER
Ben Murdochc5610432016-08-08 18:44:38 +0100203#define RETURN_NAME(Name, ...) \
204 if (dispatch_table_[Bytecodes::ToByte(Bytecode::k##Name)] == \
205 code->entry()) { \
206 return #Name; \
Ben Murdochda12d292016-06-02 14:46:10 +0100207 }
208 BYTECODE_LIST(RETURN_NAME)
209#undef RETURN_NAME
210#endif // ENABLE_DISASSEMBLER
211 return nullptr;
212}
213
Ben Murdochc5610432016-08-08 18:44:38 +0100214uintptr_t Interpreter::GetDispatchCounter(Bytecode from, Bytecode to) const {
215 int from_index = Bytecodes::ToByte(from);
216 int to_index = Bytecodes::ToByte(to);
217 return bytecode_dispatch_counters_table_[from_index * kNumberOfBytecodes +
218 to_index];
219}
220
221Local<v8::Object> Interpreter::GetDispatchCountersObject() {
222 v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(isolate_);
223 Local<v8::Context> context = isolate->GetCurrentContext();
224
225 Local<v8::Object> counters_map = v8::Object::New(isolate);
226
227 // Output is a JSON-encoded object of objects.
228 //
229 // The keys on the top level object are source bytecodes,
230 // and corresponding value are objects. Keys on these last are the
231 // destinations of the dispatch and the value associated is a counter for
232 // the correspondent source-destination dispatch chain.
233 //
234 // Only non-zero counters are written to file, but an entry in the top-level
235 // object is always present, even if the value is empty because all counters
236 // for that source are zero.
237
238 for (int from_index = 0; from_index < kNumberOfBytecodes; ++from_index) {
239 Bytecode from_bytecode = Bytecodes::FromByte(from_index);
240 Local<v8::Object> counters_row = v8::Object::New(isolate);
241
242 for (int to_index = 0; to_index < kNumberOfBytecodes; ++to_index) {
243 Bytecode to_bytecode = Bytecodes::FromByte(to_index);
244 uintptr_t counter = GetDispatchCounter(from_bytecode, to_bytecode);
245
246 if (counter > 0) {
247 std::string to_name = Bytecodes::ToString(to_bytecode);
248 Local<v8::String> to_name_object =
249 v8::String::NewFromUtf8(isolate, to_name.c_str(),
250 NewStringType::kNormal)
251 .ToLocalChecked();
252 Local<v8::Number> counter_object = v8::Number::New(isolate, counter);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100253 CHECK(counters_row
254 ->DefineOwnProperty(context, to_name_object, counter_object)
Ben Murdochc5610432016-08-08 18:44:38 +0100255 .IsJust());
256 }
257 }
258
259 std::string from_name = Bytecodes::ToString(from_bytecode);
260 Local<v8::String> from_name_object =
261 v8::String::NewFromUtf8(isolate, from_name.c_str(),
262 NewStringType::kNormal)
263 .ToLocalChecked();
264
Ben Murdoch61f157c2016-09-16 13:49:30 +0100265 CHECK(
266 counters_map->DefineOwnProperty(context, from_name_object, counters_row)
267 .IsJust());
Ben Murdochc5610432016-08-08 18:44:38 +0100268 }
269
270 return counters_map;
271}
272
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000273// LdaZero
274//
275// Load literal '0' into the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100276void Interpreter::DoLdaZero(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000277 Node* zero_value = __ NumberConstant(0.0);
278 __ SetAccumulator(zero_value);
279 __ Dispatch();
280}
281
Ben Murdochda12d292016-06-02 14:46:10 +0100282// LdaSmi <imm>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000283//
Ben Murdochda12d292016-06-02 14:46:10 +0100284// Load an integer literal into the accumulator as a Smi.
285void Interpreter::DoLdaSmi(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000286 Node* raw_int = __ BytecodeOperandImm(0);
287 Node* smi_int = __ SmiTag(raw_int);
288 __ SetAccumulator(smi_int);
289 __ Dispatch();
290}
291
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000292// LdaConstant <idx>
293//
294// Load constant literal at |idx| in the constant pool into the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100295void Interpreter::DoLdaConstant(InterpreterAssembler* assembler) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100296 Node* index = __ BytecodeOperandIdx(0);
297 Node* constant = __ LoadConstantPoolEntry(index);
298 __ SetAccumulator(constant);
299 __ Dispatch();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000300}
301
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000302// LdaUndefined
303//
304// Load Undefined into the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100305void Interpreter::DoLdaUndefined(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000306 Node* undefined_value =
307 __ HeapConstant(isolate_->factory()->undefined_value());
308 __ SetAccumulator(undefined_value);
309 __ Dispatch();
310}
311
Ben Murdoch61f157c2016-09-16 13:49:30 +0100312// LdrUndefined <reg>
313//
314// Loads undefined into the accumulator and |reg|.
315void Interpreter::DoLdrUndefined(InterpreterAssembler* assembler) {
316 Node* undefined_value =
317 __ HeapConstant(isolate_->factory()->undefined_value());
318 Node* destination = __ BytecodeOperandReg(0);
319 __ StoreRegister(undefined_value, destination);
320 __ Dispatch();
321}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000322
323// LdaNull
324//
325// Load Null into the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100326void Interpreter::DoLdaNull(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000327 Node* null_value = __ HeapConstant(isolate_->factory()->null_value());
328 __ SetAccumulator(null_value);
329 __ Dispatch();
330}
331
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000332// LdaTheHole
333//
334// Load TheHole into the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100335void Interpreter::DoLdaTheHole(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000336 Node* the_hole_value = __ HeapConstant(isolate_->factory()->the_hole_value());
337 __ SetAccumulator(the_hole_value);
338 __ Dispatch();
339}
340
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000341// LdaTrue
342//
343// Load True into the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100344void Interpreter::DoLdaTrue(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000345 Node* true_value = __ HeapConstant(isolate_->factory()->true_value());
346 __ SetAccumulator(true_value);
347 __ Dispatch();
348}
349
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000350// LdaFalse
351//
352// Load False into the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100353void Interpreter::DoLdaFalse(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000354 Node* false_value = __ HeapConstant(isolate_->factory()->false_value());
355 __ SetAccumulator(false_value);
356 __ Dispatch();
357}
358
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000359// Ldar <src>
360//
361// Load accumulator with value from register <src>.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100362void Interpreter::DoLdar(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000363 Node* reg_index = __ BytecodeOperandReg(0);
364 Node* value = __ LoadRegister(reg_index);
365 __ SetAccumulator(value);
366 __ Dispatch();
367}
368
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000369// Star <dst>
370//
371// Store accumulator to register <dst>.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100372void Interpreter::DoStar(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000373 Node* reg_index = __ BytecodeOperandReg(0);
374 Node* accumulator = __ GetAccumulator();
375 __ StoreRegister(accumulator, reg_index);
376 __ Dispatch();
377}
378
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000379// Mov <src> <dst>
380//
381// Stores the value of register <src> to register <dst>.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100382void Interpreter::DoMov(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000383 Node* src_index = __ BytecodeOperandReg(0);
384 Node* src_value = __ LoadRegister(src_index);
385 Node* dst_index = __ BytecodeOperandReg(1);
386 __ StoreRegister(src_value, dst_index);
387 __ Dispatch();
388}
389
Ben Murdoch61f157c2016-09-16 13:49:30 +0100390Node* Interpreter::BuildLoadGlobal(Callable ic,
391 InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000392 // Get the global object.
393 Node* context = __ GetContext();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000394
Ben Murdoch61f157c2016-09-16 13:49:30 +0100395 // Load the global via the LoadGlobalIC.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000396 Node* code_target = __ HeapConstant(ic.code());
Ben Murdoch61f157c2016-09-16 13:49:30 +0100397 Node* raw_slot = __ BytecodeOperandIdx(0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000398 Node* smi_slot = __ SmiTag(raw_slot);
399 Node* type_feedback_vector = __ LoadTypeFeedbackVector();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100400 return __ CallStub(ic.descriptor(), code_target, context, smi_slot,
401 type_feedback_vector);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000402}
403
Ben Murdoch61f157c2016-09-16 13:49:30 +0100404// LdaGlobal <slot>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000405//
406// Load the global with name in constant pool entry <name_index> into the
Ben Murdoch097c5b22016-05-18 11:27:45 +0100407// accumulator using FeedBackVector slot <slot> outside of a typeof.
408void Interpreter::DoLdaGlobal(InterpreterAssembler* assembler) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100409 Callable ic =
410 CodeFactory::LoadGlobalICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF);
411 Node* result = BuildLoadGlobal(ic, assembler);
412 __ SetAccumulator(result);
413 __ Dispatch();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000414}
415
Ben Murdoch61f157c2016-09-16 13:49:30 +0100416// LdrGlobal <slot> <reg>
417//
418// Load the global with name in constant pool entry <name_index> into
419// register <reg> using FeedBackVector slot <slot> outside of a typeof.
420void Interpreter::DoLdrGlobal(InterpreterAssembler* assembler) {
421 Callable ic =
422 CodeFactory::LoadGlobalICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF);
423 Node* result = BuildLoadGlobal(ic, assembler);
424 Node* destination = __ BytecodeOperandReg(1);
425 __ StoreRegister(result, destination);
426 __ Dispatch();
427}
428
429// LdaGlobalInsideTypeof <slot>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000430//
431// Load the global with name in constant pool entry <name_index> into the
Ben Murdoch097c5b22016-05-18 11:27:45 +0100432// accumulator using FeedBackVector slot <slot> inside of a typeof.
433void Interpreter::DoLdaGlobalInsideTypeof(InterpreterAssembler* assembler) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100434 Callable ic =
435 CodeFactory::LoadGlobalICInOptimizedCode(isolate_, INSIDE_TYPEOF);
436 Node* result = BuildLoadGlobal(ic, assembler);
437 __ SetAccumulator(result);
438 __ Dispatch();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100439}
440
Ben Murdoch61f157c2016-09-16 13:49:30 +0100441void Interpreter::DoStaGlobal(Callable ic, InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000442 // Get the global object.
443 Node* context = __ GetContext();
444 Node* native_context =
445 __ LoadContextSlot(context, Context::NATIVE_CONTEXT_INDEX);
446 Node* global = __ LoadContextSlot(native_context, Context::EXTENSION_INDEX);
447
448 // Store the global via the StoreIC.
449 Node* code_target = __ HeapConstant(ic.code());
450 Node* constant_index = __ BytecodeOperandIdx(0);
451 Node* name = __ LoadConstantPoolEntry(constant_index);
452 Node* value = __ GetAccumulator();
453 Node* raw_slot = __ BytecodeOperandIdx(1);
454 Node* smi_slot = __ SmiTag(raw_slot);
455 Node* type_feedback_vector = __ LoadTypeFeedbackVector();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100456 __ CallStub(ic.descriptor(), code_target, context, global, name, value,
457 smi_slot, type_feedback_vector);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000458 __ Dispatch();
459}
460
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000461// StaGlobalSloppy <name_index> <slot>
462//
463// Store the value in the accumulator into the global with name in constant pool
464// entry <name_index> using FeedBackVector slot <slot> in sloppy mode.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100465void Interpreter::DoStaGlobalSloppy(InterpreterAssembler* assembler) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100466 Callable ic = CodeFactory::StoreICInOptimizedCode(isolate_, SLOPPY);
467 DoStaGlobal(ic, assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000468}
469
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000470// StaGlobalStrict <name_index> <slot>
471//
472// Store the value in the accumulator into the global with name in constant pool
473// entry <name_index> using FeedBackVector slot <slot> in strict mode.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100474void Interpreter::DoStaGlobalStrict(InterpreterAssembler* assembler) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100475 Callable ic = CodeFactory::StoreICInOptimizedCode(isolate_, STRICT);
476 DoStaGlobal(ic, assembler);
477}
478
479compiler::Node* Interpreter::BuildLoadContextSlot(
480 InterpreterAssembler* assembler) {
481 Node* reg_index = __ BytecodeOperandReg(0);
482 Node* context = __ LoadRegister(reg_index);
483 Node* slot_index = __ BytecodeOperandIdx(1);
484 return __ LoadContextSlot(context, slot_index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000485}
486
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000487// LdaContextSlot <context> <slot_index>
488//
489// Load the object in |slot_index| of |context| into the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100490void Interpreter::DoLdaContextSlot(InterpreterAssembler* assembler) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100491 Node* result = BuildLoadContextSlot(assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000492 __ SetAccumulator(result);
493 __ Dispatch();
494}
495
Ben Murdoch61f157c2016-09-16 13:49:30 +0100496// LdrContextSlot <context> <slot_index> <reg>
497//
498// Load the object in <slot_index> of <context> into register <reg>.
499void Interpreter::DoLdrContextSlot(InterpreterAssembler* assembler) {
500 Node* result = BuildLoadContextSlot(assembler);
501 Node* destination = __ BytecodeOperandReg(2);
502 __ StoreRegister(result, destination);
503 __ Dispatch();
504}
505
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000506// StaContextSlot <context> <slot_index>
507//
508// Stores the object in the accumulator into |slot_index| of |context|.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100509void Interpreter::DoStaContextSlot(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000510 Node* value = __ GetAccumulator();
511 Node* reg_index = __ BytecodeOperandReg(0);
512 Node* context = __ LoadRegister(reg_index);
513 Node* slot_index = __ BytecodeOperandIdx(1);
514 __ StoreContextSlot(context, slot_index, value);
515 __ Dispatch();
516}
517
Ben Murdoch61f157c2016-09-16 13:49:30 +0100518void Interpreter::DoLdaLookupSlot(Runtime::FunctionId function_id,
519 InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000520 Node* index = __ BytecodeOperandIdx(0);
521 Node* name = __ LoadConstantPoolEntry(index);
522 Node* context = __ GetContext();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100523 Node* result = __ CallRuntime(function_id, context, name);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000524 __ SetAccumulator(result);
525 __ Dispatch();
526}
527
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000528// LdaLookupSlot <name_index>
529//
530// Lookup the object with the name in constant pool entry |name_index|
531// dynamically.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100532void Interpreter::DoLdaLookupSlot(InterpreterAssembler* assembler) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100533 DoLdaLookupSlot(Runtime::kLoadLookupSlot, assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000534}
535
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000536// LdaLookupSlotInsideTypeof <name_index>
537//
538// Lookup the object with the name in constant pool entry |name_index|
539// dynamically without causing a NoReferenceError.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100540void Interpreter::DoLdaLookupSlotInsideTypeof(InterpreterAssembler* assembler) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100541 DoLdaLookupSlot(Runtime::kLoadLookupSlotInsideTypeof, assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000542}
543
Ben Murdoch61f157c2016-09-16 13:49:30 +0100544void Interpreter::DoStaLookupSlot(LanguageMode language_mode,
545 InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000546 Node* value = __ GetAccumulator();
547 Node* index = __ BytecodeOperandIdx(0);
548 Node* name = __ LoadConstantPoolEntry(index);
549 Node* context = __ GetContext();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100550 Node* result = __ CallRuntime(is_strict(language_mode)
551 ? Runtime::kStoreLookupSlot_Strict
552 : Runtime::kStoreLookupSlot_Sloppy,
553 context, name, value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000554 __ SetAccumulator(result);
555 __ Dispatch();
556}
557
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000558// StaLookupSlotSloppy <name_index>
559//
560// Store the object in accumulator to the object with the name in constant
561// pool entry |name_index| in sloppy mode.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100562void Interpreter::DoStaLookupSlotSloppy(InterpreterAssembler* assembler) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100563 DoStaLookupSlot(LanguageMode::SLOPPY, assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000564}
565
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000566// StaLookupSlotStrict <name_index>
567//
568// Store the object in accumulator to the object with the name in constant
569// pool entry |name_index| in strict mode.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100570void Interpreter::DoStaLookupSlotStrict(InterpreterAssembler* assembler) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100571 DoStaLookupSlot(LanguageMode::STRICT, assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000572}
573
Ben Murdoch61f157c2016-09-16 13:49:30 +0100574Node* Interpreter::BuildLoadNamedProperty(Callable ic,
575 InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000576 Node* code_target = __ HeapConstant(ic.code());
577 Node* register_index = __ BytecodeOperandReg(0);
578 Node* object = __ LoadRegister(register_index);
579 Node* constant_index = __ BytecodeOperandIdx(1);
580 Node* name = __ LoadConstantPoolEntry(constant_index);
581 Node* raw_slot = __ BytecodeOperandIdx(2);
582 Node* smi_slot = __ SmiTag(raw_slot);
583 Node* type_feedback_vector = __ LoadTypeFeedbackVector();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100584 Node* context = __ GetContext();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100585 return __ CallStub(ic.descriptor(), code_target, context, object, name,
586 smi_slot, type_feedback_vector);
587}
588
589// LdaNamedProperty <object> <name_index> <slot>
590//
591// Calls the LoadIC at FeedBackVector slot <slot> for <object> and the name at
592// constant pool entry <name_index>.
593void Interpreter::DoLdaNamedProperty(InterpreterAssembler* assembler) {
594 Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_);
595 Node* result = BuildLoadNamedProperty(ic, assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000596 __ SetAccumulator(result);
597 __ Dispatch();
598}
599
Ben Murdoch61f157c2016-09-16 13:49:30 +0100600// LdrNamedProperty <object> <name_index> <slot> <reg>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000601//
Ben Murdoch097c5b22016-05-18 11:27:45 +0100602// Calls the LoadIC at FeedBackVector slot <slot> for <object> and the name at
Ben Murdoch61f157c2016-09-16 13:49:30 +0100603// constant pool entry <name_index> and puts the result into register <reg>.
604void Interpreter::DoLdrNamedProperty(InterpreterAssembler* assembler) {
605 Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_);
606 Node* result = BuildLoadNamedProperty(ic, assembler);
607 Node* destination = __ BytecodeOperandReg(3);
608 __ StoreRegister(result, destination);
609 __ Dispatch();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100610}
611
Ben Murdoch61f157c2016-09-16 13:49:30 +0100612Node* Interpreter::BuildLoadKeyedProperty(Callable ic,
613 InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000614 Node* code_target = __ HeapConstant(ic.code());
615 Node* reg_index = __ BytecodeOperandReg(0);
616 Node* object = __ LoadRegister(reg_index);
617 Node* name = __ GetAccumulator();
618 Node* raw_slot = __ BytecodeOperandIdx(1);
619 Node* smi_slot = __ SmiTag(raw_slot);
620 Node* type_feedback_vector = __ LoadTypeFeedbackVector();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100621 Node* context = __ GetContext();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100622 return __ CallStub(ic.descriptor(), code_target, context, object, name,
623 smi_slot, type_feedback_vector);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000624}
625
Ben Murdoch097c5b22016-05-18 11:27:45 +0100626// KeyedLoadIC <object> <slot>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000627//
Ben Murdoch097c5b22016-05-18 11:27:45 +0100628// Calls the KeyedLoadIC at FeedBackVector slot <slot> for <object> and the key
629// in the accumulator.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100630void Interpreter::DoLdaKeyedProperty(InterpreterAssembler* assembler) {
631 Callable ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate_);
632 Node* result = BuildLoadKeyedProperty(ic, assembler);
633 __ SetAccumulator(result);
634 __ Dispatch();
635}
636
637// LdrKeyedProperty <object> <slot> <reg>
638//
639// Calls the KeyedLoadIC at FeedBackVector slot <slot> for <object> and the key
640// in the accumulator and puts the result in register <reg>.
641void Interpreter::DoLdrKeyedProperty(InterpreterAssembler* assembler) {
642 Callable ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate_);
643 Node* result = BuildLoadKeyedProperty(ic, assembler);
644 Node* destination = __ BytecodeOperandReg(2);
645 __ StoreRegister(result, destination);
646 __ Dispatch();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100647}
648
Ben Murdoch097c5b22016-05-18 11:27:45 +0100649void Interpreter::DoStoreIC(Callable ic, InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000650 Node* code_target = __ HeapConstant(ic.code());
651 Node* object_reg_index = __ BytecodeOperandReg(0);
652 Node* object = __ LoadRegister(object_reg_index);
653 Node* constant_index = __ BytecodeOperandIdx(1);
654 Node* name = __ LoadConstantPoolEntry(constant_index);
655 Node* value = __ GetAccumulator();
656 Node* raw_slot = __ BytecodeOperandIdx(2);
657 Node* smi_slot = __ SmiTag(raw_slot);
658 Node* type_feedback_vector = __ LoadTypeFeedbackVector();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100659 Node* context = __ GetContext();
660 __ CallStub(ic.descriptor(), code_target, context, object, name, value,
661 smi_slot, type_feedback_vector);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000662 __ Dispatch();
663}
664
Ben Murdoch61f157c2016-09-16 13:49:30 +0100665// StaNamedPropertySloppy <object> <name_index> <slot>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000666//
667// Calls the sloppy mode StoreIC at FeedBackVector slot <slot> for <object> and
668// the name in constant pool entry <name_index> with the value in the
669// accumulator.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100670void Interpreter::DoStaNamedPropertySloppy(InterpreterAssembler* assembler) {
671 Callable ic = CodeFactory::StoreICInOptimizedCode(isolate_, SLOPPY);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000672 DoStoreIC(ic, assembler);
673}
674
Ben Murdoch61f157c2016-09-16 13:49:30 +0100675// StaNamedPropertyStrict <object> <name_index> <slot>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000676//
677// Calls the strict mode StoreIC at FeedBackVector slot <slot> for <object> and
678// the name in constant pool entry <name_index> with the value in the
679// accumulator.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100680void Interpreter::DoStaNamedPropertyStrict(InterpreterAssembler* assembler) {
681 Callable ic = CodeFactory::StoreICInOptimizedCode(isolate_, STRICT);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000682 DoStoreIC(ic, assembler);
683}
684
Ben Murdoch097c5b22016-05-18 11:27:45 +0100685void Interpreter::DoKeyedStoreIC(Callable ic, InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000686 Node* code_target = __ HeapConstant(ic.code());
687 Node* object_reg_index = __ BytecodeOperandReg(0);
688 Node* object = __ LoadRegister(object_reg_index);
689 Node* name_reg_index = __ BytecodeOperandReg(1);
690 Node* name = __ LoadRegister(name_reg_index);
691 Node* value = __ GetAccumulator();
692 Node* raw_slot = __ BytecodeOperandIdx(2);
693 Node* smi_slot = __ SmiTag(raw_slot);
694 Node* type_feedback_vector = __ LoadTypeFeedbackVector();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100695 Node* context = __ GetContext();
696 __ CallStub(ic.descriptor(), code_target, context, object, name, value,
697 smi_slot, type_feedback_vector);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000698 __ Dispatch();
699}
700
Ben Murdoch61f157c2016-09-16 13:49:30 +0100701// StaKeyedPropertySloppy <object> <key> <slot>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000702//
703// Calls the sloppy mode KeyStoreIC at FeedBackVector slot <slot> for <object>
704// and the key <key> with the value in the accumulator.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100705void Interpreter::DoStaKeyedPropertySloppy(InterpreterAssembler* assembler) {
706 Callable ic = CodeFactory::KeyedStoreICInOptimizedCode(isolate_, SLOPPY);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000707 DoKeyedStoreIC(ic, assembler);
708}
709
Ben Murdoch61f157c2016-09-16 13:49:30 +0100710// StaKeyedPropertyStrict <object> <key> <slot>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000711//
712// Calls the strict mode KeyStoreIC at FeedBackVector slot <slot> for <object>
713// and the key <key> with the value in the accumulator.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100714void Interpreter::DoStaKeyedPropertyStrict(InterpreterAssembler* assembler) {
715 Callable ic = CodeFactory::KeyedStoreICInOptimizedCode(isolate_, STRICT);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000716 DoKeyedStoreIC(ic, assembler);
717}
718
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000719// PushContext <context>
720//
Ben Murdoch097c5b22016-05-18 11:27:45 +0100721// Saves the current context in <context>, and pushes the accumulator as the
722// new current context.
723void Interpreter::DoPushContext(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000724 Node* reg_index = __ BytecodeOperandReg(0);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100725 Node* new_context = __ GetAccumulator();
726 Node* old_context = __ GetContext();
727 __ StoreRegister(old_context, reg_index);
728 __ SetContext(new_context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000729 __ Dispatch();
730}
731
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000732// PopContext <context>
733//
734// Pops the current context and sets <context> as the new context.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100735void Interpreter::DoPopContext(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000736 Node* reg_index = __ BytecodeOperandReg(0);
737 Node* context = __ LoadRegister(reg_index);
738 __ SetContext(context);
739 __ Dispatch();
740}
741
Ben Murdochc5610432016-08-08 18:44:38 +0100742template <class Generator>
743void Interpreter::DoBinaryOp(InterpreterAssembler* assembler) {
744 Node* reg_index = __ BytecodeOperandReg(0);
745 Node* lhs = __ LoadRegister(reg_index);
746 Node* rhs = __ GetAccumulator();
747 Node* context = __ GetContext();
748 Node* result = Generator::Generate(assembler, lhs, rhs, context);
749 __ SetAccumulator(result);
750 __ Dispatch();
751}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000752
753// Add <src>
754//
755// Add register <src> to accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100756void Interpreter::DoAdd(InterpreterAssembler* assembler) {
Ben Murdochc5610432016-08-08 18:44:38 +0100757 DoBinaryOp<AddStub>(assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000758}
759
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000760// Sub <src>
761//
762// Subtract register <src> from accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100763void Interpreter::DoSub(InterpreterAssembler* assembler) {
Ben Murdochc5610432016-08-08 18:44:38 +0100764 DoBinaryOp<SubtractStub>(assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000765}
766
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000767// Mul <src>
768//
769// Multiply accumulator by register <src>.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100770void Interpreter::DoMul(InterpreterAssembler* assembler) {
Ben Murdochc5610432016-08-08 18:44:38 +0100771 DoBinaryOp<MultiplyStub>(assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000772}
773
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000774// Div <src>
775//
776// Divide register <src> by accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100777void Interpreter::DoDiv(InterpreterAssembler* assembler) {
Ben Murdochc5610432016-08-08 18:44:38 +0100778 DoBinaryOp<DivideStub>(assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000779}
780
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000781// Mod <src>
782//
783// Modulo register <src> by accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100784void Interpreter::DoMod(InterpreterAssembler* assembler) {
Ben Murdochc5610432016-08-08 18:44:38 +0100785 DoBinaryOp<ModulusStub>(assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000786}
787
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000788// BitwiseOr <src>
789//
790// BitwiseOr register <src> to accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100791void Interpreter::DoBitwiseOr(InterpreterAssembler* assembler) {
Ben Murdochc5610432016-08-08 18:44:38 +0100792 DoBinaryOp<BitwiseOrStub>(assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000793}
794
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000795// BitwiseXor <src>
796//
797// BitwiseXor register <src> to accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100798void Interpreter::DoBitwiseXor(InterpreterAssembler* assembler) {
Ben Murdochc5610432016-08-08 18:44:38 +0100799 DoBinaryOp<BitwiseXorStub>(assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000800}
801
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000802// BitwiseAnd <src>
803//
804// BitwiseAnd register <src> to accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100805void Interpreter::DoBitwiseAnd(InterpreterAssembler* assembler) {
Ben Murdochc5610432016-08-08 18:44:38 +0100806 DoBinaryOp<BitwiseAndStub>(assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000807}
808
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000809// ShiftLeft <src>
810//
811// Left shifts register <src> by the count specified in the accumulator.
812// Register <src> is converted to an int32 and the accumulator to uint32
813// before the operation. 5 lsb bits from the accumulator are used as count
814// i.e. <src> << (accumulator & 0x1F).
Ben Murdoch097c5b22016-05-18 11:27:45 +0100815void Interpreter::DoShiftLeft(InterpreterAssembler* assembler) {
Ben Murdochc5610432016-08-08 18:44:38 +0100816 DoBinaryOp<ShiftLeftStub>(assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000817}
818
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000819// ShiftRight <src>
820//
821// Right shifts register <src> by the count specified in the accumulator.
822// Result is sign extended. Register <src> is converted to an int32 and the
823// accumulator to uint32 before the operation. 5 lsb bits from the accumulator
824// are used as count i.e. <src> >> (accumulator & 0x1F).
Ben Murdoch097c5b22016-05-18 11:27:45 +0100825void Interpreter::DoShiftRight(InterpreterAssembler* assembler) {
Ben Murdochc5610432016-08-08 18:44:38 +0100826 DoBinaryOp<ShiftRightStub>(assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000827}
828
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000829// ShiftRightLogical <src>
830//
831// Right Shifts register <src> by the count specified in the accumulator.
832// Result is zero-filled. The accumulator and register <src> are converted to
833// uint32 before the operation 5 lsb bits from the accumulator are used as
834// count i.e. <src> << (accumulator & 0x1F).
Ben Murdoch097c5b22016-05-18 11:27:45 +0100835void Interpreter::DoShiftRightLogical(InterpreterAssembler* assembler) {
Ben Murdochc5610432016-08-08 18:44:38 +0100836 DoBinaryOp<ShiftRightLogicalStub>(assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000837}
838
Ben Murdoch61f157c2016-09-16 13:49:30 +0100839void Interpreter::DoUnaryOp(Callable callable,
840 InterpreterAssembler* assembler) {
841 Node* target = __ HeapConstant(callable.code());
842 Node* accumulator = __ GetAccumulator();
843 Node* context = __ GetContext();
844 Node* result =
845 __ CallStub(callable.descriptor(), target, context, accumulator);
846 __ SetAccumulator(result);
847 __ Dispatch();
848}
849
Ben Murdochc5610432016-08-08 18:44:38 +0100850template <class Generator>
851void Interpreter::DoUnaryOp(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000852 Node* value = __ GetAccumulator();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100853 Node* context = __ GetContext();
Ben Murdochc5610432016-08-08 18:44:38 +0100854 Node* result = Generator::Generate(assembler, value, context);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000855 __ SetAccumulator(result);
856 __ Dispatch();
857}
858
Ben Murdoch61f157c2016-09-16 13:49:30 +0100859// ToName
860//
861// Cast the object referenced by the accumulator to a name.
862void Interpreter::DoToName(InterpreterAssembler* assembler) {
863 DoUnaryOp(CodeFactory::ToName(isolate_), assembler);
864}
865
866// ToNumber
867//
868// Cast the object referenced by the accumulator to a number.
869void Interpreter::DoToNumber(InterpreterAssembler* assembler) {
870 DoUnaryOp(CodeFactory::ToNumber(isolate_), assembler);
871}
872
873// ToObject
874//
875// Cast the object referenced by the accumulator to a JSObject.
876void Interpreter::DoToObject(InterpreterAssembler* assembler) {
877 DoUnaryOp(CodeFactory::ToObject(isolate_), assembler);
878}
879
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000880// Inc
881//
882// Increments value in the accumulator by one.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100883void Interpreter::DoInc(InterpreterAssembler* assembler) {
Ben Murdochc5610432016-08-08 18:44:38 +0100884 DoUnaryOp<IncStub>(assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000885}
886
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000887// Dec
888//
889// Decrements value in the accumulator by one.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100890void Interpreter::DoDec(InterpreterAssembler* assembler) {
Ben Murdochc5610432016-08-08 18:44:38 +0100891 DoUnaryOp<DecStub>(assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000892}
893
Ben Murdoch61f157c2016-09-16 13:49:30 +0100894Node* Interpreter::BuildToBoolean(Node* value,
895 InterpreterAssembler* assembler) {
896 Node* context = __ GetContext();
897 return ToBooleanStub::Generate(assembler, value, context);
898}
899
900Node* Interpreter::BuildLogicalNot(Node* value,
901 InterpreterAssembler* assembler) {
902 Variable result(assembler, MachineRepresentation::kTagged);
Ben Murdochc5610432016-08-08 18:44:38 +0100903 Label if_true(assembler), if_false(assembler), end(assembler);
904 Node* true_value = __ BooleanConstant(true);
905 Node* false_value = __ BooleanConstant(false);
906 __ BranchIfWordEqual(value, true_value, &if_true, &if_false);
907 __ Bind(&if_true);
908 {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100909 result.Bind(false_value);
Ben Murdochc5610432016-08-08 18:44:38 +0100910 __ Goto(&end);
911 }
912 __ Bind(&if_false);
913 {
914 if (FLAG_debug_code) {
915 __ AbortIfWordNotEqual(value, false_value,
916 BailoutReason::kExpectedBooleanValue);
917 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100918 result.Bind(true_value);
Ben Murdochc5610432016-08-08 18:44:38 +0100919 __ Goto(&end);
920 }
921 __ Bind(&end);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100922 return result.value();
Ben Murdochc5610432016-08-08 18:44:38 +0100923}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000924
Ben Murdoch61f157c2016-09-16 13:49:30 +0100925// LogicalNot
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000926//
927// Perform logical-not on the accumulator, first casting the
928// accumulator to a boolean value if required.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100929// ToBooleanLogicalNot
Ben Murdochc5610432016-08-08 18:44:38 +0100930void Interpreter::DoToBooleanLogicalNot(InterpreterAssembler* assembler) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100931 Node* value = __ GetAccumulator();
932 Node* to_boolean_value = BuildToBoolean(value, assembler);
933 Node* result = BuildLogicalNot(to_boolean_value, assembler);
934 __ SetAccumulator(result);
Ben Murdochc5610432016-08-08 18:44:38 +0100935 __ Dispatch();
936}
937
938// LogicalNot
939//
940// Perform logical-not on the accumulator, which must already be a boolean
941// value.
942void Interpreter::DoLogicalNot(InterpreterAssembler* assembler) {
943 Node* value = __ GetAccumulator();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100944 Node* result = BuildLogicalNot(value, assembler);
945 __ SetAccumulator(result);
Ben Murdochc5610432016-08-08 18:44:38 +0100946 __ Dispatch();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000947}
948
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000949// TypeOf
950//
951// Load the accumulator with the string representating type of the
952// object in the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100953void Interpreter::DoTypeOf(InterpreterAssembler* assembler) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100954 DoUnaryOp(CodeFactory::Typeof(isolate_), assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000955}
956
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000957void Interpreter::DoDelete(Runtime::FunctionId function_id,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100958 InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000959 Node* reg_index = __ BytecodeOperandReg(0);
960 Node* object = __ LoadRegister(reg_index);
961 Node* key = __ GetAccumulator();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100962 Node* context = __ GetContext();
963 Node* result = __ CallRuntime(function_id, context, object, key);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000964 __ SetAccumulator(result);
965 __ Dispatch();
966}
967
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000968// DeletePropertyStrict
969//
970// Delete the property specified in the accumulator from the object
971// referenced by the register operand following strict mode semantics.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100972void Interpreter::DoDeletePropertyStrict(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000973 DoDelete(Runtime::kDeleteProperty_Strict, assembler);
974}
975
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000976// DeletePropertySloppy
977//
978// Delete the property specified in the accumulator from the object
979// referenced by the register operand following sloppy mode semantics.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100980void Interpreter::DoDeletePropertySloppy(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000981 DoDelete(Runtime::kDeleteProperty_Sloppy, assembler);
982}
983
Ben Murdoch097c5b22016-05-18 11:27:45 +0100984void Interpreter::DoJSCall(InterpreterAssembler* assembler,
985 TailCallMode tail_call_mode) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000986 Node* function_reg = __ BytecodeOperandReg(0);
987 Node* function = __ LoadRegister(function_reg);
988 Node* receiver_reg = __ BytecodeOperandReg(1);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100989 Node* receiver_arg = __ RegisterLocation(receiver_reg);
990 Node* receiver_args_count = __ BytecodeOperandCount(2);
991 Node* receiver_count = __ Int32Constant(1);
992 Node* args_count = __ Int32Sub(receiver_args_count, receiver_count);
993 Node* context = __ GetContext();
994 // TODO(rmcilroy): Use the call type feedback slot to call via CallStub.
995 Node* result =
996 __ CallJS(function, context, receiver_arg, args_count, tail_call_mode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000997 __ SetAccumulator(result);
998 __ Dispatch();
999}
1000
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001001// Call <callable> <receiver> <arg_count>
1002//
1003// Call a JSfunction or Callable in |callable| with the |receiver| and
1004// |arg_count| arguments in subsequent registers.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001005void Interpreter::DoCall(InterpreterAssembler* assembler) {
1006 DoJSCall(assembler, TailCallMode::kDisallow);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001007}
1008
Ben Murdoch097c5b22016-05-18 11:27:45 +01001009// TailCall <callable> <receiver> <arg_count>
1010//
1011// Tail call a JSfunction or Callable in |callable| with the |receiver| and
1012// |arg_count| arguments in subsequent registers.
1013void Interpreter::DoTailCall(InterpreterAssembler* assembler) {
1014 DoJSCall(assembler, TailCallMode::kAllow);
1015}
1016
Ben Murdoch097c5b22016-05-18 11:27:45 +01001017void Interpreter::DoCallRuntimeCommon(InterpreterAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +01001018 Node* function_id = __ BytecodeOperandRuntimeId(0);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001019 Node* first_arg_reg = __ BytecodeOperandReg(1);
1020 Node* first_arg = __ RegisterLocation(first_arg_reg);
1021 Node* args_count = __ BytecodeOperandCount(2);
1022 Node* context = __ GetContext();
1023 Node* result = __ CallRuntimeN(function_id, context, first_arg, args_count);
1024 __ SetAccumulator(result);
1025 __ Dispatch();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001026}
1027
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001028// CallRuntime <function_id> <first_arg> <arg_count>
1029//
1030// Call the runtime function |function_id| with the first argument in
1031// register |first_arg| and |arg_count| arguments in subsequent
1032// registers.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001033void Interpreter::DoCallRuntime(InterpreterAssembler* assembler) {
1034 DoCallRuntimeCommon(assembler);
1035}
1036
Ben Murdochda12d292016-06-02 14:46:10 +01001037// InvokeIntrinsic <function_id> <first_arg> <arg_count>
Ben Murdoch097c5b22016-05-18 11:27:45 +01001038//
Ben Murdochda12d292016-06-02 14:46:10 +01001039// Implements the semantic equivalent of calling the runtime function
1040// |function_id| with the first argument in |first_arg| and |arg_count|
1041// arguments in subsequent registers.
1042void Interpreter::DoInvokeIntrinsic(InterpreterAssembler* assembler) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001043 Node* function_id = __ BytecodeOperandIntrinsicId(0);
Ben Murdochda12d292016-06-02 14:46:10 +01001044 Node* first_arg_reg = __ BytecodeOperandReg(1);
1045 Node* arg_count = __ BytecodeOperandCount(2);
1046 Node* context = __ GetContext();
1047 IntrinsicsHelper helper(assembler);
1048 Node* result =
1049 helper.InvokeIntrinsic(function_id, context, first_arg_reg, arg_count);
1050 __ SetAccumulator(result);
1051 __ Dispatch();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001052}
1053
1054void Interpreter::DoCallRuntimeForPairCommon(InterpreterAssembler* assembler) {
1055 // Call the runtime function.
Ben Murdochda12d292016-06-02 14:46:10 +01001056 Node* function_id = __ BytecodeOperandRuntimeId(0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001057 Node* first_arg_reg = __ BytecodeOperandReg(1);
1058 Node* first_arg = __ RegisterLocation(first_arg_reg);
1059 Node* args_count = __ BytecodeOperandCount(2);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001060 Node* context = __ GetContext();
1061 Node* result_pair =
1062 __ CallRuntimeN(function_id, context, first_arg, args_count, 2);
1063
1064 // Store the results in <first_return> and <first_return + 1>
1065 Node* first_return_reg = __ BytecodeOperandReg(3);
1066 Node* second_return_reg = __ NextRegister(first_return_reg);
1067 Node* result0 = __ Projection(0, result_pair);
1068 Node* result1 = __ Projection(1, result_pair);
1069 __ StoreRegister(result0, first_return_reg);
1070 __ StoreRegister(result1, second_return_reg);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001071 __ Dispatch();
1072}
1073
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001074// CallRuntimeForPair <function_id> <first_arg> <arg_count> <first_return>
1075//
1076// Call the runtime function |function_id| which returns a pair, with the
1077// first argument in register |first_arg| and |arg_count| arguments in
1078// subsequent registers. Returns the result in <first_return> and
1079// <first_return + 1>
Ben Murdoch097c5b22016-05-18 11:27:45 +01001080void Interpreter::DoCallRuntimeForPair(InterpreterAssembler* assembler) {
1081 DoCallRuntimeForPairCommon(assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001082}
1083
Ben Murdoch097c5b22016-05-18 11:27:45 +01001084void Interpreter::DoCallJSRuntimeCommon(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001085 Node* context_index = __ BytecodeOperandIdx(0);
1086 Node* receiver_reg = __ BytecodeOperandReg(1);
1087 Node* first_arg = __ RegisterLocation(receiver_reg);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001088 Node* receiver_args_count = __ BytecodeOperandCount(2);
1089 Node* receiver_count = __ Int32Constant(1);
1090 Node* args_count = __ Int32Sub(receiver_args_count, receiver_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001091
1092 // Get the function to call from the native context.
1093 Node* context = __ GetContext();
1094 Node* native_context =
1095 __ LoadContextSlot(context, Context::NATIVE_CONTEXT_INDEX);
1096 Node* function = __ LoadContextSlot(native_context, context_index);
1097
1098 // Call the function.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001099 Node* result = __ CallJS(function, context, first_arg, args_count,
1100 TailCallMode::kDisallow);
1101 __ SetAccumulator(result);
1102 __ Dispatch();
1103}
1104
Ben Murdoch097c5b22016-05-18 11:27:45 +01001105// CallJSRuntime <context_index> <receiver> <arg_count>
1106//
1107// Call the JS runtime function that has the |context_index| with the receiver
1108// in register |receiver| and |arg_count| arguments in subsequent registers.
1109void Interpreter::DoCallJSRuntime(InterpreterAssembler* assembler) {
1110 DoCallJSRuntimeCommon(assembler);
1111}
1112
Ben Murdoch097c5b22016-05-18 11:27:45 +01001113void Interpreter::DoCallConstruct(InterpreterAssembler* assembler) {
1114 Callable ic = CodeFactory::InterpreterPushArgsAndConstruct(isolate_);
1115 Node* new_target = __ GetAccumulator();
1116 Node* constructor_reg = __ BytecodeOperandReg(0);
1117 Node* constructor = __ LoadRegister(constructor_reg);
1118 Node* first_arg_reg = __ BytecodeOperandReg(1);
1119 Node* first_arg = __ RegisterLocation(first_arg_reg);
1120 Node* args_count = __ BytecodeOperandCount(2);
1121 Node* context = __ GetContext();
1122 Node* result =
1123 __ CallConstruct(constructor, context, new_target, first_arg, args_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001124 __ SetAccumulator(result);
1125 __ Dispatch();
1126}
1127
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001128// New <constructor> <first_arg> <arg_count>
1129//
1130// Call operator new with |constructor| and the first argument in
1131// register |first_arg| and |arg_count| arguments in subsequent
Ben Murdoch097c5b22016-05-18 11:27:45 +01001132// registers. The new.target is in the accumulator.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001133//
Ben Murdoch097c5b22016-05-18 11:27:45 +01001134void Interpreter::DoNew(InterpreterAssembler* assembler) {
1135 DoCallConstruct(assembler);
1136}
1137
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001138// TestEqual <src>
1139//
1140// Test if the value in the <src> register equals the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001141void Interpreter::DoTestEqual(InterpreterAssembler* assembler) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001142 DoBinaryOp<EqualStub>(assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001143}
1144
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001145// TestNotEqual <src>
1146//
1147// Test if the value in the <src> register is not equal to the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001148void Interpreter::DoTestNotEqual(InterpreterAssembler* assembler) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001149 DoBinaryOp<NotEqualStub>(assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001150}
1151
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001152// TestEqualStrict <src>
1153//
1154// Test if the value in the <src> register is strictly equal to the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001155void Interpreter::DoTestEqualStrict(InterpreterAssembler* assembler) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001156 DoBinaryOp<StrictEqualStub>(assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001157}
1158
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001159// TestLessThan <src>
1160//
1161// Test if the value in the <src> register is less than the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001162void Interpreter::DoTestLessThan(InterpreterAssembler* assembler) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001163 DoBinaryOp<LessThanStub>(assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001164}
1165
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001166// TestGreaterThan <src>
1167//
1168// Test if the value in the <src> register is greater than the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001169void Interpreter::DoTestGreaterThan(InterpreterAssembler* assembler) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001170 DoBinaryOp<GreaterThanStub>(assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001171}
1172
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001173// TestLessThanOrEqual <src>
1174//
1175// Test if the value in the <src> register is less than or equal to the
1176// accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001177void Interpreter::DoTestLessThanOrEqual(InterpreterAssembler* assembler) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001178 DoBinaryOp<LessThanOrEqualStub>(assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001179}
1180
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001181// TestGreaterThanOrEqual <src>
1182//
1183// Test if the value in the <src> register is greater than or equal to the
1184// accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001185void Interpreter::DoTestGreaterThanOrEqual(InterpreterAssembler* assembler) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001186 DoBinaryOp<GreaterThanOrEqualStub>(assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001187}
1188
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001189// TestIn <src>
1190//
1191// Test if the object referenced by the register operand is a property of the
1192// object referenced by the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001193void Interpreter::DoTestIn(InterpreterAssembler* assembler) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001194 DoBinaryOp<HasPropertyStub>(assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001195}
1196
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001197// TestInstanceOf <src>
1198//
1199// Test if the object referenced by the <src> register is an an instance of type
1200// referenced by the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001201void Interpreter::DoTestInstanceOf(InterpreterAssembler* assembler) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001202 DoBinaryOp<InstanceOfStub>(assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001203}
1204
Ben Murdochda12d292016-06-02 14:46:10 +01001205// Jump <imm>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001206//
Ben Murdochda12d292016-06-02 14:46:10 +01001207// Jump by number of bytes represented by the immediate operand |imm|.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001208void Interpreter::DoJump(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001209 Node* relative_jump = __ BytecodeOperandImm(0);
1210 __ Jump(relative_jump);
1211}
1212
Ben Murdochda12d292016-06-02 14:46:10 +01001213// JumpConstant <idx>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001214//
Ben Murdochda12d292016-06-02 14:46:10 +01001215// Jump by number of bytes in the Smi in the |idx| entry in the constant pool.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001216void Interpreter::DoJumpConstant(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001217 Node* index = __ BytecodeOperandIdx(0);
1218 Node* constant = __ LoadConstantPoolEntry(index);
1219 Node* relative_jump = __ SmiUntag(constant);
1220 __ Jump(relative_jump);
1221}
1222
Ben Murdochda12d292016-06-02 14:46:10 +01001223// JumpIfTrue <imm>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001224//
1225// Jump by number of bytes represented by an immediate operand if the
1226// accumulator contains true.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001227void Interpreter::DoJumpIfTrue(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001228 Node* accumulator = __ GetAccumulator();
1229 Node* relative_jump = __ BytecodeOperandImm(0);
1230 Node* true_value = __ BooleanConstant(true);
1231 __ JumpIfWordEqual(accumulator, true_value, relative_jump);
1232}
1233
Ben Murdochda12d292016-06-02 14:46:10 +01001234// JumpIfTrueConstant <idx>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001235//
Ben Murdochda12d292016-06-02 14:46:10 +01001236// Jump by number of bytes in the Smi in the |idx| entry in the constant pool
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001237// if the accumulator contains true.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001238void Interpreter::DoJumpIfTrueConstant(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001239 Node* accumulator = __ GetAccumulator();
1240 Node* index = __ BytecodeOperandIdx(0);
1241 Node* constant = __ LoadConstantPoolEntry(index);
1242 Node* relative_jump = __ SmiUntag(constant);
1243 Node* true_value = __ BooleanConstant(true);
1244 __ JumpIfWordEqual(accumulator, true_value, relative_jump);
1245}
1246
Ben Murdochda12d292016-06-02 14:46:10 +01001247// JumpIfFalse <imm>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001248//
1249// Jump by number of bytes represented by an immediate operand if the
1250// accumulator contains false.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001251void Interpreter::DoJumpIfFalse(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001252 Node* accumulator = __ GetAccumulator();
1253 Node* relative_jump = __ BytecodeOperandImm(0);
1254 Node* false_value = __ BooleanConstant(false);
1255 __ JumpIfWordEqual(accumulator, false_value, relative_jump);
1256}
1257
Ben Murdochda12d292016-06-02 14:46:10 +01001258// JumpIfFalseConstant <idx>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001259//
Ben Murdochda12d292016-06-02 14:46:10 +01001260// Jump by number of bytes in the Smi in the |idx| entry in the constant pool
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001261// if the accumulator contains false.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001262void Interpreter::DoJumpIfFalseConstant(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001263 Node* accumulator = __ GetAccumulator();
1264 Node* index = __ BytecodeOperandIdx(0);
1265 Node* constant = __ LoadConstantPoolEntry(index);
1266 Node* relative_jump = __ SmiUntag(constant);
1267 Node* false_value = __ BooleanConstant(false);
1268 __ JumpIfWordEqual(accumulator, false_value, relative_jump);
1269}
1270
Ben Murdochda12d292016-06-02 14:46:10 +01001271// JumpIfToBooleanTrue <imm>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001272//
1273// Jump by number of bytes represented by an immediate operand if the object
1274// referenced by the accumulator is true when the object is cast to boolean.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001275void Interpreter::DoJumpIfToBooleanTrue(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001276 Node* accumulator = __ GetAccumulator();
Ben Murdoch61f157c2016-09-16 13:49:30 +01001277 Node* to_boolean_value = BuildToBoolean(accumulator, assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001278 Node* relative_jump = __ BytecodeOperandImm(0);
1279 Node* true_value = __ BooleanConstant(true);
1280 __ JumpIfWordEqual(to_boolean_value, true_value, relative_jump);
1281}
1282
Ben Murdochda12d292016-06-02 14:46:10 +01001283// JumpIfToBooleanTrueConstant <idx>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001284//
Ben Murdochda12d292016-06-02 14:46:10 +01001285// Jump by number of bytes in the Smi in the |idx| entry in the constant pool
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001286// if the object referenced by the accumulator is true when the object is cast
1287// to boolean.
1288void Interpreter::DoJumpIfToBooleanTrueConstant(
Ben Murdoch097c5b22016-05-18 11:27:45 +01001289 InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001290 Node* accumulator = __ GetAccumulator();
Ben Murdoch61f157c2016-09-16 13:49:30 +01001291 Node* to_boolean_value = BuildToBoolean(accumulator, assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001292 Node* index = __ BytecodeOperandIdx(0);
1293 Node* constant = __ LoadConstantPoolEntry(index);
1294 Node* relative_jump = __ SmiUntag(constant);
1295 Node* true_value = __ BooleanConstant(true);
1296 __ JumpIfWordEqual(to_boolean_value, true_value, relative_jump);
1297}
1298
Ben Murdochda12d292016-06-02 14:46:10 +01001299// JumpIfToBooleanFalse <imm>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001300//
1301// Jump by number of bytes represented by an immediate operand if the object
1302// referenced by the accumulator is false when the object is cast to boolean.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001303void Interpreter::DoJumpIfToBooleanFalse(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001304 Node* accumulator = __ GetAccumulator();
Ben Murdoch61f157c2016-09-16 13:49:30 +01001305 Node* to_boolean_value = BuildToBoolean(accumulator, assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001306 Node* relative_jump = __ BytecodeOperandImm(0);
1307 Node* false_value = __ BooleanConstant(false);
1308 __ JumpIfWordEqual(to_boolean_value, false_value, relative_jump);
1309}
1310
Ben Murdochda12d292016-06-02 14:46:10 +01001311// JumpIfToBooleanFalseConstant <idx>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001312//
Ben Murdochda12d292016-06-02 14:46:10 +01001313// Jump by number of bytes in the Smi in the |idx| entry in the constant pool
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001314// if the object referenced by the accumulator is false when the object is cast
1315// to boolean.
1316void Interpreter::DoJumpIfToBooleanFalseConstant(
Ben Murdoch097c5b22016-05-18 11:27:45 +01001317 InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001318 Node* accumulator = __ GetAccumulator();
Ben Murdoch61f157c2016-09-16 13:49:30 +01001319 Node* to_boolean_value = BuildToBoolean(accumulator, assembler);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001320 Node* index = __ BytecodeOperandIdx(0);
1321 Node* constant = __ LoadConstantPoolEntry(index);
1322 Node* relative_jump = __ SmiUntag(constant);
1323 Node* false_value = __ BooleanConstant(false);
1324 __ JumpIfWordEqual(to_boolean_value, false_value, relative_jump);
1325}
1326
Ben Murdochda12d292016-06-02 14:46:10 +01001327// JumpIfNull <imm>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001328//
1329// Jump by number of bytes represented by an immediate operand if the object
1330// referenced by the accumulator is the null constant.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001331void Interpreter::DoJumpIfNull(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001332 Node* accumulator = __ GetAccumulator();
1333 Node* null_value = __ HeapConstant(isolate_->factory()->null_value());
1334 Node* relative_jump = __ BytecodeOperandImm(0);
1335 __ JumpIfWordEqual(accumulator, null_value, relative_jump);
1336}
1337
Ben Murdochda12d292016-06-02 14:46:10 +01001338// JumpIfNullConstant <idx>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001339//
Ben Murdochda12d292016-06-02 14:46:10 +01001340// Jump by number of bytes in the Smi in the |idx| entry in the constant pool
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001341// if the object referenced by the accumulator is the null constant.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001342void Interpreter::DoJumpIfNullConstant(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001343 Node* accumulator = __ GetAccumulator();
1344 Node* null_value = __ HeapConstant(isolate_->factory()->null_value());
1345 Node* index = __ BytecodeOperandIdx(0);
1346 Node* constant = __ LoadConstantPoolEntry(index);
1347 Node* relative_jump = __ SmiUntag(constant);
1348 __ JumpIfWordEqual(accumulator, null_value, relative_jump);
1349}
1350
Ben Murdochda12d292016-06-02 14:46:10 +01001351// JumpIfUndefined <imm>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001352//
1353// Jump by number of bytes represented by an immediate operand if the object
1354// referenced by the accumulator is the undefined constant.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001355void Interpreter::DoJumpIfUndefined(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001356 Node* accumulator = __ GetAccumulator();
1357 Node* undefined_value =
1358 __ HeapConstant(isolate_->factory()->undefined_value());
1359 Node* relative_jump = __ BytecodeOperandImm(0);
1360 __ JumpIfWordEqual(accumulator, undefined_value, relative_jump);
1361}
1362
Ben Murdochda12d292016-06-02 14:46:10 +01001363// JumpIfUndefinedConstant <idx>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001364//
Ben Murdochda12d292016-06-02 14:46:10 +01001365// Jump by number of bytes in the Smi in the |idx| entry in the constant pool
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001366// if the object referenced by the accumulator is the undefined constant.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001367void Interpreter::DoJumpIfUndefinedConstant(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001368 Node* accumulator = __ GetAccumulator();
1369 Node* undefined_value =
1370 __ HeapConstant(isolate_->factory()->undefined_value());
1371 Node* index = __ BytecodeOperandIdx(0);
1372 Node* constant = __ LoadConstantPoolEntry(index);
1373 Node* relative_jump = __ SmiUntag(constant);
1374 __ JumpIfWordEqual(accumulator, undefined_value, relative_jump);
1375}
1376
Ben Murdochda12d292016-06-02 14:46:10 +01001377// JumpIfNotHole <imm>
Ben Murdoch097c5b22016-05-18 11:27:45 +01001378//
1379// Jump by number of bytes represented by an immediate operand if the object
1380// referenced by the accumulator is the hole.
1381void Interpreter::DoJumpIfNotHole(InterpreterAssembler* assembler) {
1382 Node* accumulator = __ GetAccumulator();
1383 Node* the_hole_value = __ HeapConstant(isolate_->factory()->the_hole_value());
1384 Node* relative_jump = __ BytecodeOperandImm(0);
1385 __ JumpIfWordNotEqual(accumulator, the_hole_value, relative_jump);
1386}
1387
Ben Murdochda12d292016-06-02 14:46:10 +01001388// JumpIfNotHoleConstant <idx>
Ben Murdoch097c5b22016-05-18 11:27:45 +01001389//
Ben Murdochda12d292016-06-02 14:46:10 +01001390// Jump by number of bytes in the Smi in the |idx| entry in the constant pool
Ben Murdoch097c5b22016-05-18 11:27:45 +01001391// if the object referenced by the accumulator is the hole constant.
1392void Interpreter::DoJumpIfNotHoleConstant(InterpreterAssembler* assembler) {
1393 Node* accumulator = __ GetAccumulator();
1394 Node* the_hole_value = __ HeapConstant(isolate_->factory()->the_hole_value());
1395 Node* index = __ BytecodeOperandIdx(0);
1396 Node* constant = __ LoadConstantPoolEntry(index);
1397 Node* relative_jump = __ SmiUntag(constant);
1398 __ JumpIfWordNotEqual(accumulator, the_hole_value, relative_jump);
1399}
1400
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001401// CreateRegExpLiteral <pattern_idx> <literal_idx> <flags>
1402//
1403// Creates a regular expression literal for literal index <literal_idx> with
1404// <flags> and the pattern in <pattern_idx>.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001405void Interpreter::DoCreateRegExpLiteral(InterpreterAssembler* assembler) {
Ben Murdochda12d292016-06-02 14:46:10 +01001406 Callable callable = CodeFactory::FastCloneRegExp(isolate_);
1407 Node* target = __ HeapConstant(callable.code());
1408 Node* index = __ BytecodeOperandIdx(0);
1409 Node* pattern = __ LoadConstantPoolEntry(index);
1410 Node* literal_index_raw = __ BytecodeOperandIdx(1);
1411 Node* literal_index = __ SmiTag(literal_index_raw);
1412 Node* flags_raw = __ BytecodeOperandFlag(2);
1413 Node* flags = __ SmiTag(flags_raw);
1414 Node* closure = __ LoadRegister(Register::function_closure());
1415 Node* context = __ GetContext();
1416 Node* result = __ CallStub(callable.descriptor(), target, context, closure,
1417 literal_index, pattern, flags);
1418 __ SetAccumulator(result);
1419 __ Dispatch();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001420}
1421
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001422// CreateArrayLiteral <element_idx> <literal_idx> <flags>
1423//
1424// Creates an array literal for literal index <literal_idx> with flags <flags>
1425// and constant elements in <element_idx>.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001426void Interpreter::DoCreateArrayLiteral(InterpreterAssembler* assembler) {
Ben Murdochc5610432016-08-08 18:44:38 +01001427 Node* index = __ BytecodeOperandIdx(0);
1428 Node* constant_elements = __ LoadConstantPoolEntry(index);
1429 Node* literal_index_raw = __ BytecodeOperandIdx(1);
1430 Node* literal_index = __ SmiTag(literal_index_raw);
1431 Node* flags_raw = __ BytecodeOperandFlag(2);
1432 Node* flags = __ SmiTag(flags_raw);
1433 Node* closure = __ LoadRegister(Register::function_closure());
1434 Node* context = __ GetContext();
1435 Node* result = __ CallRuntime(Runtime::kCreateArrayLiteral, context, closure,
1436 literal_index, constant_elements, flags);
1437 __ SetAccumulator(result);
1438 __ Dispatch();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001439}
1440
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001441// CreateObjectLiteral <element_idx> <literal_idx> <flags>
1442//
Ben Murdochc5610432016-08-08 18:44:38 +01001443// Creates an object literal for literal index <literal_idx> with
1444// CreateObjectLiteralFlags <flags> and constant elements in <element_idx>.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001445void Interpreter::DoCreateObjectLiteral(InterpreterAssembler* assembler) {
Ben Murdochc5610432016-08-08 18:44:38 +01001446 Node* literal_index_raw = __ BytecodeOperandIdx(1);
1447 Node* literal_index = __ SmiTag(literal_index_raw);
1448 Node* bytecode_flags = __ BytecodeOperandFlag(2);
1449 Node* closure = __ LoadRegister(Register::function_closure());
1450
1451 // Check if we can do a fast clone or have to call the runtime.
1452 Label if_fast_clone(assembler),
1453 if_not_fast_clone(assembler, Label::kDeferred);
1454 Node* fast_clone_properties_count =
1455 __ BitFieldDecode<CreateObjectLiteralFlags::FastClonePropertiesCountBits>(
1456 bytecode_flags);
1457 __ BranchIf(fast_clone_properties_count, &if_fast_clone, &if_not_fast_clone);
1458
1459 __ Bind(&if_fast_clone);
1460 {
1461 // If we can do a fast clone do the fast-path in FastCloneShallowObjectStub.
1462 Node* result = FastCloneShallowObjectStub::GenerateFastPath(
1463 assembler, &if_not_fast_clone, closure, literal_index,
1464 fast_clone_properties_count);
1465 __ SetAccumulator(result);
1466 __ Dispatch();
1467 }
1468
1469 __ Bind(&if_not_fast_clone);
1470 {
1471 // If we can't do a fast clone, call into the runtime.
1472 Node* index = __ BytecodeOperandIdx(0);
1473 Node* constant_elements = __ LoadConstantPoolEntry(index);
1474 Node* context = __ GetContext();
1475
1476 STATIC_ASSERT(CreateObjectLiteralFlags::FlagsBits::kShift == 0);
1477 Node* flags_raw = __ Word32And(
1478 bytecode_flags,
1479 __ Int32Constant(CreateObjectLiteralFlags::FlagsBits::kMask));
1480 Node* flags = __ SmiTag(flags_raw);
1481
1482 Node* result =
1483 __ CallRuntime(Runtime::kCreateObjectLiteral, context, closure,
1484 literal_index, constant_elements, flags);
1485 __ SetAccumulator(result);
1486 __ Dispatch();
1487 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001488}
1489
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001490// CreateClosure <index> <tenured>
1491//
1492// Creates a new closure for SharedFunctionInfo at position |index| in the
1493// constant pool and with the PretenureFlag <tenured>.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001494void Interpreter::DoCreateClosure(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001495 // TODO(rmcilroy): Possibly call FastNewClosureStub when possible instead of
1496 // calling into the runtime.
1497 Node* index = __ BytecodeOperandIdx(0);
1498 Node* shared = __ LoadConstantPoolEntry(index);
Ben Murdochda12d292016-06-02 14:46:10 +01001499 Node* tenured_raw = __ BytecodeOperandFlag(1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001500 Node* tenured = __ SmiTag(tenured_raw);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001501 Node* context = __ GetContext();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001502 Node* result =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001503 __ CallRuntime(Runtime::kInterpreterNewClosure, context, shared, tenured);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001504 __ SetAccumulator(result);
1505 __ Dispatch();
1506}
1507
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001508// CreateMappedArguments
1509//
1510// Creates a new mapped arguments object.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001511void Interpreter::DoCreateMappedArguments(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001512 Node* closure = __ LoadRegister(Register::function_closure());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001513 Node* context = __ GetContext();
Ben Murdochc5610432016-08-08 18:44:38 +01001514
1515 Label if_duplicate_parameters(assembler, Label::kDeferred);
1516 Label if_not_duplicate_parameters(assembler);
1517
1518 // Check if function has duplicate parameters.
1519 // TODO(rmcilroy): Remove this check when FastNewSloppyArgumentsStub supports
1520 // duplicate parameters.
1521 Node* shared_info =
1522 __ LoadObjectField(closure, JSFunction::kSharedFunctionInfoOffset);
1523 Node* compiler_hints = __ LoadObjectField(
1524 shared_info, SharedFunctionInfo::kHasDuplicateParametersByteOffset,
1525 MachineType::Uint8());
1526 Node* duplicate_parameters_bit = __ Int32Constant(
1527 1 << SharedFunctionInfo::kHasDuplicateParametersBitWithinByte);
1528 Node* compare = __ Word32And(compiler_hints, duplicate_parameters_bit);
1529 __ BranchIf(compare, &if_duplicate_parameters, &if_not_duplicate_parameters);
1530
1531 __ Bind(&if_not_duplicate_parameters);
1532 {
1533 // TODO(rmcilroy): Inline FastNewSloppyArguments when it is a TurboFan stub.
1534 Callable callable = CodeFactory::FastNewSloppyArguments(isolate_, true);
1535 Node* target = __ HeapConstant(callable.code());
1536 Node* result = __ CallStub(callable.descriptor(), target, context, closure);
1537 __ SetAccumulator(result);
1538 __ Dispatch();
1539 }
1540
1541 __ Bind(&if_duplicate_parameters);
1542 {
1543 Node* result =
1544 __ CallRuntime(Runtime::kNewSloppyArguments_Generic, context, closure);
1545 __ SetAccumulator(result);
1546 __ Dispatch();
1547 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001548}
1549
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001550// CreateUnmappedArguments
1551//
1552// Creates a new unmapped arguments object.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001553void Interpreter::DoCreateUnmappedArguments(InterpreterAssembler* assembler) {
Ben Murdochc5610432016-08-08 18:44:38 +01001554 // TODO(rmcilroy): Inline FastNewStrictArguments when it is a TurboFan stub.
1555 Callable callable = CodeFactory::FastNewStrictArguments(isolate_, true);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001556 Node* target = __ HeapConstant(callable.code());
1557 Node* context = __ GetContext();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001558 Node* closure = __ LoadRegister(Register::function_closure());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001559 Node* result = __ CallStub(callable.descriptor(), target, context, closure);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001560 __ SetAccumulator(result);
1561 __ Dispatch();
1562}
1563
Ben Murdoch097c5b22016-05-18 11:27:45 +01001564// CreateRestParameter
1565//
1566// Creates a new rest parameter array.
1567void Interpreter::DoCreateRestParameter(InterpreterAssembler* assembler) {
Ben Murdochc5610432016-08-08 18:44:38 +01001568 // TODO(rmcilroy): Inline FastNewRestArguments when it is a TurboFan stub.
1569 Callable callable = CodeFactory::FastNewRestParameter(isolate_, true);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001570 Node* target = __ HeapConstant(callable.code());
1571 Node* closure = __ LoadRegister(Register::function_closure());
1572 Node* context = __ GetContext();
1573 Node* result = __ CallStub(callable.descriptor(), target, context, closure);
1574 __ SetAccumulator(result);
1575 __ Dispatch();
1576}
1577
1578// StackCheck
1579//
1580// Performs a stack guard check.
1581void Interpreter::DoStackCheck(InterpreterAssembler* assembler) {
Ben Murdochc5610432016-08-08 18:44:38 +01001582 Label ok(assembler), stack_check_interrupt(assembler, Label::kDeferred);
1583
1584 Node* interrupt = __ StackCheckTriggeredInterrupt();
1585 __ BranchIf(interrupt, &stack_check_interrupt, &ok);
1586
1587 __ Bind(&ok);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001588 __ Dispatch();
Ben Murdochc5610432016-08-08 18:44:38 +01001589
1590 __ Bind(&stack_check_interrupt);
1591 {
1592 Node* context = __ GetContext();
1593 __ CallRuntime(Runtime::kStackGuard, context);
1594 __ Dispatch();
1595 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001596}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001597
1598// Throw
1599//
1600// Throws the exception in the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001601void Interpreter::DoThrow(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001602 Node* exception = __ GetAccumulator();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001603 Node* context = __ GetContext();
1604 __ CallRuntime(Runtime::kThrow, context, exception);
1605 // We shouldn't ever return from a throw.
1606 __ Abort(kUnexpectedReturnFromThrow);
1607}
1608
Ben Murdoch097c5b22016-05-18 11:27:45 +01001609// ReThrow
1610//
1611// Re-throws the exception in the accumulator.
1612void Interpreter::DoReThrow(InterpreterAssembler* assembler) {
1613 Node* exception = __ GetAccumulator();
1614 Node* context = __ GetContext();
1615 __ CallRuntime(Runtime::kReThrow, context, exception);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001616 // We shouldn't ever return from a throw.
1617 __ Abort(kUnexpectedReturnFromThrow);
1618}
1619
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001620// Return
1621//
1622// Return the value in the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001623void Interpreter::DoReturn(InterpreterAssembler* assembler) {
Ben Murdochc5610432016-08-08 18:44:38 +01001624 __ UpdateInterruptBudgetOnReturn();
1625 Node* accumulator = __ GetAccumulator();
1626 __ Return(accumulator);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001627}
1628
Ben Murdoch097c5b22016-05-18 11:27:45 +01001629// Debugger
1630//
1631// Call runtime to handle debugger statement.
1632void Interpreter::DoDebugger(InterpreterAssembler* assembler) {
1633 Node* context = __ GetContext();
1634 __ CallRuntime(Runtime::kHandleDebuggerStatement, context);
1635 __ Dispatch();
1636}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001637
Ben Murdoch097c5b22016-05-18 11:27:45 +01001638// DebugBreak
1639//
1640// Call runtime to handle a debug break.
Ben Murdochda12d292016-06-02 14:46:10 +01001641#define DEBUG_BREAK(Name, ...) \
1642 void Interpreter::Do##Name(InterpreterAssembler* assembler) { \
1643 Node* context = __ GetContext(); \
1644 Node* accumulator = __ GetAccumulator(); \
1645 Node* original_handler = \
1646 __ CallRuntime(Runtime::kDebugBreakOnBytecode, context, accumulator); \
1647 __ DispatchToBytecodeHandler(original_handler); \
Ben Murdoch097c5b22016-05-18 11:27:45 +01001648 }
1649DEBUG_BREAK_BYTECODE_LIST(DEBUG_BREAK);
1650#undef DEBUG_BREAK
1651
1652// ForInPrepare <cache_info_triple>
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001653//
1654// Returns state for for..in loop execution based on the object in the
Ben Murdoch097c5b22016-05-18 11:27:45 +01001655// accumulator. The result is output in registers |cache_info_triple| to
1656// |cache_info_triple + 2|, with the registers holding cache_type, cache_array,
1657// and cache_length respectively.
1658void Interpreter::DoForInPrepare(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001659 Node* object = __ GetAccumulator();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001660 Node* context = __ GetContext();
1661 Node* result_triple = __ CallRuntime(Runtime::kForInPrepare, context, object);
1662
1663 // Set output registers:
1664 // 0 == cache_type, 1 == cache_array, 2 == cache_length
1665 Node* output_register = __ BytecodeOperandReg(0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001666 for (int i = 0; i < 3; i++) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001667 Node* cache_info = __ Projection(i, result_triple);
1668 __ StoreRegister(cache_info, output_register);
1669 output_register = __ NextRegister(output_register);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001670 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001671 __ Dispatch();
1672}
1673
Ben Murdoch097c5b22016-05-18 11:27:45 +01001674// ForInNext <receiver> <index> <cache_info_pair>
1675//
1676// Returns the next enumerable property in the the accumulator.
1677void Interpreter::DoForInNext(InterpreterAssembler* assembler) {
1678 Node* receiver_reg = __ BytecodeOperandReg(0);
1679 Node* receiver = __ LoadRegister(receiver_reg);
1680 Node* index_reg = __ BytecodeOperandReg(1);
1681 Node* index = __ LoadRegister(index_reg);
1682 Node* cache_type_reg = __ BytecodeOperandReg(2);
1683 Node* cache_type = __ LoadRegister(cache_type_reg);
1684 Node* cache_array_reg = __ NextRegister(cache_type_reg);
1685 Node* cache_array = __ LoadRegister(cache_array_reg);
Ben Murdochda12d292016-06-02 14:46:10 +01001686
1687 // Load the next key from the enumeration array.
Ben Murdochc5610432016-08-08 18:44:38 +01001688 Node* key = __ LoadFixedArrayElement(cache_array, index, 0,
1689 CodeStubAssembler::SMI_PARAMETERS);
Ben Murdochda12d292016-06-02 14:46:10 +01001690
1691 // Check if we can use the for-in fast path potentially using the enum cache.
Ben Murdochc5610432016-08-08 18:44:38 +01001692 Label if_fast(assembler), if_slow(assembler, Label::kDeferred);
Ben Murdochda12d292016-06-02 14:46:10 +01001693 Node* receiver_map = __ LoadObjectField(receiver, HeapObject::kMapOffset);
1694 Node* condition = __ WordEqual(receiver_map, cache_type);
Ben Murdochc5610432016-08-08 18:44:38 +01001695 __ BranchIf(condition, &if_fast, &if_slow);
Ben Murdochda12d292016-06-02 14:46:10 +01001696 __ Bind(&if_fast);
1697 {
1698 // Enum cache in use for {receiver}, the {key} is definitely valid.
1699 __ SetAccumulator(key);
1700 __ Dispatch();
1701 }
1702 __ Bind(&if_slow);
1703 {
1704 // Record the fact that we hit the for-in slow path.
1705 Node* vector_index = __ BytecodeOperandIdx(3);
1706 Node* type_feedback_vector = __ LoadTypeFeedbackVector();
1707 Node* megamorphic_sentinel =
1708 __ HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate_));
Ben Murdochc5610432016-08-08 18:44:38 +01001709 __ StoreFixedArrayElement(type_feedback_vector, vector_index,
1710 megamorphic_sentinel, SKIP_WRITE_BARRIER);
Ben Murdochda12d292016-06-02 14:46:10 +01001711
1712 // Need to filter the {key} for the {receiver}.
1713 Node* context = __ GetContext();
1714 Node* result =
1715 __ CallRuntime(Runtime::kForInFilter, context, receiver, key);
1716 __ SetAccumulator(result);
1717 __ Dispatch();
1718 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001719}
1720
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001721// ForInDone <index> <cache_length>
1722//
1723// Returns true if the end of the enumerable properties has been reached.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001724void Interpreter::DoForInDone(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001725 Node* index_reg = __ BytecodeOperandReg(0);
1726 Node* index = __ LoadRegister(index_reg);
1727 Node* cache_length_reg = __ BytecodeOperandReg(1);
1728 Node* cache_length = __ LoadRegister(cache_length_reg);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001729
Ben Murdochda12d292016-06-02 14:46:10 +01001730 // Check if {index} is at {cache_length} already.
Ben Murdochc5610432016-08-08 18:44:38 +01001731 Label if_true(assembler), if_false(assembler), end(assembler);
1732 __ BranchIfWordEqual(index, cache_length, &if_true, &if_false);
Ben Murdochda12d292016-06-02 14:46:10 +01001733 __ Bind(&if_true);
1734 {
Ben Murdochc5610432016-08-08 18:44:38 +01001735 __ SetAccumulator(__ BooleanConstant(true));
1736 __ Goto(&end);
Ben Murdochda12d292016-06-02 14:46:10 +01001737 }
1738 __ Bind(&if_false);
1739 {
Ben Murdochc5610432016-08-08 18:44:38 +01001740 __ SetAccumulator(__ BooleanConstant(false));
1741 __ Goto(&end);
Ben Murdochda12d292016-06-02 14:46:10 +01001742 }
Ben Murdochc5610432016-08-08 18:44:38 +01001743 __ Bind(&end);
1744 __ Dispatch();
Ben Murdochda12d292016-06-02 14:46:10 +01001745}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001746
1747// ForInStep <index>
1748//
1749// Increments the loop counter in register |index| and stores the result
1750// in the accumulator.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001751void Interpreter::DoForInStep(InterpreterAssembler* assembler) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001752 Node* index_reg = __ BytecodeOperandReg(0);
1753 Node* index = __ LoadRegister(index_reg);
Ben Murdochda12d292016-06-02 14:46:10 +01001754 Node* one = __ SmiConstant(Smi::FromInt(1));
1755 Node* result = __ SmiAdd(index, one);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001756 __ SetAccumulator(result);
1757 __ Dispatch();
1758}
1759
Ben Murdochda12d292016-06-02 14:46:10 +01001760// Wide
1761//
1762// Prefix bytecode indicating next bytecode has wide (16-bit) operands.
1763void Interpreter::DoWide(InterpreterAssembler* assembler) {
1764 __ DispatchWide(OperandScale::kDouble);
1765}
1766
1767// ExtraWide
1768//
1769// Prefix bytecode indicating next bytecode has extra-wide (32-bit) operands.
1770void Interpreter::DoExtraWide(InterpreterAssembler* assembler) {
1771 __ DispatchWide(OperandScale::kQuadruple);
1772}
1773
1774// Illegal
1775//
1776// An invalid bytecode aborting execution if dispatched.
1777void Interpreter::DoIllegal(InterpreterAssembler* assembler) {
1778 __ Abort(kInvalidBytecode);
1779}
1780
Ben Murdochc5610432016-08-08 18:44:38 +01001781// Nop
1782//
1783// No operation.
1784void Interpreter::DoNop(InterpreterAssembler* assembler) { __ Dispatch(); }
1785
1786// SuspendGenerator <generator>
1787//
1788// Exports the register file and stores it into the generator. Also stores the
Ben Murdoch61f157c2016-09-16 13:49:30 +01001789// current context, the state given in the accumulator, and the current bytecode
1790// offset (for debugging purposes) into the generator.
Ben Murdochc5610432016-08-08 18:44:38 +01001791void Interpreter::DoSuspendGenerator(InterpreterAssembler* assembler) {
1792 Node* generator_reg = __ BytecodeOperandReg(0);
1793 Node* generator = __ LoadRegister(generator_reg);
1794
Ben Murdoch61f157c2016-09-16 13:49:30 +01001795 Label if_stepping(assembler, Label::kDeferred), ok(assembler);
1796 Node* step_action_address = __ ExternalConstant(
1797 ExternalReference::debug_last_step_action_address(isolate_));
1798 Node* step_action = __ Load(MachineType::Int8(), step_action_address);
1799 STATIC_ASSERT(StepIn > StepNext);
1800 STATIC_ASSERT(StepFrame > StepNext);
1801 STATIC_ASSERT(LastStepAction == StepFrame);
1802 Node* step_next = __ Int32Constant(StepNext);
1803 __ BranchIfInt32LessThanOrEqual(step_next, step_action, &if_stepping, &ok);
1804 __ Bind(&ok);
1805
Ben Murdochc5610432016-08-08 18:44:38 +01001806 Node* array =
1807 __ LoadObjectField(generator, JSGeneratorObject::kOperandStackOffset);
1808 Node* context = __ GetContext();
1809 Node* state = __ GetAccumulator();
1810
1811 __ ExportRegisterFile(array);
1812 __ StoreObjectField(generator, JSGeneratorObject::kContextOffset, context);
1813 __ StoreObjectField(generator, JSGeneratorObject::kContinuationOffset, state);
1814
Ben Murdoch61f157c2016-09-16 13:49:30 +01001815 Node* offset = __ SmiTag(__ BytecodeOffset());
1816 __ StoreObjectField(generator, JSGeneratorObject::kInputOrDebugPosOffset,
1817 offset);
1818
Ben Murdochc5610432016-08-08 18:44:38 +01001819 __ Dispatch();
Ben Murdoch61f157c2016-09-16 13:49:30 +01001820
1821 __ Bind(&if_stepping);
1822 {
1823 Node* context = __ GetContext();
1824 __ CallRuntime(Runtime::kDebugRecordAsyncFunction, context, generator);
1825 __ Goto(&ok);
1826 }
Ben Murdochc5610432016-08-08 18:44:38 +01001827}
1828
1829// ResumeGenerator <generator>
1830//
1831// Imports the register file stored in the generator. Also loads the
1832// generator's state and stores it in the accumulator, before overwriting it
1833// with kGeneratorExecuting.
1834void Interpreter::DoResumeGenerator(InterpreterAssembler* assembler) {
1835 Node* generator_reg = __ BytecodeOperandReg(0);
1836 Node* generator = __ LoadRegister(generator_reg);
1837
1838 __ ImportRegisterFile(
1839 __ LoadObjectField(generator, JSGeneratorObject::kOperandStackOffset));
1840
1841 Node* old_state =
1842 __ LoadObjectField(generator, JSGeneratorObject::kContinuationOffset);
1843 Node* new_state = __ Int32Constant(JSGeneratorObject::kGeneratorExecuting);
1844 __ StoreObjectField(generator, JSGeneratorObject::kContinuationOffset,
1845 __ SmiTag(new_state));
1846 __ SetAccumulator(old_state);
1847
1848 __ Dispatch();
1849}
1850
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001851} // namespace interpreter
1852} // namespace internal
1853} // namespace v8