blob: 7080d02120903237aa2803db368440e4429d6ebc [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/compiler/interpreter-assembler.h"
6
7#include <ostream>
8
9#include "src/code-factory.h"
10#include "src/compiler/graph.h"
11#include "src/compiler/instruction-selector.h"
12#include "src/compiler/linkage.h"
13#include "src/compiler/pipeline.h"
14#include "src/compiler/raw-machine-assembler.h"
15#include "src/compiler/schedule.h"
16#include "src/frames.h"
17#include "src/interface-descriptors.h"
18#include "src/interpreter/bytecodes.h"
19#include "src/machine-type.h"
20#include "src/macro-assembler.h"
21#include "src/zone.h"
22
23namespace v8 {
24namespace internal {
25namespace compiler {
26
27
28InterpreterAssembler::InterpreterAssembler(Isolate* isolate, Zone* zone,
29 interpreter::Bytecode bytecode)
30 : bytecode_(bytecode),
31 raw_assembler_(new RawMachineAssembler(
32 isolate, new (zone) Graph(zone),
33 Linkage::GetInterpreterDispatchDescriptor(zone),
34 MachineType::PointerRepresentation(),
35 InstructionSelector::SupportedMachineOperatorFlags())),
36 accumulator_(
37 raw_assembler_->Parameter(Linkage::kInterpreterAccumulatorParameter)),
38 bytecode_offset_(raw_assembler_->Parameter(
39 Linkage::kInterpreterBytecodeOffsetParameter)),
40 context_(
41 raw_assembler_->Parameter(Linkage::kInterpreterContextParameter)),
42 code_generated_(false) {}
43
44
45InterpreterAssembler::~InterpreterAssembler() {}
46
47
48Handle<Code> InterpreterAssembler::GenerateCode() {
49 DCHECK(!code_generated_);
50
51 // Disallow empty handlers that never return.
52 DCHECK_NE(0, graph()->end()->InputCount());
53
54 const char* bytecode_name = interpreter::Bytecodes::ToString(bytecode_);
55 Schedule* schedule = raw_assembler_->Export();
56 Handle<Code> code = Pipeline::GenerateCodeForCodeStub(
57 isolate(), raw_assembler_->call_descriptor(), graph(), schedule,
58 Code::STUB, bytecode_name);
59
60#ifdef ENABLE_DISASSEMBLER
61 if (FLAG_trace_ignition_codegen) {
62 OFStream os(stdout);
63 code->Disassemble(bytecode_name, os);
64 os << std::flush;
65 }
66#endif
67
68 code_generated_ = true;
69 return code;
70}
71
72
73Node* InterpreterAssembler::GetAccumulator() { return accumulator_; }
74
75
76void InterpreterAssembler::SetAccumulator(Node* value) { accumulator_ = value; }
77
78
79Node* InterpreterAssembler::GetContext() { return context_; }
80
81
82void InterpreterAssembler::SetContext(Node* value) { context_ = value; }
83
84
85Node* InterpreterAssembler::BytecodeOffset() { return bytecode_offset_; }
86
87
88Node* InterpreterAssembler::RegisterFileRawPointer() {
89 return raw_assembler_->Parameter(Linkage::kInterpreterRegisterFileParameter);
90}
91
92
93Node* InterpreterAssembler::BytecodeArrayTaggedPointer() {
94 return raw_assembler_->Parameter(Linkage::kInterpreterBytecodeArrayParameter);
95}
96
97
98Node* InterpreterAssembler::DispatchTableRawPointer() {
99 return raw_assembler_->Parameter(Linkage::kInterpreterDispatchTableParameter);
100}
101
102
103Node* InterpreterAssembler::RegisterLocation(Node* reg_index) {
104 return IntPtrAdd(RegisterFileRawPointer(), RegisterFrameOffset(reg_index));
105}
106
107
108Node* InterpreterAssembler::LoadRegister(int offset) {
109 return raw_assembler_->Load(MachineType::AnyTagged(),
110 RegisterFileRawPointer(), Int32Constant(offset));
111}
112
113
114Node* InterpreterAssembler::LoadRegister(interpreter::Register reg) {
115 return LoadRegister(reg.ToOperand() << kPointerSizeLog2);
116}
117
118
119Node* InterpreterAssembler::RegisterFrameOffset(Node* index) {
120 return WordShl(index, kPointerSizeLog2);
121}
122
123
124Node* InterpreterAssembler::LoadRegister(Node* reg_index) {
125 return raw_assembler_->Load(MachineType::AnyTagged(),
126 RegisterFileRawPointer(),
127 RegisterFrameOffset(reg_index));
128}
129
130
131Node* InterpreterAssembler::StoreRegister(Node* value, int offset) {
132 return raw_assembler_->Store(MachineRepresentation::kTagged,
133 RegisterFileRawPointer(), Int32Constant(offset),
134 value, kNoWriteBarrier);
135}
136
137
138Node* InterpreterAssembler::StoreRegister(Node* value,
139 interpreter::Register reg) {
140 return StoreRegister(value, reg.ToOperand() << kPointerSizeLog2);
141}
142
143
144Node* InterpreterAssembler::StoreRegister(Node* value, Node* reg_index) {
145 return raw_assembler_->Store(
146 MachineRepresentation::kTagged, RegisterFileRawPointer(),
147 RegisterFrameOffset(reg_index), value, kNoWriteBarrier);
148}
149
150
151Node* InterpreterAssembler::NextRegister(Node* reg_index) {
152 // Register indexes are negative, so the next index is minus one.
153 return IntPtrAdd(reg_index, Int32Constant(-1));
154}
155
156
157Node* InterpreterAssembler::BytecodeOperand(int operand_index) {
158 DCHECK_LT(operand_index, interpreter::Bytecodes::NumberOfOperands(bytecode_));
159 DCHECK_EQ(interpreter::OperandSize::kByte,
160 interpreter::Bytecodes::GetOperandSize(bytecode_, operand_index));
161 return raw_assembler_->Load(
162 MachineType::Uint8(), BytecodeArrayTaggedPointer(),
163 IntPtrAdd(BytecodeOffset(),
164 Int32Constant(interpreter::Bytecodes::GetOperandOffset(
165 bytecode_, operand_index))));
166}
167
168
169Node* InterpreterAssembler::BytecodeOperandSignExtended(int operand_index) {
170 DCHECK_LT(operand_index, interpreter::Bytecodes::NumberOfOperands(bytecode_));
171 DCHECK_EQ(interpreter::OperandSize::kByte,
172 interpreter::Bytecodes::GetOperandSize(bytecode_, operand_index));
173 Node* load = raw_assembler_->Load(
174 MachineType::Int8(), BytecodeArrayTaggedPointer(),
175 IntPtrAdd(BytecodeOffset(),
176 Int32Constant(interpreter::Bytecodes::GetOperandOffset(
177 bytecode_, operand_index))));
178 // Ensure that we sign extend to full pointer size
179 if (kPointerSize == 8) {
180 load = raw_assembler_->ChangeInt32ToInt64(load);
181 }
182 return load;
183}
184
185
186Node* InterpreterAssembler::BytecodeOperandShort(int operand_index) {
187 DCHECK_LT(operand_index, interpreter::Bytecodes::NumberOfOperands(bytecode_));
188 DCHECK_EQ(interpreter::OperandSize::kShort,
189 interpreter::Bytecodes::GetOperandSize(bytecode_, operand_index));
190 if (TargetSupportsUnalignedAccess()) {
191 return raw_assembler_->Load(
192 MachineType::Uint16(), BytecodeArrayTaggedPointer(),
193 IntPtrAdd(BytecodeOffset(),
194 Int32Constant(interpreter::Bytecodes::GetOperandOffset(
195 bytecode_, operand_index))));
196 } else {
197 int offset =
198 interpreter::Bytecodes::GetOperandOffset(bytecode_, operand_index);
199 Node* first_byte = raw_assembler_->Load(
200 MachineType::Uint8(), BytecodeArrayTaggedPointer(),
201 IntPtrAdd(BytecodeOffset(), Int32Constant(offset)));
202 Node* second_byte = raw_assembler_->Load(
203 MachineType::Uint8(), BytecodeArrayTaggedPointer(),
204 IntPtrAdd(BytecodeOffset(), Int32Constant(offset + 1)));
205#if V8_TARGET_LITTLE_ENDIAN
206 return raw_assembler_->WordOr(WordShl(second_byte, kBitsPerByte),
207 first_byte);
208#elif V8_TARGET_BIG_ENDIAN
209 return raw_assembler_->WordOr(WordShl(first_byte, kBitsPerByte),
210 second_byte);
211#else
212#error "Unknown Architecture"
213#endif
214 }
215}
216
217
218Node* InterpreterAssembler::BytecodeOperandShortSignExtended(
219 int operand_index) {
220 DCHECK_LT(operand_index, interpreter::Bytecodes::NumberOfOperands(bytecode_));
221 DCHECK_EQ(interpreter::OperandSize::kShort,
222 interpreter::Bytecodes::GetOperandSize(bytecode_, operand_index));
223 int operand_offset =
224 interpreter::Bytecodes::GetOperandOffset(bytecode_, operand_index);
225 Node* load;
226 if (TargetSupportsUnalignedAccess()) {
227 load = raw_assembler_->Load(
228 MachineType::Int16(), BytecodeArrayTaggedPointer(),
229 IntPtrAdd(BytecodeOffset(), Int32Constant(operand_offset)));
230 } else {
231#if V8_TARGET_LITTLE_ENDIAN
232 Node* hi_byte_offset = Int32Constant(operand_offset + 1);
233 Node* lo_byte_offset = Int32Constant(operand_offset);
234#elif V8_TARGET_BIG_ENDIAN
235 Node* hi_byte_offset = Int32Constant(operand_offset);
236 Node* lo_byte_offset = Int32Constant(operand_offset + 1);
237#else
238#error "Unknown Architecture"
239#endif
240 Node* hi_byte =
241 raw_assembler_->Load(MachineType::Int8(), BytecodeArrayTaggedPointer(),
242 IntPtrAdd(BytecodeOffset(), hi_byte_offset));
243 Node* lo_byte =
244 raw_assembler_->Load(MachineType::Uint8(), BytecodeArrayTaggedPointer(),
245 IntPtrAdd(BytecodeOffset(), lo_byte_offset));
246 hi_byte = raw_assembler_->Word32Shl(hi_byte, Int32Constant(kBitsPerByte));
247 load = raw_assembler_->Word32Or(hi_byte, lo_byte);
248 }
249
250 // Ensure that we sign extend to full pointer size
251 if (kPointerSize == 8) {
252 load = raw_assembler_->ChangeInt32ToInt64(load);
253 }
254 return load;
255}
256
257
258Node* InterpreterAssembler::BytecodeOperandCount(int operand_index) {
259 switch (interpreter::Bytecodes::GetOperandSize(bytecode_, operand_index)) {
260 case interpreter::OperandSize::kByte:
261 DCHECK_EQ(
262 interpreter::OperandType::kCount8,
263 interpreter::Bytecodes::GetOperandType(bytecode_, operand_index));
264 return BytecodeOperand(operand_index);
265 case interpreter::OperandSize::kShort:
266 DCHECK_EQ(
267 interpreter::OperandType::kCount16,
268 interpreter::Bytecodes::GetOperandType(bytecode_, operand_index));
269 return BytecodeOperandShort(operand_index);
270 default:
271 UNREACHABLE();
272 return nullptr;
273 }
274}
275
276
277Node* InterpreterAssembler::BytecodeOperandImm(int operand_index) {
278 DCHECK_EQ(interpreter::OperandType::kImm8,
279 interpreter::Bytecodes::GetOperandType(bytecode_, operand_index));
280 return BytecodeOperandSignExtended(operand_index);
281}
282
283
284Node* InterpreterAssembler::BytecodeOperandIdx(int operand_index) {
285 switch (interpreter::Bytecodes::GetOperandSize(bytecode_, operand_index)) {
286 case interpreter::OperandSize::kByte:
287 DCHECK_EQ(
288 interpreter::OperandType::kIdx8,
289 interpreter::Bytecodes::GetOperandType(bytecode_, operand_index));
290 return BytecodeOperand(operand_index);
291 case interpreter::OperandSize::kShort:
292 DCHECK_EQ(
293 interpreter::OperandType::kIdx16,
294 interpreter::Bytecodes::GetOperandType(bytecode_, operand_index));
295 return BytecodeOperandShort(operand_index);
296 default:
297 UNREACHABLE();
298 return nullptr;
299 }
300}
301
302
303Node* InterpreterAssembler::BytecodeOperandReg(int operand_index) {
304 switch (interpreter::Bytecodes::GetOperandType(bytecode_, operand_index)) {
305 case interpreter::OperandType::kReg8:
306 case interpreter::OperandType::kRegPair8:
307 case interpreter::OperandType::kMaybeReg8:
308 DCHECK_EQ(
309 interpreter::OperandSize::kByte,
310 interpreter::Bytecodes::GetOperandSize(bytecode_, operand_index));
311 return BytecodeOperandSignExtended(operand_index);
312 case interpreter::OperandType::kReg16:
313 DCHECK_EQ(
314 interpreter::OperandSize::kShort,
315 interpreter::Bytecodes::GetOperandSize(bytecode_, operand_index));
316 return BytecodeOperandShortSignExtended(operand_index);
317 default:
318 UNREACHABLE();
319 return nullptr;
320 }
321}
322
323
324Node* InterpreterAssembler::Int32Constant(int value) {
325 return raw_assembler_->Int32Constant(value);
326}
327
328
329Node* InterpreterAssembler::IntPtrConstant(intptr_t value) {
330 return raw_assembler_->IntPtrConstant(value);
331}
332
333
334Node* InterpreterAssembler::NumberConstant(double value) {
335 return raw_assembler_->NumberConstant(value);
336}
337
338
339Node* InterpreterAssembler::HeapConstant(Handle<HeapObject> object) {
340 return raw_assembler_->HeapConstant(object);
341}
342
343
344Node* InterpreterAssembler::BooleanConstant(bool value) {
345 return raw_assembler_->BooleanConstant(value);
346}
347
348
349Node* InterpreterAssembler::SmiShiftBitsConstant() {
350 return Int32Constant(kSmiShiftSize + kSmiTagSize);
351}
352
353
354Node* InterpreterAssembler::SmiTag(Node* value) {
355 return raw_assembler_->WordShl(value, SmiShiftBitsConstant());
356}
357
358
359Node* InterpreterAssembler::SmiUntag(Node* value) {
360 return raw_assembler_->WordSar(value, SmiShiftBitsConstant());
361}
362
363
364Node* InterpreterAssembler::IntPtrAdd(Node* a, Node* b) {
365 return raw_assembler_->IntPtrAdd(a, b);
366}
367
368
369Node* InterpreterAssembler::IntPtrSub(Node* a, Node* b) {
370 return raw_assembler_->IntPtrSub(a, b);
371}
372
373
374Node* InterpreterAssembler::WordShl(Node* value, int shift) {
375 return raw_assembler_->WordShl(value, Int32Constant(shift));
376}
377
378
379Node* InterpreterAssembler::LoadConstantPoolEntry(Node* index) {
380 Node* constant_pool = LoadObjectField(BytecodeArrayTaggedPointer(),
381 BytecodeArray::kConstantPoolOffset);
382 Node* entry_offset =
383 IntPtrAdd(IntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag),
384 WordShl(index, kPointerSizeLog2));
385 return raw_assembler_->Load(MachineType::AnyTagged(), constant_pool,
386 entry_offset);
387}
388
389
390Node* InterpreterAssembler::LoadFixedArrayElement(Node* fixed_array,
391 int index) {
392 Node* entry_offset =
393 IntPtrAdd(IntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag),
394 WordShl(Int32Constant(index), kPointerSizeLog2));
395 return raw_assembler_->Load(MachineType::AnyTagged(), fixed_array,
396 entry_offset);
397}
398
399
400Node* InterpreterAssembler::LoadObjectField(Node* object, int offset) {
401 return raw_assembler_->Load(MachineType::AnyTagged(), object,
402 IntPtrConstant(offset - kHeapObjectTag));
403}
404
405
406Node* InterpreterAssembler::LoadContextSlot(Node* context, int slot_index) {
407 return raw_assembler_->Load(MachineType::AnyTagged(), context,
408 IntPtrConstant(Context::SlotOffset(slot_index)));
409}
410
411
412Node* InterpreterAssembler::LoadContextSlot(Node* context, Node* slot_index) {
413 Node* offset =
414 IntPtrAdd(WordShl(slot_index, kPointerSizeLog2),
415 Int32Constant(Context::kHeaderSize - kHeapObjectTag));
416 return raw_assembler_->Load(MachineType::AnyTagged(), context, offset);
417}
418
419
420Node* InterpreterAssembler::StoreContextSlot(Node* context, Node* slot_index,
421 Node* value) {
422 Node* offset =
423 IntPtrAdd(WordShl(slot_index, kPointerSizeLog2),
424 Int32Constant(Context::kHeaderSize - kHeapObjectTag));
425 return raw_assembler_->Store(MachineRepresentation::kTagged, context, offset,
426 value, kFullWriteBarrier);
427}
428
429
430Node* InterpreterAssembler::LoadTypeFeedbackVector() {
431 Node* function = raw_assembler_->Load(
432 MachineType::AnyTagged(), RegisterFileRawPointer(),
433 IntPtrConstant(InterpreterFrameConstants::kFunctionFromRegisterPointer));
434 Node* shared_info =
435 LoadObjectField(function, JSFunction::kSharedFunctionInfoOffset);
436 Node* vector =
437 LoadObjectField(shared_info, SharedFunctionInfo::kFeedbackVectorOffset);
438 return vector;
439}
440
441
442Node* InterpreterAssembler::Projection(int index, Node* node) {
443 return raw_assembler_->Projection(index, node);
444}
445
446
447Node* InterpreterAssembler::CallConstruct(Node* new_target, Node* constructor,
448 Node* first_arg, Node* arg_count) {
449 Callable callable = CodeFactory::InterpreterPushArgsAndConstruct(isolate());
450 CallDescriptor* descriptor = Linkage::GetStubCallDescriptor(
451 isolate(), zone(), callable.descriptor(), 0, CallDescriptor::kNoFlags);
452
453 Node* code_target = HeapConstant(callable.code());
454
455 Node** args = zone()->NewArray<Node*>(5);
456 args[0] = arg_count;
457 args[1] = new_target;
458 args[2] = constructor;
459 args[3] = first_arg;
460 args[4] = GetContext();
461
462 return CallN(descriptor, code_target, args);
463}
464
465
466void InterpreterAssembler::CallPrologue() {
467 StoreRegister(SmiTag(bytecode_offset_),
468 InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer);
469}
470
471
472void InterpreterAssembler::CallEpilogue() {
473 // Restore the bytecode offset from the stack frame.
474 bytecode_offset_ = SmiUntag(LoadRegister(
475 InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer));
476}
477
478
479Node* InterpreterAssembler::CallN(CallDescriptor* descriptor, Node* code_target,
480 Node** args) {
481 CallPrologue();
482
483 Node* stack_pointer_before_call = nullptr;
484 if (FLAG_debug_code) {
485 stack_pointer_before_call = raw_assembler_->LoadStackPointer();
486 }
487 Node* return_val = raw_assembler_->CallN(descriptor, code_target, args);
488 if (FLAG_debug_code) {
489 Node* stack_pointer_after_call = raw_assembler_->LoadStackPointer();
490 AbortIfWordNotEqual(stack_pointer_before_call, stack_pointer_after_call,
491 kUnexpectedStackPointer);
492 }
493
494 CallEpilogue();
495 return return_val;
496}
497
498
499Node* InterpreterAssembler::CallJS(Node* function, Node* first_arg,
500 Node* arg_count) {
501 Callable callable = CodeFactory::InterpreterPushArgsAndCall(isolate());
502 CallDescriptor* descriptor = Linkage::GetStubCallDescriptor(
503 isolate(), zone(), callable.descriptor(), 0, CallDescriptor::kNoFlags);
504
505 Node* code_target = HeapConstant(callable.code());
506
507 Node** args = zone()->NewArray<Node*>(4);
508 args[0] = arg_count;
509 args[1] = first_arg;
510 args[2] = function;
511 args[3] = GetContext();
512
513 return CallN(descriptor, code_target, args);
514}
515
516
517Node* InterpreterAssembler::CallIC(CallInterfaceDescriptor descriptor,
518 Node* target, Node** args) {
519 CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
520 isolate(), zone(), descriptor, 0, CallDescriptor::kNoFlags);
521 return CallN(call_descriptor, target, args);
522}
523
524
525Node* InterpreterAssembler::CallIC(CallInterfaceDescriptor descriptor,
526 Node* target, Node* arg1, Node* arg2,
527 Node* arg3) {
528 Node** args = zone()->NewArray<Node*>(4);
529 args[0] = arg1;
530 args[1] = arg2;
531 args[2] = arg3;
532 args[3] = GetContext();
533 return CallIC(descriptor, target, args);
534}
535
536
537Node* InterpreterAssembler::CallIC(CallInterfaceDescriptor descriptor,
538 Node* target, Node* arg1, Node* arg2,
539 Node* arg3, Node* arg4) {
540 Node** args = zone()->NewArray<Node*>(5);
541 args[0] = arg1;
542 args[1] = arg2;
543 args[2] = arg3;
544 args[3] = arg4;
545 args[4] = GetContext();
546 return CallIC(descriptor, target, args);
547}
548
549
550Node* InterpreterAssembler::CallIC(CallInterfaceDescriptor descriptor,
551 Node* target, Node* arg1, Node* arg2,
552 Node* arg3, Node* arg4, Node* arg5) {
553 Node** args = zone()->NewArray<Node*>(6);
554 args[0] = arg1;
555 args[1] = arg2;
556 args[2] = arg3;
557 args[3] = arg4;
558 args[4] = arg5;
559 args[5] = GetContext();
560 return CallIC(descriptor, target, args);
561}
562
563
564Node* InterpreterAssembler::CallRuntime(Node* function_id, Node* first_arg,
565 Node* arg_count, int result_size) {
566 Callable callable = CodeFactory::InterpreterCEntry(isolate(), result_size);
567 CallDescriptor* descriptor = Linkage::GetStubCallDescriptor(
568 isolate(), zone(), callable.descriptor(), 0, CallDescriptor::kNoFlags,
569 Operator::kNoProperties, MachineType::AnyTagged(), result_size);
570 Node* code_target = HeapConstant(callable.code());
571
572 // Get the function entry from the function id.
573 Node* function_table = raw_assembler_->ExternalConstant(
574 ExternalReference::runtime_function_table_address(isolate()));
575 Node* function_offset = raw_assembler_->Int32Mul(
576 function_id, Int32Constant(sizeof(Runtime::Function)));
577 Node* function = IntPtrAdd(function_table, function_offset);
578 Node* function_entry =
579 raw_assembler_->Load(MachineType::Pointer(), function,
580 Int32Constant(offsetof(Runtime::Function, entry)));
581
582 Node** args = zone()->NewArray<Node*>(4);
583 args[0] = arg_count;
584 args[1] = first_arg;
585 args[2] = function_entry;
586 args[3] = GetContext();
587
588 return CallN(descriptor, code_target, args);
589}
590
591
592Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id,
593 Node* arg1) {
594 CallPrologue();
595 Node* return_val =
596 raw_assembler_->CallRuntime1(function_id, arg1, GetContext());
597 CallEpilogue();
598 return return_val;
599}
600
601
602Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id,
603 Node* arg1, Node* arg2) {
604 CallPrologue();
605 Node* return_val =
606 raw_assembler_->CallRuntime2(function_id, arg1, arg2, GetContext());
607 CallEpilogue();
608 return return_val;
609}
610
611
612Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id,
613 Node* arg1, Node* arg2, Node* arg3,
614 Node* arg4) {
615 CallPrologue();
616 Node* return_val = raw_assembler_->CallRuntime4(function_id, arg1, arg2, arg3,
617 arg4, GetContext());
618 CallEpilogue();
619 return return_val;
620}
621
622
623void InterpreterAssembler::Return() {
624 Node* exit_trampoline_code_object =
625 HeapConstant(isolate()->builtins()->InterpreterExitTrampoline());
626 // If the order of the parameters you need to change the call signature below.
627 STATIC_ASSERT(0 == Linkage::kInterpreterAccumulatorParameter);
628 STATIC_ASSERT(1 == Linkage::kInterpreterRegisterFileParameter);
629 STATIC_ASSERT(2 == Linkage::kInterpreterBytecodeOffsetParameter);
630 STATIC_ASSERT(3 == Linkage::kInterpreterBytecodeArrayParameter);
631 STATIC_ASSERT(4 == Linkage::kInterpreterDispatchTableParameter);
632 STATIC_ASSERT(5 == Linkage::kInterpreterContextParameter);
633 Node* args[] = { GetAccumulator(),
634 RegisterFileRawPointer(),
635 BytecodeOffset(),
636 BytecodeArrayTaggedPointer(),
637 DispatchTableRawPointer(),
638 GetContext() };
639 raw_assembler_->TailCallN(call_descriptor(), exit_trampoline_code_object,
640 args);
641}
642
643
644Node* InterpreterAssembler::Advance(int delta) {
645 return IntPtrAdd(BytecodeOffset(), Int32Constant(delta));
646}
647
648
649Node* InterpreterAssembler::Advance(Node* delta) {
650 return raw_assembler_->IntPtrAdd(BytecodeOffset(), delta);
651}
652
653
654void InterpreterAssembler::Jump(Node* delta) { DispatchTo(Advance(delta)); }
655
656
657void InterpreterAssembler::JumpIfWordEqual(Node* lhs, Node* rhs, Node* delta) {
658 RawMachineLabel match, no_match;
659 Node* condition = raw_assembler_->WordEqual(lhs, rhs);
660 raw_assembler_->Branch(condition, &match, &no_match);
661 raw_assembler_->Bind(&match);
662 DispatchTo(Advance(delta));
663 raw_assembler_->Bind(&no_match);
664 Dispatch();
665}
666
667
668void InterpreterAssembler::Dispatch() {
669 DispatchTo(Advance(interpreter::Bytecodes::Size(bytecode_)));
670}
671
672
673void InterpreterAssembler::DispatchTo(Node* new_bytecode_offset) {
674 Node* target_bytecode = raw_assembler_->Load(
675 MachineType::Uint8(), BytecodeArrayTaggedPointer(), new_bytecode_offset);
676
677 // TODO(rmcilroy): Create a code target dispatch table to avoid conversion
678 // from code object on every dispatch.
679 Node* target_code_object = raw_assembler_->Load(
680 MachineType::Pointer(), DispatchTableRawPointer(),
681 raw_assembler_->Word32Shl(target_bytecode,
682 Int32Constant(kPointerSizeLog2)));
683
684 // If the order of the parameters you need to change the call signature below.
685 STATIC_ASSERT(0 == Linkage::kInterpreterAccumulatorParameter);
686 STATIC_ASSERT(1 == Linkage::kInterpreterRegisterFileParameter);
687 STATIC_ASSERT(2 == Linkage::kInterpreterBytecodeOffsetParameter);
688 STATIC_ASSERT(3 == Linkage::kInterpreterBytecodeArrayParameter);
689 STATIC_ASSERT(4 == Linkage::kInterpreterDispatchTableParameter);
690 STATIC_ASSERT(5 == Linkage::kInterpreterContextParameter);
691 Node* args[] = { GetAccumulator(),
692 RegisterFileRawPointer(),
693 new_bytecode_offset,
694 BytecodeArrayTaggedPointer(),
695 DispatchTableRawPointer(),
696 GetContext() };
697 raw_assembler_->TailCallN(call_descriptor(), target_code_object, args);
698}
699
700
701void InterpreterAssembler::Abort(BailoutReason bailout_reason) {
702 Node* abort_id = SmiTag(Int32Constant(bailout_reason));
703 Node* ret_value = CallRuntime(Runtime::kAbort, abort_id);
704 // Unreached, but keeps turbofan happy.
705 raw_assembler_->Return(ret_value);
706}
707
708
709void InterpreterAssembler::AbortIfWordNotEqual(Node* lhs, Node* rhs,
710 BailoutReason bailout_reason) {
711 RawMachineLabel match, no_match;
712 Node* condition = raw_assembler_->WordEqual(lhs, rhs);
713 raw_assembler_->Branch(condition, &match, &no_match);
714 raw_assembler_->Bind(&no_match);
715 Abort(bailout_reason);
716 raw_assembler_->Bind(&match);
717}
718
719
720// static
721bool InterpreterAssembler::TargetSupportsUnalignedAccess() {
722#if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
723 return false;
724#elif V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_PPC
725 return CpuFeatures::IsSupported(UNALIGNED_ACCESSES);
726#elif V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_X87
727 return true;
728#else
729#error "Unknown Architecture"
730#endif
731}
732
733
734// RawMachineAssembler delegate helpers:
735Isolate* InterpreterAssembler::isolate() { return raw_assembler_->isolate(); }
736
737
738Graph* InterpreterAssembler::graph() { return raw_assembler_->graph(); }
739
740
741CallDescriptor* InterpreterAssembler::call_descriptor() const {
742 return raw_assembler_->call_descriptor();
743}
744
745
746Zone* InterpreterAssembler::zone() { return raw_assembler_->zone(); }
747
748
749} // namespace compiler
750} // namespace internal
751} // namespace v8