1 // 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
7 #include "src/code-factory.h"
8 #include "src/compiler.h"
9 #include "src/compiler/interpreter-assembler.h"
10 #include "src/factory.h"
11 #include "src/interpreter/bytecode-generator.h"
12 #include "src/interpreter/bytecodes.h"
13 #include "src/zone.h"
14
15 namespace v8 {
16 namespace internal {
17 namespace interpreter {
18
19 using compiler::Node;
20
21 #define __ assembler->
22
23
Interpreter(Isolate * isolate)24 Interpreter::Interpreter(Isolate* isolate)
25 : isolate_(isolate) {}
26
27
28 // static
CreateUninitializedInterpreterTable(Isolate * isolate)29 Handle<FixedArray> Interpreter::CreateUninitializedInterpreterTable(
30 Isolate* isolate) {
31 Handle<FixedArray> handler_table = isolate->factory()->NewFixedArray(
32 static_cast<int>(Bytecode::kLast) + 1, TENURED);
33 // We rely on the interpreter handler table being immovable, so check that
34 // it was allocated on the first page (which is always immovable).
35 DCHECK(isolate->heap()->old_space()->FirstPage()->Contains(
36 handler_table->address()));
37 return handler_table;
38 }
39
40
Initialize()41 void Interpreter::Initialize() {
42 DCHECK(FLAG_ignition);
43 Handle<FixedArray> handler_table = isolate_->factory()->interpreter_table();
44 if (!IsInterpreterTableInitialized(handler_table)) {
45 Zone zone;
46 HandleScope scope(isolate_);
47
48 #define GENERATE_CODE(Name, ...) \
49 { \
50 compiler::InterpreterAssembler assembler(isolate_, &zone, \
51 Bytecode::k##Name); \
52 Do##Name(&assembler); \
53 Handle<Code> code = assembler.GenerateCode(); \
54 handler_table->set(static_cast<int>(Bytecode::k##Name), *code); \
55 }
56 BYTECODE_LIST(GENERATE_CODE)
57 #undef GENERATE_CODE
58 }
59 }
60
61
MakeBytecode(CompilationInfo * info)62 bool Interpreter::MakeBytecode(CompilationInfo* info) {
63 BytecodeGenerator generator(info->isolate(), info->zone());
64 info->EnsureFeedbackVector();
65 Handle<BytecodeArray> bytecodes = generator.MakeBytecode(info);
66 if (FLAG_print_bytecode) {
67 OFStream os(stdout);
68 os << "Function: " << info->GetDebugName().get() << std::endl;
69 bytecodes->Print(os);
70 os << std::flush;
71 }
72
73 info->SetBytecodeArray(bytecodes);
74 info->SetCode(info->isolate()->builtins()->InterpreterEntryTrampoline());
75 return true;
76 }
77
78
IsInterpreterTableInitialized(Handle<FixedArray> handler_table)79 bool Interpreter::IsInterpreterTableInitialized(
80 Handle<FixedArray> handler_table) {
81 DCHECK(handler_table->length() == static_cast<int>(Bytecode::kLast) + 1);
82 return handler_table->get(0) != isolate_->heap()->undefined_value();
83 }
84
85
86 // LdaZero
87 //
88 // Load literal '0' into the accumulator.
DoLdaZero(compiler::InterpreterAssembler * assembler)89 void Interpreter::DoLdaZero(compiler::InterpreterAssembler* assembler) {
90 Node* zero_value = __ NumberConstant(0.0);
91 __ SetAccumulator(zero_value);
92 __ Dispatch();
93 }
94
95
96 // LdaSmi8 <imm8>
97 //
98 // Load an 8-bit integer literal into the accumulator as a Smi.
DoLdaSmi8(compiler::InterpreterAssembler * assembler)99 void Interpreter::DoLdaSmi8(compiler::InterpreterAssembler* assembler) {
100 Node* raw_int = __ BytecodeOperandImm(0);
101 Node* smi_int = __ SmiTag(raw_int);
102 __ SetAccumulator(smi_int);
103 __ Dispatch();
104 }
105
106
DoLoadConstant(compiler::InterpreterAssembler * assembler)107 void Interpreter::DoLoadConstant(compiler::InterpreterAssembler* assembler) {
108 Node* index = __ BytecodeOperandIdx(0);
109 Node* constant = __ LoadConstantPoolEntry(index);
110 __ SetAccumulator(constant);
111 __ Dispatch();
112 }
113
114
115 // LdaConstant <idx>
116 //
117 // Load constant literal at |idx| in the constant pool into the accumulator.
DoLdaConstant(compiler::InterpreterAssembler * assembler)118 void Interpreter::DoLdaConstant(compiler::InterpreterAssembler* assembler) {
119 DoLoadConstant(assembler);
120 }
121
122
123 // LdaConstantWide <idx>
124 //
125 // Load constant literal at |idx| in the constant pool into the accumulator.
DoLdaConstantWide(compiler::InterpreterAssembler * assembler)126 void Interpreter::DoLdaConstantWide(compiler::InterpreterAssembler* assembler) {
127 DoLoadConstant(assembler);
128 }
129
130
131 // LdaUndefined
132 //
133 // Load Undefined into the accumulator.
DoLdaUndefined(compiler::InterpreterAssembler * assembler)134 void Interpreter::DoLdaUndefined(compiler::InterpreterAssembler* assembler) {
135 Node* undefined_value =
136 __ HeapConstant(isolate_->factory()->undefined_value());
137 __ SetAccumulator(undefined_value);
138 __ Dispatch();
139 }
140
141
142 // LdaNull
143 //
144 // Load Null into the accumulator.
DoLdaNull(compiler::InterpreterAssembler * assembler)145 void Interpreter::DoLdaNull(compiler::InterpreterAssembler* assembler) {
146 Node* null_value = __ HeapConstant(isolate_->factory()->null_value());
147 __ SetAccumulator(null_value);
148 __ Dispatch();
149 }
150
151
152 // LdaTheHole
153 //
154 // Load TheHole into the accumulator.
DoLdaTheHole(compiler::InterpreterAssembler * assembler)155 void Interpreter::DoLdaTheHole(compiler::InterpreterAssembler* assembler) {
156 Node* the_hole_value = __ HeapConstant(isolate_->factory()->the_hole_value());
157 __ SetAccumulator(the_hole_value);
158 __ Dispatch();
159 }
160
161
162 // LdaTrue
163 //
164 // Load True into the accumulator.
DoLdaTrue(compiler::InterpreterAssembler * assembler)165 void Interpreter::DoLdaTrue(compiler::InterpreterAssembler* assembler) {
166 Node* true_value = __ HeapConstant(isolate_->factory()->true_value());
167 __ SetAccumulator(true_value);
168 __ Dispatch();
169 }
170
171
172 // LdaFalse
173 //
174 // Load False into the accumulator.
DoLdaFalse(compiler::InterpreterAssembler * assembler)175 void Interpreter::DoLdaFalse(compiler::InterpreterAssembler* assembler) {
176 Node* false_value = __ HeapConstant(isolate_->factory()->false_value());
177 __ SetAccumulator(false_value);
178 __ Dispatch();
179 }
180
181
182 // Ldar <src>
183 //
184 // Load accumulator with value from register <src>.
DoLdar(compiler::InterpreterAssembler * assembler)185 void Interpreter::DoLdar(compiler::InterpreterAssembler* assembler) {
186 Node* reg_index = __ BytecodeOperandReg(0);
187 Node* value = __ LoadRegister(reg_index);
188 __ SetAccumulator(value);
189 __ Dispatch();
190 }
191
192
193 // Star <dst>
194 //
195 // Store accumulator to register <dst>.
DoStar(compiler::InterpreterAssembler * assembler)196 void Interpreter::DoStar(compiler::InterpreterAssembler* assembler) {
197 Node* reg_index = __ BytecodeOperandReg(0);
198 Node* accumulator = __ GetAccumulator();
199 __ StoreRegister(accumulator, reg_index);
200 __ Dispatch();
201 }
202
203
204 // Exchange <reg8> <reg16>
205 //
206 // Exchange two registers.
DoExchange(compiler::InterpreterAssembler * assembler)207 void Interpreter::DoExchange(compiler::InterpreterAssembler* assembler) {
208 Node* reg0_index = __ BytecodeOperandReg(0);
209 Node* reg1_index = __ BytecodeOperandReg(1);
210 Node* reg0_value = __ LoadRegister(reg0_index);
211 Node* reg1_value = __ LoadRegister(reg1_index);
212 __ StoreRegister(reg1_value, reg0_index);
213 __ StoreRegister(reg0_value, reg1_index);
214 __ Dispatch();
215 }
216
217
218 // ExchangeWide <reg16> <reg16>
219 //
220 // Exchange two registers.
DoExchangeWide(compiler::InterpreterAssembler * assembler)221 void Interpreter::DoExchangeWide(compiler::InterpreterAssembler* assembler) {
222 return DoExchange(assembler);
223 }
224
225
226 // Mov <src> <dst>
227 //
228 // Stores the value of register <src> to register <dst>.
DoMov(compiler::InterpreterAssembler * assembler)229 void Interpreter::DoMov(compiler::InterpreterAssembler* assembler) {
230 Node* src_index = __ BytecodeOperandReg(0);
231 Node* src_value = __ LoadRegister(src_index);
232 Node* dst_index = __ BytecodeOperandReg(1);
233 __ StoreRegister(src_value, dst_index);
234 __ Dispatch();
235 }
236
237
DoLoadGlobal(Callable ic,compiler::InterpreterAssembler * assembler)238 void Interpreter::DoLoadGlobal(Callable ic,
239 compiler::InterpreterAssembler* assembler) {
240 // Get the global object.
241 Node* context = __ GetContext();
242 Node* native_context =
243 __ LoadContextSlot(context, Context::NATIVE_CONTEXT_INDEX);
244 Node* global = __ LoadContextSlot(native_context, Context::EXTENSION_INDEX);
245
246 // Load the global via the LoadIC.
247 Node* code_target = __ HeapConstant(ic.code());
248 Node* constant_index = __ BytecodeOperandIdx(0);
249 Node* name = __ LoadConstantPoolEntry(constant_index);
250 Node* raw_slot = __ BytecodeOperandIdx(1);
251 Node* smi_slot = __ SmiTag(raw_slot);
252 Node* type_feedback_vector = __ LoadTypeFeedbackVector();
253 Node* result = __ CallIC(ic.descriptor(), code_target, global, name, smi_slot,
254 type_feedback_vector);
255 __ SetAccumulator(result);
256 __ Dispatch();
257 }
258
259
260 // LdaGlobalSloppy <name_index> <slot>
261 //
262 // Load the global with name in constant pool entry <name_index> into the
263 // accumulator using FeedBackVector slot <slot> in sloppy mode.
DoLdaGlobalSloppy(compiler::InterpreterAssembler * assembler)264 void Interpreter::DoLdaGlobalSloppy(compiler::InterpreterAssembler* assembler) {
265 Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF,
266 SLOPPY, UNINITIALIZED);
267 DoLoadGlobal(ic, assembler);
268 }
269
270
271 // LdaGlobalSloppy <name_index> <slot>
272 //
273 // Load the global with name in constant pool entry <name_index> into the
274 // accumulator using FeedBackVector slot <slot> in strict mode.
DoLdaGlobalStrict(compiler::InterpreterAssembler * assembler)275 void Interpreter::DoLdaGlobalStrict(compiler::InterpreterAssembler* assembler) {
276 Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF,
277 STRICT, UNINITIALIZED);
278 DoLoadGlobal(ic, assembler);
279 }
280
281
282 // LdaGlobalInsideTypeofSloppy <name_index> <slot>
283 //
284 // Load the global with name in constant pool entry <name_index> into the
285 // accumulator using FeedBackVector slot <slot> in sloppy mode.
DoLdaGlobalInsideTypeofSloppy(compiler::InterpreterAssembler * assembler)286 void Interpreter::DoLdaGlobalInsideTypeofSloppy(
287 compiler::InterpreterAssembler* assembler) {
288 Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, INSIDE_TYPEOF,
289 SLOPPY, UNINITIALIZED);
290 DoLoadGlobal(ic, assembler);
291 }
292
293
294 // LdaGlobalInsideTypeofStrict <name_index> <slot>
295 //
296 // Load the global with name in constant pool entry <name_index> into the
297 // accumulator using FeedBackVector slot <slot> in strict mode.
DoLdaGlobalInsideTypeofStrict(compiler::InterpreterAssembler * assembler)298 void Interpreter::DoLdaGlobalInsideTypeofStrict(
299 compiler::InterpreterAssembler* assembler) {
300 Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, INSIDE_TYPEOF,
301 STRICT, UNINITIALIZED);
302 DoLoadGlobal(ic, assembler);
303 }
304
305
306 // LdaGlobalSloppyWide <name_index> <slot>
307 //
308 // Load the global with name in constant pool entry <name_index> into the
309 // accumulator using FeedBackVector slot <slot> in sloppy mode.
DoLdaGlobalSloppyWide(compiler::InterpreterAssembler * assembler)310 void Interpreter::DoLdaGlobalSloppyWide(
311 compiler::InterpreterAssembler* assembler) {
312 Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF,
313 SLOPPY, UNINITIALIZED);
314 DoLoadGlobal(ic, assembler);
315 }
316
317
318 // LdaGlobalSloppyWide <name_index> <slot>
319 //
320 // Load the global with name in constant pool entry <name_index> into the
321 // accumulator using FeedBackVector slot <slot> in strict mode.
DoLdaGlobalStrictWide(compiler::InterpreterAssembler * assembler)322 void Interpreter::DoLdaGlobalStrictWide(
323 compiler::InterpreterAssembler* assembler) {
324 Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF,
325 STRICT, UNINITIALIZED);
326 DoLoadGlobal(ic, assembler);
327 }
328
329
330 // LdaGlobalInsideTypeofSloppyWide <name_index> <slot>
331 //
332 // Load the global with name in constant pool entry <name_index> into the
333 // accumulator using FeedBackVector slot <slot> in sloppy mode.
DoLdaGlobalInsideTypeofSloppyWide(compiler::InterpreterAssembler * assembler)334 void Interpreter::DoLdaGlobalInsideTypeofSloppyWide(
335 compiler::InterpreterAssembler* assembler) {
336 Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, INSIDE_TYPEOF,
337 SLOPPY, UNINITIALIZED);
338 DoLoadGlobal(ic, assembler);
339 }
340
341
342 // LdaGlobalInsideTypeofSloppyWide <name_index> <slot>
343 //
344 // Load the global with name in constant pool entry <name_index> into the
345 // accumulator using FeedBackVector slot <slot> in strict mode.
DoLdaGlobalInsideTypeofStrictWide(compiler::InterpreterAssembler * assembler)346 void Interpreter::DoLdaGlobalInsideTypeofStrictWide(
347 compiler::InterpreterAssembler* assembler) {
348 Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, INSIDE_TYPEOF,
349 STRICT, UNINITIALIZED);
350 DoLoadGlobal(ic, assembler);
351 }
352
353
DoStoreGlobal(Callable ic,compiler::InterpreterAssembler * assembler)354 void Interpreter::DoStoreGlobal(Callable ic,
355 compiler::InterpreterAssembler* assembler) {
356 // Get the global object.
357 Node* context = __ GetContext();
358 Node* native_context =
359 __ LoadContextSlot(context, Context::NATIVE_CONTEXT_INDEX);
360 Node* global = __ LoadContextSlot(native_context, Context::EXTENSION_INDEX);
361
362 // Store the global via the StoreIC.
363 Node* code_target = __ HeapConstant(ic.code());
364 Node* constant_index = __ BytecodeOperandIdx(0);
365 Node* name = __ LoadConstantPoolEntry(constant_index);
366 Node* value = __ GetAccumulator();
367 Node* raw_slot = __ BytecodeOperandIdx(1);
368 Node* smi_slot = __ SmiTag(raw_slot);
369 Node* type_feedback_vector = __ LoadTypeFeedbackVector();
370 __ CallIC(ic.descriptor(), code_target, global, name, value, smi_slot,
371 type_feedback_vector);
372
373 __ Dispatch();
374 }
375
376
377 // StaGlobalSloppy <name_index> <slot>
378 //
379 // Store the value in the accumulator into the global with name in constant pool
380 // entry <name_index> using FeedBackVector slot <slot> in sloppy mode.
DoStaGlobalSloppy(compiler::InterpreterAssembler * assembler)381 void Interpreter::DoStaGlobalSloppy(compiler::InterpreterAssembler* assembler) {
382 Callable ic =
383 CodeFactory::StoreICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED);
384 DoStoreGlobal(ic, assembler);
385 }
386
387
388 // StaGlobalStrict <name_index> <slot>
389 //
390 // Store the value in the accumulator into the global with name in constant pool
391 // entry <name_index> using FeedBackVector slot <slot> in strict mode.
DoStaGlobalStrict(compiler::InterpreterAssembler * assembler)392 void Interpreter::DoStaGlobalStrict(compiler::InterpreterAssembler* assembler) {
393 Callable ic =
394 CodeFactory::StoreICInOptimizedCode(isolate_, STRICT, UNINITIALIZED);
395 DoStoreGlobal(ic, assembler);
396 }
397
398
399 // StaGlobalSloppyWide <name_index> <slot>
400 //
401 // Store the value in the accumulator into the global with name in constant pool
402 // entry <name_index> using FeedBackVector slot <slot> in sloppy mode.
DoStaGlobalSloppyWide(compiler::InterpreterAssembler * assembler)403 void Interpreter::DoStaGlobalSloppyWide(
404 compiler::InterpreterAssembler* assembler) {
405 Callable ic =
406 CodeFactory::StoreICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED);
407 DoStoreGlobal(ic, assembler);
408 }
409
410
411 // StaGlobalStrictWide <name_index> <slot>
412 //
413 // Store the value in the accumulator into the global with name in constant pool
414 // entry <name_index> using FeedBackVector slot <slot> in strict mode.
DoStaGlobalStrictWide(compiler::InterpreterAssembler * assembler)415 void Interpreter::DoStaGlobalStrictWide(
416 compiler::InterpreterAssembler* assembler) {
417 Callable ic =
418 CodeFactory::StoreICInOptimizedCode(isolate_, STRICT, UNINITIALIZED);
419 DoStoreGlobal(ic, assembler);
420 }
421
422
423 // LdaContextSlot <context> <slot_index>
424 //
425 // Load the object in |slot_index| of |context| into the accumulator.
DoLdaContextSlot(compiler::InterpreterAssembler * assembler)426 void Interpreter::DoLdaContextSlot(compiler::InterpreterAssembler* assembler) {
427 Node* reg_index = __ BytecodeOperandReg(0);
428 Node* context = __ LoadRegister(reg_index);
429 Node* slot_index = __ BytecodeOperandIdx(1);
430 Node* result = __ LoadContextSlot(context, slot_index);
431 __ SetAccumulator(result);
432 __ Dispatch();
433 }
434
435
436 // LdaContextSlotWide <context> <slot_index>
437 //
438 // Load the object in |slot_index| of |context| into the accumulator.
DoLdaContextSlotWide(compiler::InterpreterAssembler * assembler)439 void Interpreter::DoLdaContextSlotWide(
440 compiler::InterpreterAssembler* assembler) {
441 DoLdaContextSlot(assembler);
442 }
443
444
445 // StaContextSlot <context> <slot_index>
446 //
447 // Stores the object in the accumulator into |slot_index| of |context|.
DoStaContextSlot(compiler::InterpreterAssembler * assembler)448 void Interpreter::DoStaContextSlot(compiler::InterpreterAssembler* assembler) {
449 Node* value = __ GetAccumulator();
450 Node* reg_index = __ BytecodeOperandReg(0);
451 Node* context = __ LoadRegister(reg_index);
452 Node* slot_index = __ BytecodeOperandIdx(1);
453 __ StoreContextSlot(context, slot_index, value);
454 __ Dispatch();
455 }
456
457
458 // StaContextSlot <context> <slot_index>
459 //
460 // Stores the object in the accumulator into |slot_index| of |context|.
DoStaContextSlotWide(compiler::InterpreterAssembler * assembler)461 void Interpreter::DoStaContextSlotWide(
462 compiler::InterpreterAssembler* assembler) {
463 DoStaContextSlot(assembler);
464 }
465
466
DoLoadLookupSlot(Runtime::FunctionId function_id,compiler::InterpreterAssembler * assembler)467 void Interpreter::DoLoadLookupSlot(Runtime::FunctionId function_id,
468 compiler::InterpreterAssembler* assembler) {
469 Node* index = __ BytecodeOperandIdx(0);
470 Node* name = __ LoadConstantPoolEntry(index);
471 Node* context = __ GetContext();
472 Node* result_pair = __ CallRuntime(function_id, context, name);
473 Node* result = __ Projection(0, result_pair);
474 __ SetAccumulator(result);
475 __ Dispatch();
476 }
477
478
479 // LdaLookupSlot <name_index>
480 //
481 // Lookup the object with the name in constant pool entry |name_index|
482 // dynamically.
DoLdaLookupSlot(compiler::InterpreterAssembler * assembler)483 void Interpreter::DoLdaLookupSlot(compiler::InterpreterAssembler* assembler) {
484 DoLoadLookupSlot(Runtime::kLoadLookupSlot, assembler);
485 }
486
487
488 // LdaLookupSlotInsideTypeof <name_index>
489 //
490 // Lookup the object with the name in constant pool entry |name_index|
491 // dynamically without causing a NoReferenceError.
DoLdaLookupSlotInsideTypeof(compiler::InterpreterAssembler * assembler)492 void Interpreter::DoLdaLookupSlotInsideTypeof(
493 compiler::InterpreterAssembler* assembler) {
494 DoLoadLookupSlot(Runtime::kLoadLookupSlotNoReferenceError, assembler);
495 }
496
497
498 // LdaLookupSlotWide <name_index>
499 //
500 // Lookup the object with the name in constant pool entry |name_index|
501 // dynamically.
DoLdaLookupSlotWide(compiler::InterpreterAssembler * assembler)502 void Interpreter::DoLdaLookupSlotWide(
503 compiler::InterpreterAssembler* assembler) {
504 DoLdaLookupSlot(assembler);
505 }
506
507
508 // LdaLookupSlotInsideTypeofWide <name_index>
509 //
510 // Lookup the object with the name in constant pool entry |name_index|
511 // dynamically without causing a NoReferenceError.
DoLdaLookupSlotInsideTypeofWide(compiler::InterpreterAssembler * assembler)512 void Interpreter::DoLdaLookupSlotInsideTypeofWide(
513 compiler::InterpreterAssembler* assembler) {
514 DoLdaLookupSlotInsideTypeof(assembler);
515 }
516
517
DoStoreLookupSlot(LanguageMode language_mode,compiler::InterpreterAssembler * assembler)518 void Interpreter::DoStoreLookupSlot(LanguageMode language_mode,
519 compiler::InterpreterAssembler* assembler) {
520 Node* value = __ GetAccumulator();
521 Node* index = __ BytecodeOperandIdx(0);
522 Node* name = __ LoadConstantPoolEntry(index);
523 Node* context = __ GetContext();
524 Node* language_mode_node = __ NumberConstant(language_mode);
525 Node* result = __ CallRuntime(Runtime::kStoreLookupSlot, value, context, name,
526 language_mode_node);
527 __ SetAccumulator(result);
528 __ Dispatch();
529 }
530
531
532 // StaLookupSlotSloppy <name_index>
533 //
534 // Store the object in accumulator to the object with the name in constant
535 // pool entry |name_index| in sloppy mode.
DoStaLookupSlotSloppy(compiler::InterpreterAssembler * assembler)536 void Interpreter::DoStaLookupSlotSloppy(
537 compiler::InterpreterAssembler* assembler) {
538 DoStoreLookupSlot(LanguageMode::SLOPPY, assembler);
539 }
540
541
542 // StaLookupSlotStrict <name_index>
543 //
544 // Store the object in accumulator to the object with the name in constant
545 // pool entry |name_index| in strict mode.
DoStaLookupSlotStrict(compiler::InterpreterAssembler * assembler)546 void Interpreter::DoStaLookupSlotStrict(
547 compiler::InterpreterAssembler* assembler) {
548 DoStoreLookupSlot(LanguageMode::STRICT, assembler);
549 }
550
551
552 // StaLookupSlotSloppyWide <name_index>
553 //
554 // Store the object in accumulator to the object with the name in constant
555 // pool entry |name_index| in sloppy mode.
DoStaLookupSlotSloppyWide(compiler::InterpreterAssembler * assembler)556 void Interpreter::DoStaLookupSlotSloppyWide(
557 compiler::InterpreterAssembler* assembler) {
558 DoStaLookupSlotSloppy(assembler);
559 }
560
561
562 // StaLookupSlotStrictWide <name_index>
563 //
564 // Store the object in accumulator to the object with the name in constant
565 // pool entry |name_index| in strict mode.
DoStaLookupSlotStrictWide(compiler::InterpreterAssembler * assembler)566 void Interpreter::DoStaLookupSlotStrictWide(
567 compiler::InterpreterAssembler* assembler) {
568 DoStaLookupSlotStrict(assembler);
569 }
570
571
DoLoadIC(Callable ic,compiler::InterpreterAssembler * assembler)572 void Interpreter::DoLoadIC(Callable ic,
573 compiler::InterpreterAssembler* assembler) {
574 Node* code_target = __ HeapConstant(ic.code());
575 Node* register_index = __ BytecodeOperandReg(0);
576 Node* object = __ LoadRegister(register_index);
577 Node* constant_index = __ BytecodeOperandIdx(1);
578 Node* name = __ LoadConstantPoolEntry(constant_index);
579 Node* raw_slot = __ BytecodeOperandIdx(2);
580 Node* smi_slot = __ SmiTag(raw_slot);
581 Node* type_feedback_vector = __ LoadTypeFeedbackVector();
582 Node* result = __ CallIC(ic.descriptor(), code_target, object, name, smi_slot,
583 type_feedback_vector);
584 __ SetAccumulator(result);
585 __ Dispatch();
586 }
587
588
589 // LoadICSloppy <object> <name_index> <slot>
590 //
591 // Calls the sloppy mode LoadIC at FeedBackVector slot <slot> for <object> and
592 // the name at constant pool entry <name_index>.
DoLoadICSloppy(compiler::InterpreterAssembler * assembler)593 void Interpreter::DoLoadICSloppy(compiler::InterpreterAssembler* assembler) {
594 Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF,
595 SLOPPY, UNINITIALIZED);
596 DoLoadIC(ic, assembler);
597 }
598
599
600 // LoadICStrict <object> <name_index> <slot>
601 //
602 // Calls the sloppy mode LoadIC at FeedBackVector slot <slot> for <object> and
603 // the name at constant pool entry <name_index>.
DoLoadICStrict(compiler::InterpreterAssembler * assembler)604 void Interpreter::DoLoadICStrict(compiler::InterpreterAssembler* assembler) {
605 Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF,
606 STRICT, UNINITIALIZED);
607 DoLoadIC(ic, assembler);
608 }
609
610
611 // LoadICSloppyWide <object> <name_index> <slot>
612 //
613 // Calls the sloppy mode LoadIC at FeedBackVector slot <slot> for <object> and
614 // the name at constant pool entry <name_index>.
DoLoadICSloppyWide(compiler::InterpreterAssembler * assembler)615 void Interpreter::DoLoadICSloppyWide(
616 compiler::InterpreterAssembler* assembler) {
617 Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF,
618 SLOPPY, UNINITIALIZED);
619 DoLoadIC(ic, assembler);
620 }
621
622
623 // LoadICStrictWide <object> <name_index> <slot>
624 //
625 // Calls the sloppy mode LoadIC at FeedBackVector slot <slot> for <object> and
626 // the name at constant pool entry <name_index>.
DoLoadICStrictWide(compiler::InterpreterAssembler * assembler)627 void Interpreter::DoLoadICStrictWide(
628 compiler::InterpreterAssembler* assembler) {
629 Callable ic = CodeFactory::LoadICInOptimizedCode(isolate_, NOT_INSIDE_TYPEOF,
630 STRICT, UNINITIALIZED);
631 DoLoadIC(ic, assembler);
632 }
633
634
DoKeyedLoadIC(Callable ic,compiler::InterpreterAssembler * assembler)635 void Interpreter::DoKeyedLoadIC(Callable ic,
636 compiler::InterpreterAssembler* assembler) {
637 Node* code_target = __ HeapConstant(ic.code());
638 Node* reg_index = __ BytecodeOperandReg(0);
639 Node* object = __ LoadRegister(reg_index);
640 Node* name = __ GetAccumulator();
641 Node* raw_slot = __ BytecodeOperandIdx(1);
642 Node* smi_slot = __ SmiTag(raw_slot);
643 Node* type_feedback_vector = __ LoadTypeFeedbackVector();
644 Node* result = __ CallIC(ic.descriptor(), code_target, object, name, smi_slot,
645 type_feedback_vector);
646 __ SetAccumulator(result);
647 __ Dispatch();
648 }
649
650
651 // KeyedLoadICSloppy <object> <slot>
652 //
653 // Calls the sloppy mode KeyedLoadIC at FeedBackVector slot <slot> for <object>
654 // and the key in the accumulator.
DoKeyedLoadICSloppy(compiler::InterpreterAssembler * assembler)655 void Interpreter::DoKeyedLoadICSloppy(
656 compiler::InterpreterAssembler* assembler) {
657 Callable ic =
658 CodeFactory::KeyedLoadICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED);
659 DoKeyedLoadIC(ic, assembler);
660 }
661
662
663 // KeyedLoadICStrict <object> <slot>
664 //
665 // Calls the strict mode KeyedLoadIC at FeedBackVector slot <slot> for <object>
666 // and the key in the accumulator.
DoKeyedLoadICStrict(compiler::InterpreterAssembler * assembler)667 void Interpreter::DoKeyedLoadICStrict(
668 compiler::InterpreterAssembler* assembler) {
669 Callable ic =
670 CodeFactory::KeyedLoadICInOptimizedCode(isolate_, STRICT, UNINITIALIZED);
671 DoKeyedLoadIC(ic, assembler);
672 }
673
674
675 // KeyedLoadICSloppyWide <object> <slot>
676 //
677 // Calls the sloppy mode KeyedLoadIC at FeedBackVector slot <slot> for <object>
678 // and the key in the accumulator.
DoKeyedLoadICSloppyWide(compiler::InterpreterAssembler * assembler)679 void Interpreter::DoKeyedLoadICSloppyWide(
680 compiler::InterpreterAssembler* assembler) {
681 Callable ic =
682 CodeFactory::KeyedLoadICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED);
683 DoKeyedLoadIC(ic, assembler);
684 }
685
686
687 // KeyedLoadICStrictWide <object> <slot>
688 //
689 // Calls the strict mode KeyedLoadIC at FeedBackVector slot <slot> for <object>
690 // and the key in the accumulator.
DoKeyedLoadICStrictWide(compiler::InterpreterAssembler * assembler)691 void Interpreter::DoKeyedLoadICStrictWide(
692 compiler::InterpreterAssembler* assembler) {
693 Callable ic =
694 CodeFactory::KeyedLoadICInOptimizedCode(isolate_, STRICT, UNINITIALIZED);
695 DoKeyedLoadIC(ic, assembler);
696 }
697
698
DoStoreIC(Callable ic,compiler::InterpreterAssembler * assembler)699 void Interpreter::DoStoreIC(Callable ic,
700 compiler::InterpreterAssembler* assembler) {
701 Node* code_target = __ HeapConstant(ic.code());
702 Node* object_reg_index = __ BytecodeOperandReg(0);
703 Node* object = __ LoadRegister(object_reg_index);
704 Node* constant_index = __ BytecodeOperandIdx(1);
705 Node* name = __ LoadConstantPoolEntry(constant_index);
706 Node* value = __ GetAccumulator();
707 Node* raw_slot = __ BytecodeOperandIdx(2);
708 Node* smi_slot = __ SmiTag(raw_slot);
709 Node* type_feedback_vector = __ LoadTypeFeedbackVector();
710 __ CallIC(ic.descriptor(), code_target, object, name, value, smi_slot,
711 type_feedback_vector);
712 __ Dispatch();
713 }
714
715
716 // StoreICSloppy <object> <name_index> <slot>
717 //
718 // Calls the sloppy mode StoreIC at FeedBackVector slot <slot> for <object> and
719 // the name in constant pool entry <name_index> with the value in the
720 // accumulator.
DoStoreICSloppy(compiler::InterpreterAssembler * assembler)721 void Interpreter::DoStoreICSloppy(compiler::InterpreterAssembler* assembler) {
722 Callable ic =
723 CodeFactory::StoreICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED);
724 DoStoreIC(ic, assembler);
725 }
726
727
728 // StoreICStrict <object> <name_index> <slot>
729 //
730 // Calls the strict mode StoreIC at FeedBackVector slot <slot> for <object> and
731 // the name in constant pool entry <name_index> with the value in the
732 // accumulator.
DoStoreICStrict(compiler::InterpreterAssembler * assembler)733 void Interpreter::DoStoreICStrict(compiler::InterpreterAssembler* assembler) {
734 Callable ic =
735 CodeFactory::StoreICInOptimizedCode(isolate_, STRICT, UNINITIALIZED);
736 DoStoreIC(ic, assembler);
737 }
738
739
740 // StoreICSloppyWide <object> <name_index> <slot>
741 //
742 // Calls the sloppy mode StoreIC at FeedBackVector slot <slot> for <object> and
743 // the name in constant pool entry <name_index> with the value in the
744 // accumulator.
DoStoreICSloppyWide(compiler::InterpreterAssembler * assembler)745 void Interpreter::DoStoreICSloppyWide(
746 compiler::InterpreterAssembler* assembler) {
747 Callable ic =
748 CodeFactory::StoreICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED);
749 DoStoreIC(ic, assembler);
750 }
751
752
753 // StoreICStrictWide <object> <name_index> <slot>
754 //
755 // Calls the strict mode StoreIC at FeedBackVector slot <slot> for <object> and
756 // the name in constant pool entry <name_index> with the value in the
757 // accumulator.
DoStoreICStrictWide(compiler::InterpreterAssembler * assembler)758 void Interpreter::DoStoreICStrictWide(
759 compiler::InterpreterAssembler* assembler) {
760 Callable ic =
761 CodeFactory::StoreICInOptimizedCode(isolate_, STRICT, UNINITIALIZED);
762 DoStoreIC(ic, assembler);
763 }
764
765
DoKeyedStoreIC(Callable ic,compiler::InterpreterAssembler * assembler)766 void Interpreter::DoKeyedStoreIC(Callable ic,
767 compiler::InterpreterAssembler* assembler) {
768 Node* code_target = __ HeapConstant(ic.code());
769 Node* object_reg_index = __ BytecodeOperandReg(0);
770 Node* object = __ LoadRegister(object_reg_index);
771 Node* name_reg_index = __ BytecodeOperandReg(1);
772 Node* name = __ LoadRegister(name_reg_index);
773 Node* value = __ GetAccumulator();
774 Node* raw_slot = __ BytecodeOperandIdx(2);
775 Node* smi_slot = __ SmiTag(raw_slot);
776 Node* type_feedback_vector = __ LoadTypeFeedbackVector();
777 __ CallIC(ic.descriptor(), code_target, object, name, value, smi_slot,
778 type_feedback_vector);
779 __ Dispatch();
780 }
781
782
783 // KeyedStoreICSloppy <object> <key> <slot>
784 //
785 // Calls the sloppy mode KeyStoreIC at FeedBackVector slot <slot> for <object>
786 // and the key <key> with the value in the accumulator.
DoKeyedStoreICSloppy(compiler::InterpreterAssembler * assembler)787 void Interpreter::DoKeyedStoreICSloppy(
788 compiler::InterpreterAssembler* assembler) {
789 Callable ic =
790 CodeFactory::KeyedStoreICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED);
791 DoKeyedStoreIC(ic, assembler);
792 }
793
794
795 // KeyedStoreICStore <object> <key> <slot>
796 //
797 // Calls the strict mode KeyStoreIC at FeedBackVector slot <slot> for <object>
798 // and the key <key> with the value in the accumulator.
DoKeyedStoreICStrict(compiler::InterpreterAssembler * assembler)799 void Interpreter::DoKeyedStoreICStrict(
800 compiler::InterpreterAssembler* assembler) {
801 Callable ic =
802 CodeFactory::KeyedStoreICInOptimizedCode(isolate_, STRICT, UNINITIALIZED);
803 DoKeyedStoreIC(ic, assembler);
804 }
805
806
807 // KeyedStoreICSloppyWide <object> <key> <slot>
808 //
809 // Calls the sloppy mode KeyStoreIC at FeedBackVector slot <slot> for <object>
810 // and the key <key> with the value in the accumulator.
DoKeyedStoreICSloppyWide(compiler::InterpreterAssembler * assembler)811 void Interpreter::DoKeyedStoreICSloppyWide(
812 compiler::InterpreterAssembler* assembler) {
813 Callable ic =
814 CodeFactory::KeyedStoreICInOptimizedCode(isolate_, SLOPPY, UNINITIALIZED);
815 DoKeyedStoreIC(ic, assembler);
816 }
817
818
819 // KeyedStoreICStoreWide <object> <key> <slot>
820 //
821 // Calls the strict mode KeyStoreIC at FeedBackVector slot <slot> for <object>
822 // and the key <key> with the value in the accumulator.
DoKeyedStoreICStrictWide(compiler::InterpreterAssembler * assembler)823 void Interpreter::DoKeyedStoreICStrictWide(
824 compiler::InterpreterAssembler* assembler) {
825 Callable ic =
826 CodeFactory::KeyedStoreICInOptimizedCode(isolate_, STRICT, UNINITIALIZED);
827 DoKeyedStoreIC(ic, assembler);
828 }
829
830
831 // PushContext <context>
832 //
833 // Pushes the accumulator as the current context, and saves it in <context>
DoPushContext(compiler::InterpreterAssembler * assembler)834 void Interpreter::DoPushContext(compiler::InterpreterAssembler* assembler) {
835 Node* reg_index = __ BytecodeOperandReg(0);
836 Node* context = __ GetAccumulator();
837 __ SetContext(context);
838 __ StoreRegister(context, reg_index);
839 __ Dispatch();
840 }
841
842
843 // PopContext <context>
844 //
845 // Pops the current context and sets <context> as the new context.
DoPopContext(compiler::InterpreterAssembler * assembler)846 void Interpreter::DoPopContext(compiler::InterpreterAssembler* assembler) {
847 Node* reg_index = __ BytecodeOperandReg(0);
848 Node* context = __ LoadRegister(reg_index);
849 __ SetContext(context);
850 __ Dispatch();
851 }
852
853
DoBinaryOp(Runtime::FunctionId function_id,compiler::InterpreterAssembler * assembler)854 void Interpreter::DoBinaryOp(Runtime::FunctionId function_id,
855 compiler::InterpreterAssembler* assembler) {
856 // TODO(rmcilroy): Call ICs which back-patch bytecode with type specialized
857 // operations, instead of calling builtins directly.
858 Node* reg_index = __ BytecodeOperandReg(0);
859 Node* lhs = __ LoadRegister(reg_index);
860 Node* rhs = __ GetAccumulator();
861 Node* result = __ CallRuntime(function_id, lhs, rhs);
862 __ SetAccumulator(result);
863 __ Dispatch();
864 }
865
866
867 // Add <src>
868 //
869 // Add register <src> to accumulator.
DoAdd(compiler::InterpreterAssembler * assembler)870 void Interpreter::DoAdd(compiler::InterpreterAssembler* assembler) {
871 DoBinaryOp(Runtime::kAdd, assembler);
872 }
873
874
875 // Sub <src>
876 //
877 // Subtract register <src> from accumulator.
DoSub(compiler::InterpreterAssembler * assembler)878 void Interpreter::DoSub(compiler::InterpreterAssembler* assembler) {
879 DoBinaryOp(Runtime::kSubtract, assembler);
880 }
881
882
883 // Mul <src>
884 //
885 // Multiply accumulator by register <src>.
DoMul(compiler::InterpreterAssembler * assembler)886 void Interpreter::DoMul(compiler::InterpreterAssembler* assembler) {
887 DoBinaryOp(Runtime::kMultiply, assembler);
888 }
889
890
891 // Div <src>
892 //
893 // Divide register <src> by accumulator.
DoDiv(compiler::InterpreterAssembler * assembler)894 void Interpreter::DoDiv(compiler::InterpreterAssembler* assembler) {
895 DoBinaryOp(Runtime::kDivide, assembler);
896 }
897
898
899 // Mod <src>
900 //
901 // Modulo register <src> by accumulator.
DoMod(compiler::InterpreterAssembler * assembler)902 void Interpreter::DoMod(compiler::InterpreterAssembler* assembler) {
903 DoBinaryOp(Runtime::kModulus, assembler);
904 }
905
906
907 // BitwiseOr <src>
908 //
909 // BitwiseOr register <src> to accumulator.
DoBitwiseOr(compiler::InterpreterAssembler * assembler)910 void Interpreter::DoBitwiseOr(compiler::InterpreterAssembler* assembler) {
911 DoBinaryOp(Runtime::kBitwiseOr, assembler);
912 }
913
914
915 // BitwiseXor <src>
916 //
917 // BitwiseXor register <src> to accumulator.
DoBitwiseXor(compiler::InterpreterAssembler * assembler)918 void Interpreter::DoBitwiseXor(compiler::InterpreterAssembler* assembler) {
919 DoBinaryOp(Runtime::kBitwiseXor, assembler);
920 }
921
922
923 // BitwiseAnd <src>
924 //
925 // BitwiseAnd register <src> to accumulator.
DoBitwiseAnd(compiler::InterpreterAssembler * assembler)926 void Interpreter::DoBitwiseAnd(compiler::InterpreterAssembler* assembler) {
927 DoBinaryOp(Runtime::kBitwiseAnd, assembler);
928 }
929
930
931 // ShiftLeft <src>
932 //
933 // Left shifts register <src> by the count specified in the accumulator.
934 // Register <src> is converted to an int32 and the accumulator to uint32
935 // before the operation. 5 lsb bits from the accumulator are used as count
936 // i.e. <src> << (accumulator & 0x1F).
DoShiftLeft(compiler::InterpreterAssembler * assembler)937 void Interpreter::DoShiftLeft(compiler::InterpreterAssembler* assembler) {
938 DoBinaryOp(Runtime::kShiftLeft, assembler);
939 }
940
941
942 // ShiftRight <src>
943 //
944 // Right shifts register <src> by the count specified in the accumulator.
945 // Result is sign extended. Register <src> is converted to an int32 and the
946 // accumulator to uint32 before the operation. 5 lsb bits from the accumulator
947 // are used as count i.e. <src> >> (accumulator & 0x1F).
DoShiftRight(compiler::InterpreterAssembler * assembler)948 void Interpreter::DoShiftRight(compiler::InterpreterAssembler* assembler) {
949 DoBinaryOp(Runtime::kShiftRight, assembler);
950 }
951
952
953 // ShiftRightLogical <src>
954 //
955 // Right Shifts register <src> by the count specified in the accumulator.
956 // Result is zero-filled. The accumulator and register <src> are converted to
957 // uint32 before the operation 5 lsb bits from the accumulator are used as
958 // count i.e. <src> << (accumulator & 0x1F).
DoShiftRightLogical(compiler::InterpreterAssembler * assembler)959 void Interpreter::DoShiftRightLogical(
960 compiler::InterpreterAssembler* assembler) {
961 DoBinaryOp(Runtime::kShiftRightLogical, assembler);
962 }
963
964
DoCountOp(Runtime::FunctionId function_id,compiler::InterpreterAssembler * assembler)965 void Interpreter::DoCountOp(Runtime::FunctionId function_id,
966 compiler::InterpreterAssembler* assembler) {
967 Node* value = __ GetAccumulator();
968 Node* one = __ NumberConstant(1);
969 Node* result = __ CallRuntime(function_id, value, one);
970 __ SetAccumulator(result);
971 __ Dispatch();
972 }
973
974
975 // Inc
976 //
977 // Increments value in the accumulator by one.
DoInc(compiler::InterpreterAssembler * assembler)978 void Interpreter::DoInc(compiler::InterpreterAssembler* assembler) {
979 DoCountOp(Runtime::kAdd, assembler);
980 }
981
982
983 // Dec
984 //
985 // Decrements value in the accumulator by one.
DoDec(compiler::InterpreterAssembler * assembler)986 void Interpreter::DoDec(compiler::InterpreterAssembler* assembler) {
987 DoCountOp(Runtime::kSubtract, assembler);
988 }
989
990
991 // LogicalNot
992 //
993 // Perform logical-not on the accumulator, first casting the
994 // accumulator to a boolean value if required.
DoLogicalNot(compiler::InterpreterAssembler * assembler)995 void Interpreter::DoLogicalNot(compiler::InterpreterAssembler* assembler) {
996 Node* accumulator = __ GetAccumulator();
997 Node* result = __ CallRuntime(Runtime::kInterpreterLogicalNot, accumulator);
998 __ SetAccumulator(result);
999 __ Dispatch();
1000 }
1001
1002
1003 // TypeOf
1004 //
1005 // Load the accumulator with the string representating type of the
1006 // object in the accumulator.
DoTypeOf(compiler::InterpreterAssembler * assembler)1007 void Interpreter::DoTypeOf(compiler::InterpreterAssembler* assembler) {
1008 Node* accumulator = __ GetAccumulator();
1009 Node* result = __ CallRuntime(Runtime::kInterpreterTypeOf, accumulator);
1010 __ SetAccumulator(result);
1011 __ Dispatch();
1012 }
1013
1014
DoDelete(Runtime::FunctionId function_id,compiler::InterpreterAssembler * assembler)1015 void Interpreter::DoDelete(Runtime::FunctionId function_id,
1016 compiler::InterpreterAssembler* assembler) {
1017 Node* reg_index = __ BytecodeOperandReg(0);
1018 Node* object = __ LoadRegister(reg_index);
1019 Node* key = __ GetAccumulator();
1020 Node* result = __ CallRuntime(function_id, object, key);
1021 __ SetAccumulator(result);
1022 __ Dispatch();
1023 }
1024
1025
1026 // DeletePropertyStrict
1027 //
1028 // Delete the property specified in the accumulator from the object
1029 // referenced by the register operand following strict mode semantics.
DoDeletePropertyStrict(compiler::InterpreterAssembler * assembler)1030 void Interpreter::DoDeletePropertyStrict(
1031 compiler::InterpreterAssembler* assembler) {
1032 DoDelete(Runtime::kDeleteProperty_Strict, assembler);
1033 }
1034
1035
1036 // DeletePropertySloppy
1037 //
1038 // Delete the property specified in the accumulator from the object
1039 // referenced by the register operand following sloppy mode semantics.
DoDeletePropertySloppy(compiler::InterpreterAssembler * assembler)1040 void Interpreter::DoDeletePropertySloppy(
1041 compiler::InterpreterAssembler* assembler) {
1042 DoDelete(Runtime::kDeleteProperty_Sloppy, assembler);
1043 }
1044
1045
1046 // DeleteLookupSlot
1047 //
1048 // Delete the variable with the name specified in the accumulator by dynamically
1049 // looking it up.
DoDeleteLookupSlot(compiler::InterpreterAssembler * assembler)1050 void Interpreter::DoDeleteLookupSlot(
1051 compiler::InterpreterAssembler* assembler) {
1052 Node* name = __ GetAccumulator();
1053 Node* context = __ GetContext();
1054 Node* result = __ CallRuntime(Runtime::kDeleteLookupSlot, context, name);
1055 __ SetAccumulator(result);
1056 __ Dispatch();
1057 }
1058
1059
DoJSCall(compiler::InterpreterAssembler * assembler)1060 void Interpreter::DoJSCall(compiler::InterpreterAssembler* assembler) {
1061 Node* function_reg = __ BytecodeOperandReg(0);
1062 Node* function = __ LoadRegister(function_reg);
1063 Node* receiver_reg = __ BytecodeOperandReg(1);
1064 Node* first_arg = __ RegisterLocation(receiver_reg);
1065 Node* args_count = __ BytecodeOperandCount(2);
1066 // TODO(rmcilroy): Use the call type feedback slot to call via CallIC.
1067 Node* result = __ CallJS(function, first_arg, args_count);
1068 __ SetAccumulator(result);
1069 __ Dispatch();
1070 }
1071
1072
1073 // Call <callable> <receiver> <arg_count>
1074 //
1075 // Call a JSfunction or Callable in |callable| with the |receiver| and
1076 // |arg_count| arguments in subsequent registers.
DoCall(compiler::InterpreterAssembler * assembler)1077 void Interpreter::DoCall(compiler::InterpreterAssembler* assembler) {
1078 DoJSCall(assembler);
1079 }
1080
1081
1082 // CallWide <callable> <receiver> <arg_count>
1083 //
1084 // Call a JSfunction or Callable in |callable| with the |receiver| and
1085 // |arg_count| arguments in subsequent registers.
DoCallWide(compiler::InterpreterAssembler * assembler)1086 void Interpreter::DoCallWide(compiler::InterpreterAssembler* assembler) {
1087 DoJSCall(assembler);
1088 }
1089
1090
1091 // CallRuntime <function_id> <first_arg> <arg_count>
1092 //
1093 // Call the runtime function |function_id| with the first argument in
1094 // register |first_arg| and |arg_count| arguments in subsequent
1095 // registers.
DoCallRuntime(compiler::InterpreterAssembler * assembler)1096 void Interpreter::DoCallRuntime(compiler::InterpreterAssembler* assembler) {
1097 Node* function_id = __ BytecodeOperandIdx(0);
1098 Node* first_arg_reg = __ BytecodeOperandReg(1);
1099 Node* first_arg = __ RegisterLocation(first_arg_reg);
1100 Node* args_count = __ BytecodeOperandCount(2);
1101 Node* result = __ CallRuntime(function_id, first_arg, args_count);
1102 __ SetAccumulator(result);
1103 __ Dispatch();
1104 }
1105
1106
1107 // CallRuntimeForPair <function_id> <first_arg> <arg_count> <first_return>
1108 //
1109 // Call the runtime function |function_id| which returns a pair, with the
1110 // first argument in register |first_arg| and |arg_count| arguments in
1111 // subsequent registers. Returns the result in <first_return> and
1112 // <first_return + 1>
DoCallRuntimeForPair(compiler::InterpreterAssembler * assembler)1113 void Interpreter::DoCallRuntimeForPair(
1114 compiler::InterpreterAssembler* assembler) {
1115 // Call the runtime function.
1116 Node* function_id = __ BytecodeOperandIdx(0);
1117 Node* first_arg_reg = __ BytecodeOperandReg(1);
1118 Node* first_arg = __ RegisterLocation(first_arg_reg);
1119 Node* args_count = __ BytecodeOperandCount(2);
1120 Node* result_pair = __ CallRuntime(function_id, first_arg, args_count, 2);
1121
1122 // Store the results in <first_return> and <first_return + 1>
1123 Node* first_return_reg = __ BytecodeOperandReg(3);
1124 Node* second_return_reg = __ NextRegister(first_return_reg);
1125 Node* result0 = __ Projection(0, result_pair);
1126 Node* result1 = __ Projection(1, result_pair);
1127 __ StoreRegister(result0, first_return_reg);
1128 __ StoreRegister(result1, second_return_reg);
1129
1130 __ Dispatch();
1131 }
1132
1133
1134 // CallJSRuntime <context_index> <receiver> <arg_count>
1135 //
1136 // Call the JS runtime function that has the |context_index| with the receiver
1137 // in register |receiver| and |arg_count| arguments in subsequent registers.
DoCallJSRuntime(compiler::InterpreterAssembler * assembler)1138 void Interpreter::DoCallJSRuntime(compiler::InterpreterAssembler* assembler) {
1139 Node* context_index = __ BytecodeOperandIdx(0);
1140 Node* receiver_reg = __ BytecodeOperandReg(1);
1141 Node* first_arg = __ RegisterLocation(receiver_reg);
1142 Node* args_count = __ BytecodeOperandCount(2);
1143
1144 // Get the function to call from the native context.
1145 Node* context = __ GetContext();
1146 Node* native_context =
1147 __ LoadContextSlot(context, Context::NATIVE_CONTEXT_INDEX);
1148 Node* function = __ LoadContextSlot(native_context, context_index);
1149
1150 // Call the function.
1151 Node* result = __ CallJS(function, first_arg, args_count);
1152 __ SetAccumulator(result);
1153 __ Dispatch();
1154 }
1155
1156
1157 // New <constructor> <first_arg> <arg_count>
1158 //
1159 // Call operator new with |constructor| and the first argument in
1160 // register |first_arg| and |arg_count| arguments in subsequent
1161 //
DoNew(compiler::InterpreterAssembler * assembler)1162 void Interpreter::DoNew(compiler::InterpreterAssembler* assembler) {
1163 Callable ic = CodeFactory::InterpreterPushArgsAndConstruct(isolate_);
1164 Node* constructor_reg = __ BytecodeOperandReg(0);
1165 Node* constructor = __ LoadRegister(constructor_reg);
1166 Node* first_arg_reg = __ BytecodeOperandReg(1);
1167 Node* first_arg = __ RegisterLocation(first_arg_reg);
1168 Node* args_count = __ BytecodeOperandCount(2);
1169 Node* result =
1170 __ CallConstruct(constructor, constructor, first_arg, args_count);
1171 __ SetAccumulator(result);
1172 __ Dispatch();
1173 }
1174
1175
1176 // TestEqual <src>
1177 //
1178 // Test if the value in the <src> register equals the accumulator.
DoTestEqual(compiler::InterpreterAssembler * assembler)1179 void Interpreter::DoTestEqual(compiler::InterpreterAssembler* assembler) {
1180 DoBinaryOp(Runtime::kInterpreterEquals, assembler);
1181 }
1182
1183
1184 // TestNotEqual <src>
1185 //
1186 // Test if the value in the <src> register is not equal to the accumulator.
DoTestNotEqual(compiler::InterpreterAssembler * assembler)1187 void Interpreter::DoTestNotEqual(compiler::InterpreterAssembler* assembler) {
1188 DoBinaryOp(Runtime::kInterpreterNotEquals, assembler);
1189 }
1190
1191
1192 // TestEqualStrict <src>
1193 //
1194 // Test if the value in the <src> register is strictly equal to the accumulator.
DoTestEqualStrict(compiler::InterpreterAssembler * assembler)1195 void Interpreter::DoTestEqualStrict(compiler::InterpreterAssembler* assembler) {
1196 DoBinaryOp(Runtime::kInterpreterStrictEquals, assembler);
1197 }
1198
1199
1200 // TestNotEqualStrict <src>
1201 //
1202 // Test if the value in the <src> register is not strictly equal to the
1203 // accumulator.
DoTestNotEqualStrict(compiler::InterpreterAssembler * assembler)1204 void Interpreter::DoTestNotEqualStrict(
1205 compiler::InterpreterAssembler* assembler) {
1206 DoBinaryOp(Runtime::kInterpreterStrictNotEquals, assembler);
1207 }
1208
1209
1210 // TestLessThan <src>
1211 //
1212 // Test if the value in the <src> register is less than the accumulator.
DoTestLessThan(compiler::InterpreterAssembler * assembler)1213 void Interpreter::DoTestLessThan(compiler::InterpreterAssembler* assembler) {
1214 DoBinaryOp(Runtime::kInterpreterLessThan, assembler);
1215 }
1216
1217
1218 // TestGreaterThan <src>
1219 //
1220 // Test if the value in the <src> register is greater than the accumulator.
DoTestGreaterThan(compiler::InterpreterAssembler * assembler)1221 void Interpreter::DoTestGreaterThan(compiler::InterpreterAssembler* assembler) {
1222 DoBinaryOp(Runtime::kInterpreterGreaterThan, assembler);
1223 }
1224
1225
1226 // TestLessThanOrEqual <src>
1227 //
1228 // Test if the value in the <src> register is less than or equal to the
1229 // accumulator.
DoTestLessThanOrEqual(compiler::InterpreterAssembler * assembler)1230 void Interpreter::DoTestLessThanOrEqual(
1231 compiler::InterpreterAssembler* assembler) {
1232 DoBinaryOp(Runtime::kInterpreterLessThanOrEqual, assembler);
1233 }
1234
1235
1236 // TestGreaterThanOrEqual <src>
1237 //
1238 // Test if the value in the <src> register is greater than or equal to the
1239 // accumulator.
DoTestGreaterThanOrEqual(compiler::InterpreterAssembler * assembler)1240 void Interpreter::DoTestGreaterThanOrEqual(
1241 compiler::InterpreterAssembler* assembler) {
1242 DoBinaryOp(Runtime::kInterpreterGreaterThanOrEqual, assembler);
1243 }
1244
1245
1246 // TestIn <src>
1247 //
1248 // Test if the object referenced by the register operand is a property of the
1249 // object referenced by the accumulator.
DoTestIn(compiler::InterpreterAssembler * assembler)1250 void Interpreter::DoTestIn(compiler::InterpreterAssembler* assembler) {
1251 DoBinaryOp(Runtime::kHasProperty, assembler);
1252 }
1253
1254
1255 // TestInstanceOf <src>
1256 //
1257 // Test if the object referenced by the <src> register is an an instance of type
1258 // referenced by the accumulator.
DoTestInstanceOf(compiler::InterpreterAssembler * assembler)1259 void Interpreter::DoTestInstanceOf(compiler::InterpreterAssembler* assembler) {
1260 DoBinaryOp(Runtime::kInstanceOf, assembler);
1261 }
1262
1263
1264 // ToName
1265 //
1266 // Cast the object referenced by the accumulator to a name.
DoToName(compiler::InterpreterAssembler * assembler)1267 void Interpreter::DoToName(compiler::InterpreterAssembler* assembler) {
1268 Node* accumulator = __ GetAccumulator();
1269 Node* result = __ CallRuntime(Runtime::kToName, accumulator);
1270 __ SetAccumulator(result);
1271 __ Dispatch();
1272 }
1273
1274
1275 // ToNumber
1276 //
1277 // Cast the object referenced by the accumulator to a number.
DoToNumber(compiler::InterpreterAssembler * assembler)1278 void Interpreter::DoToNumber(compiler::InterpreterAssembler* assembler) {
1279 Node* accumulator = __ GetAccumulator();
1280 Node* result = __ CallRuntime(Runtime::kToNumber, accumulator);
1281 __ SetAccumulator(result);
1282 __ Dispatch();
1283 }
1284
1285
1286 // ToObject
1287 //
1288 // Cast the object referenced by the accumulator to a JSObject.
DoToObject(compiler::InterpreterAssembler * assembler)1289 void Interpreter::DoToObject(compiler::InterpreterAssembler* assembler) {
1290 Node* accumulator = __ GetAccumulator();
1291 Node* result = __ CallRuntime(Runtime::kToObject, accumulator);
1292 __ SetAccumulator(result);
1293 __ Dispatch();
1294 }
1295
1296
1297 // Jump <imm8>
1298 //
1299 // Jump by number of bytes represented by the immediate operand |imm8|.
DoJump(compiler::InterpreterAssembler * assembler)1300 void Interpreter::DoJump(compiler::InterpreterAssembler* assembler) {
1301 Node* relative_jump = __ BytecodeOperandImm(0);
1302 __ Jump(relative_jump);
1303 }
1304
1305
1306 // JumpConstant <idx8>
1307 //
1308 // Jump by number of bytes in the Smi in the |idx8| entry in the constant pool.
DoJumpConstant(compiler::InterpreterAssembler * assembler)1309 void Interpreter::DoJumpConstant(compiler::InterpreterAssembler* assembler) {
1310 Node* index = __ BytecodeOperandIdx(0);
1311 Node* constant = __ LoadConstantPoolEntry(index);
1312 Node* relative_jump = __ SmiUntag(constant);
1313 __ Jump(relative_jump);
1314 }
1315
1316
1317 // JumpConstantWide <idx16>
1318 //
1319 // Jump by number of bytes in the Smi in the |idx16| entry in the
1320 // constant pool.
DoJumpConstantWide(compiler::InterpreterAssembler * assembler)1321 void Interpreter::DoJumpConstantWide(
1322 compiler::InterpreterAssembler* assembler) {
1323 DoJumpConstant(assembler);
1324 }
1325
1326
1327 // JumpIfTrue <imm8>
1328 //
1329 // Jump by number of bytes represented by an immediate operand if the
1330 // accumulator contains true.
DoJumpIfTrue(compiler::InterpreterAssembler * assembler)1331 void Interpreter::DoJumpIfTrue(compiler::InterpreterAssembler* assembler) {
1332 Node* accumulator = __ GetAccumulator();
1333 Node* relative_jump = __ BytecodeOperandImm(0);
1334 Node* true_value = __ BooleanConstant(true);
1335 __ JumpIfWordEqual(accumulator, true_value, relative_jump);
1336 }
1337
1338
1339 // JumpIfTrueConstant <idx8>
1340 //
1341 // Jump by number of bytes in the Smi in the |idx8| entry in the constant pool
1342 // if the accumulator contains true.
DoJumpIfTrueConstant(compiler::InterpreterAssembler * assembler)1343 void Interpreter::DoJumpIfTrueConstant(
1344 compiler::InterpreterAssembler* assembler) {
1345 Node* accumulator = __ GetAccumulator();
1346 Node* index = __ BytecodeOperandIdx(0);
1347 Node* constant = __ LoadConstantPoolEntry(index);
1348 Node* relative_jump = __ SmiUntag(constant);
1349 Node* true_value = __ BooleanConstant(true);
1350 __ JumpIfWordEqual(accumulator, true_value, relative_jump);
1351 }
1352
1353
1354 // JumpIfTrueConstantWide <idx16>
1355 //
1356 // Jump by number of bytes in the Smi in the |idx16| entry in the constant pool
1357 // if the accumulator contains true.
DoJumpIfTrueConstantWide(compiler::InterpreterAssembler * assembler)1358 void Interpreter::DoJumpIfTrueConstantWide(
1359 compiler::InterpreterAssembler* assembler) {
1360 DoJumpIfTrueConstant(assembler);
1361 }
1362
1363
1364 // JumpIfFalse <imm8>
1365 //
1366 // Jump by number of bytes represented by an immediate operand if the
1367 // accumulator contains false.
DoJumpIfFalse(compiler::InterpreterAssembler * assembler)1368 void Interpreter::DoJumpIfFalse(compiler::InterpreterAssembler* assembler) {
1369 Node* accumulator = __ GetAccumulator();
1370 Node* relative_jump = __ BytecodeOperandImm(0);
1371 Node* false_value = __ BooleanConstant(false);
1372 __ JumpIfWordEqual(accumulator, false_value, relative_jump);
1373 }
1374
1375
1376 // JumpIfFalseConstant <idx8>
1377 //
1378 // Jump by number of bytes in the Smi in the |idx8| entry in the constant pool
1379 // if the accumulator contains false.
DoJumpIfFalseConstant(compiler::InterpreterAssembler * assembler)1380 void Interpreter::DoJumpIfFalseConstant(
1381 compiler::InterpreterAssembler* assembler) {
1382 Node* accumulator = __ GetAccumulator();
1383 Node* index = __ BytecodeOperandIdx(0);
1384 Node* constant = __ LoadConstantPoolEntry(index);
1385 Node* relative_jump = __ SmiUntag(constant);
1386 Node* false_value = __ BooleanConstant(false);
1387 __ JumpIfWordEqual(accumulator, false_value, relative_jump);
1388 }
1389
1390
1391 // JumpIfFalseConstant <idx16>
1392 //
1393 // Jump by number of bytes in the Smi in the |idx16| entry in the constant pool
1394 // if the accumulator contains false.
DoJumpIfFalseConstantWide(compiler::InterpreterAssembler * assembler)1395 void Interpreter::DoJumpIfFalseConstantWide(
1396 compiler::InterpreterAssembler* assembler) {
1397 DoJumpIfFalseConstant(assembler);
1398 }
1399
1400
1401 // JumpIfToBooleanTrue <imm8>
1402 //
1403 // Jump by number of bytes represented by an immediate operand if the object
1404 // referenced by the accumulator is true when the object is cast to boolean.
DoJumpIfToBooleanTrue(compiler::InterpreterAssembler * assembler)1405 void Interpreter::DoJumpIfToBooleanTrue(
1406 compiler::InterpreterAssembler* assembler) {
1407 Node* accumulator = __ GetAccumulator();
1408 Node* to_boolean_value =
1409 __ CallRuntime(Runtime::kInterpreterToBoolean, accumulator);
1410 Node* relative_jump = __ BytecodeOperandImm(0);
1411 Node* true_value = __ BooleanConstant(true);
1412 __ JumpIfWordEqual(to_boolean_value, true_value, relative_jump);
1413 }
1414
1415
1416 // JumpIfToBooleanTrueConstant <idx8>
1417 //
1418 // Jump by number of bytes in the Smi in the |idx8| entry in the constant pool
1419 // if the object referenced by the accumulator is true when the object is cast
1420 // to boolean.
DoJumpIfToBooleanTrueConstant(compiler::InterpreterAssembler * assembler)1421 void Interpreter::DoJumpIfToBooleanTrueConstant(
1422 compiler::InterpreterAssembler* assembler) {
1423 Node* accumulator = __ GetAccumulator();
1424 Node* to_boolean_value =
1425 __ CallRuntime(Runtime::kInterpreterToBoolean, accumulator);
1426 Node* index = __ BytecodeOperandIdx(0);
1427 Node* constant = __ LoadConstantPoolEntry(index);
1428 Node* relative_jump = __ SmiUntag(constant);
1429 Node* true_value = __ BooleanConstant(true);
1430 __ JumpIfWordEqual(to_boolean_value, true_value, relative_jump);
1431 }
1432
1433
1434 // JumpIfToBooleanTrueConstantWide <idx16>
1435 //
1436 // Jump by number of bytes in the Smi in the |idx16| entry in the constant pool
1437 // if the object referenced by the accumulator is true when the object is cast
1438 // to boolean.
DoJumpIfToBooleanTrueConstantWide(compiler::InterpreterAssembler * assembler)1439 void Interpreter::DoJumpIfToBooleanTrueConstantWide(
1440 compiler::InterpreterAssembler* assembler) {
1441 DoJumpIfToBooleanTrueConstant(assembler);
1442 }
1443
1444
1445 // JumpIfToBooleanFalse <imm8>
1446 //
1447 // Jump by number of bytes represented by an immediate operand if the object
1448 // referenced by the accumulator is false when the object is cast to boolean.
DoJumpIfToBooleanFalse(compiler::InterpreterAssembler * assembler)1449 void Interpreter::DoJumpIfToBooleanFalse(
1450 compiler::InterpreterAssembler* assembler) {
1451 Node* accumulator = __ GetAccumulator();
1452 Node* to_boolean_value =
1453 __ CallRuntime(Runtime::kInterpreterToBoolean, accumulator);
1454 Node* relative_jump = __ BytecodeOperandImm(0);
1455 Node* false_value = __ BooleanConstant(false);
1456 __ JumpIfWordEqual(to_boolean_value, false_value, relative_jump);
1457 }
1458
1459
1460 // JumpIfToBooleanFalseConstant <idx8>
1461 //
1462 // Jump by number of bytes in the Smi in the |idx8| entry in the constant pool
1463 // if the object referenced by the accumulator is false when the object is cast
1464 // to boolean.
DoJumpIfToBooleanFalseConstant(compiler::InterpreterAssembler * assembler)1465 void Interpreter::DoJumpIfToBooleanFalseConstant(
1466 compiler::InterpreterAssembler* assembler) {
1467 Node* accumulator = __ GetAccumulator();
1468 Node* to_boolean_value =
1469 __ CallRuntime(Runtime::kInterpreterToBoolean, accumulator);
1470 Node* index = __ BytecodeOperandIdx(0);
1471 Node* constant = __ LoadConstantPoolEntry(index);
1472 Node* relative_jump = __ SmiUntag(constant);
1473 Node* false_value = __ BooleanConstant(false);
1474 __ JumpIfWordEqual(to_boolean_value, false_value, relative_jump);
1475 }
1476
1477
1478 // JumpIfToBooleanFalseConstantWide <idx16>
1479 //
1480 // Jump by number of bytes in the Smi in the |idx16| entry in the constant pool
1481 // if the object referenced by the accumulator is false when the object is cast
1482 // to boolean.
DoJumpIfToBooleanFalseConstantWide(compiler::InterpreterAssembler * assembler)1483 void Interpreter::DoJumpIfToBooleanFalseConstantWide(
1484 compiler::InterpreterAssembler* assembler) {
1485 DoJumpIfToBooleanFalseConstant(assembler);
1486 }
1487
1488
1489 // JumpIfNull <imm8>
1490 //
1491 // Jump by number of bytes represented by an immediate operand if the object
1492 // referenced by the accumulator is the null constant.
DoJumpIfNull(compiler::InterpreterAssembler * assembler)1493 void Interpreter::DoJumpIfNull(compiler::InterpreterAssembler* assembler) {
1494 Node* accumulator = __ GetAccumulator();
1495 Node* null_value = __ HeapConstant(isolate_->factory()->null_value());
1496 Node* relative_jump = __ BytecodeOperandImm(0);
1497 __ JumpIfWordEqual(accumulator, null_value, relative_jump);
1498 }
1499
1500
1501 // JumpIfNullConstant <idx8>
1502 //
1503 // Jump by number of bytes in the Smi in the |idx8| entry in the constant pool
1504 // if the object referenced by the accumulator is the null constant.
DoJumpIfNullConstant(compiler::InterpreterAssembler * assembler)1505 void Interpreter::DoJumpIfNullConstant(
1506 compiler::InterpreterAssembler* assembler) {
1507 Node* accumulator = __ GetAccumulator();
1508 Node* null_value = __ HeapConstant(isolate_->factory()->null_value());
1509 Node* index = __ BytecodeOperandIdx(0);
1510 Node* constant = __ LoadConstantPoolEntry(index);
1511 Node* relative_jump = __ SmiUntag(constant);
1512 __ JumpIfWordEqual(accumulator, null_value, relative_jump);
1513 }
1514
1515
1516 // JumpIfNullConstantWide <idx16>
1517 //
1518 // Jump by number of bytes in the Smi in the |idx16| entry in the constant pool
1519 // if the object referenced by the accumulator is the null constant.
DoJumpIfNullConstantWide(compiler::InterpreterAssembler * assembler)1520 void Interpreter::DoJumpIfNullConstantWide(
1521 compiler::InterpreterAssembler* assembler) {
1522 DoJumpIfNullConstant(assembler);
1523 }
1524
1525
1526 // jumpifundefined <imm8>
1527 //
1528 // Jump by number of bytes represented by an immediate operand if the object
1529 // referenced by the accumulator is the undefined constant.
DoJumpIfUndefined(compiler::InterpreterAssembler * assembler)1530 void Interpreter::DoJumpIfUndefined(compiler::InterpreterAssembler* assembler) {
1531 Node* accumulator = __ GetAccumulator();
1532 Node* undefined_value =
1533 __ HeapConstant(isolate_->factory()->undefined_value());
1534 Node* relative_jump = __ BytecodeOperandImm(0);
1535 __ JumpIfWordEqual(accumulator, undefined_value, relative_jump);
1536 }
1537
1538
1539 // JumpIfUndefinedConstant <idx8>
1540 //
1541 // Jump by number of bytes in the Smi in the |idx8| entry in the constant pool
1542 // if the object referenced by the accumulator is the undefined constant.
DoJumpIfUndefinedConstant(compiler::InterpreterAssembler * assembler)1543 void Interpreter::DoJumpIfUndefinedConstant(
1544 compiler::InterpreterAssembler* assembler) {
1545 Node* accumulator = __ GetAccumulator();
1546 Node* undefined_value =
1547 __ HeapConstant(isolate_->factory()->undefined_value());
1548 Node* index = __ BytecodeOperandIdx(0);
1549 Node* constant = __ LoadConstantPoolEntry(index);
1550 Node* relative_jump = __ SmiUntag(constant);
1551 __ JumpIfWordEqual(accumulator, undefined_value, relative_jump);
1552 }
1553
1554
1555 // JumpIfUndefinedConstantWide <idx16>
1556 //
1557 // Jump by number of bytes in the Smi in the |idx16| entry in the constant pool
1558 // if the object referenced by the accumulator is the undefined constant.
DoJumpIfUndefinedConstantWide(compiler::InterpreterAssembler * assembler)1559 void Interpreter::DoJumpIfUndefinedConstantWide(
1560 compiler::InterpreterAssembler* assembler) {
1561 DoJumpIfUndefinedConstant(assembler);
1562 }
1563
1564
DoCreateLiteral(Runtime::FunctionId function_id,compiler::InterpreterAssembler * assembler)1565 void Interpreter::DoCreateLiteral(Runtime::FunctionId function_id,
1566 compiler::InterpreterAssembler* assembler) {
1567 Node* index = __ BytecodeOperandIdx(0);
1568 Node* constant_elements = __ LoadConstantPoolEntry(index);
1569 Node* literal_index_raw = __ BytecodeOperandIdx(1);
1570 Node* literal_index = __ SmiTag(literal_index_raw);
1571 Node* flags_raw = __ BytecodeOperandImm(2);
1572 Node* flags = __ SmiTag(flags_raw);
1573 Node* closure = __ LoadRegister(Register::function_closure());
1574 Node* result = __ CallRuntime(function_id, closure, literal_index,
1575 constant_elements, flags);
1576 __ SetAccumulator(result);
1577 __ Dispatch();
1578 }
1579
1580
1581 // CreateRegExpLiteral <pattern_idx> <literal_idx> <flags>
1582 //
1583 // Creates a regular expression literal for literal index <literal_idx> with
1584 // <flags> and the pattern in <pattern_idx>.
DoCreateRegExpLiteral(compiler::InterpreterAssembler * assembler)1585 void Interpreter::DoCreateRegExpLiteral(
1586 compiler::InterpreterAssembler* assembler) {
1587 DoCreateLiteral(Runtime::kCreateRegExpLiteral, assembler);
1588 }
1589
1590
1591 // CreateRegExpLiteralWide <pattern_idx> <literal_idx> <flags>
1592 //
1593 // Creates a regular expression literal for literal index <literal_idx> with
1594 // <flags> and the pattern in <pattern_idx>.
DoCreateRegExpLiteralWide(compiler::InterpreterAssembler * assembler)1595 void Interpreter::DoCreateRegExpLiteralWide(
1596 compiler::InterpreterAssembler* assembler) {
1597 DoCreateLiteral(Runtime::kCreateRegExpLiteral, assembler);
1598 }
1599
1600
1601 // CreateArrayLiteral <element_idx> <literal_idx> <flags>
1602 //
1603 // Creates an array literal for literal index <literal_idx> with flags <flags>
1604 // and constant elements in <element_idx>.
DoCreateArrayLiteral(compiler::InterpreterAssembler * assembler)1605 void Interpreter::DoCreateArrayLiteral(
1606 compiler::InterpreterAssembler* assembler) {
1607 DoCreateLiteral(Runtime::kCreateArrayLiteral, assembler);
1608 }
1609
1610
1611 // CreateArrayLiteralWide <element_idx> <literal_idx> <flags>
1612 //
1613 // Creates an array literal for literal index <literal_idx> with flags <flags>
1614 // and constant elements in <element_idx>.
DoCreateArrayLiteralWide(compiler::InterpreterAssembler * assembler)1615 void Interpreter::DoCreateArrayLiteralWide(
1616 compiler::InterpreterAssembler* assembler) {
1617 DoCreateLiteral(Runtime::kCreateArrayLiteral, assembler);
1618 }
1619
1620
1621 // CreateObjectLiteral <element_idx> <literal_idx> <flags>
1622 //
1623 // Creates an object literal for literal index <literal_idx> with flags <flags>
1624 // and constant elements in <element_idx>.
DoCreateObjectLiteral(compiler::InterpreterAssembler * assembler)1625 void Interpreter::DoCreateObjectLiteral(
1626 compiler::InterpreterAssembler* assembler) {
1627 DoCreateLiteral(Runtime::kCreateObjectLiteral, assembler);
1628 }
1629
1630
1631 // CreateObjectLiteralWide <element_idx> <literal_idx> <flags>
1632 //
1633 // Creates an object literal for literal index <literal_idx> with flags <flags>
1634 // and constant elements in <element_idx>.
DoCreateObjectLiteralWide(compiler::InterpreterAssembler * assembler)1635 void Interpreter::DoCreateObjectLiteralWide(
1636 compiler::InterpreterAssembler* assembler) {
1637 DoCreateLiteral(Runtime::kCreateObjectLiteral, assembler);
1638 }
1639
1640
1641 // CreateClosure <index> <tenured>
1642 //
1643 // Creates a new closure for SharedFunctionInfo at position |index| in the
1644 // constant pool and with the PretenureFlag <tenured>.
DoCreateClosure(compiler::InterpreterAssembler * assembler)1645 void Interpreter::DoCreateClosure(compiler::InterpreterAssembler* assembler) {
1646 // TODO(rmcilroy): Possibly call FastNewClosureStub when possible instead of
1647 // calling into the runtime.
1648 Node* index = __ BytecodeOperandIdx(0);
1649 Node* shared = __ LoadConstantPoolEntry(index);
1650 Node* tenured_raw = __ BytecodeOperandImm(1);
1651 Node* tenured = __ SmiTag(tenured_raw);
1652 Node* result =
1653 __ CallRuntime(Runtime::kInterpreterNewClosure, shared, tenured);
1654 __ SetAccumulator(result);
1655 __ Dispatch();
1656 }
1657
1658
1659 // CreateClosureWide <index> <tenured>
1660 //
1661 // Creates a new closure for SharedFunctionInfo at position |index| in the
1662 // constant pool and with the PretenureFlag <tenured>.
DoCreateClosureWide(compiler::InterpreterAssembler * assembler)1663 void Interpreter::DoCreateClosureWide(
1664 compiler::InterpreterAssembler* assembler) {
1665 return DoCreateClosure(assembler);
1666 }
1667
1668
1669 // CreateMappedArguments
1670 //
1671 // Creates a new mapped arguments object.
DoCreateMappedArguments(compiler::InterpreterAssembler * assembler)1672 void Interpreter::DoCreateMappedArguments(
1673 compiler::InterpreterAssembler* assembler) {
1674 Node* closure = __ LoadRegister(Register::function_closure());
1675 Node* result = __ CallRuntime(Runtime::kNewSloppyArguments_Generic, closure);
1676 __ SetAccumulator(result);
1677 __ Dispatch();
1678 }
1679
1680
1681 // CreateUnmappedArguments
1682 //
1683 // Creates a new unmapped arguments object.
DoCreateUnmappedArguments(compiler::InterpreterAssembler * assembler)1684 void Interpreter::DoCreateUnmappedArguments(
1685 compiler::InterpreterAssembler* assembler) {
1686 Node* closure = __ LoadRegister(Register::function_closure());
1687 Node* result = __ CallRuntime(Runtime::kNewStrictArguments_Generic, closure);
1688 __ SetAccumulator(result);
1689 __ Dispatch();
1690 }
1691
1692
1693 // Throw
1694 //
1695 // Throws the exception in the accumulator.
DoThrow(compiler::InterpreterAssembler * assembler)1696 void Interpreter::DoThrow(compiler::InterpreterAssembler* assembler) {
1697 Node* exception = __ GetAccumulator();
1698 __ CallRuntime(Runtime::kThrow, exception);
1699 // We shouldn't ever return from a throw.
1700 __ Abort(kUnexpectedReturnFromThrow);
1701 }
1702
1703
1704 // Return
1705 //
1706 // Return the value in the accumulator.
DoReturn(compiler::InterpreterAssembler * assembler)1707 void Interpreter::DoReturn(compiler::InterpreterAssembler* assembler) {
1708 __ Return();
1709 }
1710
1711
1712 // ForInPrepare <cache_type> <cache_array> <cache_length>
1713 //
1714 // Returns state for for..in loop execution based on the object in the
1715 // accumulator. The registers |cache_type|, |cache_array|, and
1716 // |cache_length| represent output parameters.
DoForInPrepare(compiler::InterpreterAssembler * assembler)1717 void Interpreter::DoForInPrepare(compiler::InterpreterAssembler* assembler) {
1718 Node* object = __ GetAccumulator();
1719 Node* result = __ CallRuntime(Runtime::kInterpreterForInPrepare, object);
1720 for (int i = 0; i < 3; i++) {
1721 // 0 == cache_type, 1 == cache_array, 2 == cache_length
1722 Node* cache_info = __ LoadFixedArrayElement(result, i);
1723 Node* cache_info_reg = __ BytecodeOperandReg(i);
1724 __ StoreRegister(cache_info, cache_info_reg);
1725 }
1726 __ SetAccumulator(result);
1727 __ Dispatch();
1728 }
1729
1730
1731 // ForInNext <receiver> <cache_type> <cache_array> <index>
1732 //
1733 // Returns the next enumerable property in the the accumulator.
DoForInNext(compiler::InterpreterAssembler * assembler)1734 void Interpreter::DoForInNext(compiler::InterpreterAssembler* assembler) {
1735 Node* receiver_reg = __ BytecodeOperandReg(0);
1736 Node* receiver = __ LoadRegister(receiver_reg);
1737 Node* cache_type_reg = __ BytecodeOperandReg(1);
1738 Node* cache_type = __ LoadRegister(cache_type_reg);
1739 Node* cache_array_reg = __ BytecodeOperandReg(2);
1740 Node* cache_array = __ LoadRegister(cache_array_reg);
1741 Node* index_reg = __ BytecodeOperandReg(3);
1742 Node* index = __ LoadRegister(index_reg);
1743 Node* result = __ CallRuntime(Runtime::kForInNext, receiver, cache_array,
1744 cache_type, index);
1745 __ SetAccumulator(result);
1746 __ Dispatch();
1747 }
1748
1749
1750 // ForInDone <index> <cache_length>
1751 //
1752 // Returns true if the end of the enumerable properties has been reached.
DoForInDone(compiler::InterpreterAssembler * assembler)1753 void Interpreter::DoForInDone(compiler::InterpreterAssembler* assembler) {
1754 // TODO(oth): Implement directly rather than making a runtime call.
1755 Node* index_reg = __ BytecodeOperandReg(0);
1756 Node* index = __ LoadRegister(index_reg);
1757 Node* cache_length_reg = __ BytecodeOperandReg(1);
1758 Node* cache_length = __ LoadRegister(cache_length_reg);
1759 Node* result = __ CallRuntime(Runtime::kForInDone, index, cache_length);
1760 __ SetAccumulator(result);
1761 __ Dispatch();
1762 }
1763
1764
1765 // ForInStep <index>
1766 //
1767 // Increments the loop counter in register |index| and stores the result
1768 // in the accumulator.
DoForInStep(compiler::InterpreterAssembler * assembler)1769 void Interpreter::DoForInStep(compiler::InterpreterAssembler* assembler) {
1770 // TODO(oth): Implement directly rather than making a runtime call.
1771 Node* index_reg = __ BytecodeOperandReg(0);
1772 Node* index = __ LoadRegister(index_reg);
1773 Node* result = __ CallRuntime(Runtime::kForInStep, index);
1774 __ SetAccumulator(result);
1775 __ Dispatch();
1776 }
1777
1778 } // namespace interpreter
1779 } // namespace internal
1780 } // namespace v8
1781