[presubmit] Enable readability/namespace linter checking.
[platform/upstream/v8.git] / src / compiler / interpreter-assembler.cc
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/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/machine-type.h"
14 #include "src/compiler/pipeline.h"
15 #include "src/compiler/raw-machine-assembler.h"
16 #include "src/compiler/schedule.h"
17 #include "src/frames.h"
18 #include "src/interface-descriptors.h"
19 #include "src/interpreter/bytecodes.h"
20 #include "src/macro-assembler.h"
21 #include "src/zone.h"
22
23 namespace v8 {
24 namespace internal {
25 namespace compiler {
26
27
28 InterpreterAssembler::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), kMachPtr,
34           InstructionSelector::SupportedMachineOperatorFlags())),
35       end_nodes_(zone),
36       accumulator_(
37           raw_assembler_->Parameter(Linkage::kInterpreterAccumulatorParameter)),
38       code_generated_(false) {}
39
40
41 InterpreterAssembler::~InterpreterAssembler() {}
42
43
44 Handle<Code> InterpreterAssembler::GenerateCode() {
45   DCHECK(!code_generated_);
46
47   End();
48
49   const char* bytecode_name = interpreter::Bytecodes::ToString(bytecode_);
50   Schedule* schedule = raw_assembler_->Export();
51   // TODO(rmcilroy): use a non-testing code generator.
52   Handle<Code> code = Pipeline::GenerateCodeForInterpreter(
53       isolate(), raw_assembler_->call_descriptor(), graph(), schedule,
54       bytecode_name);
55
56 #ifdef ENABLE_DISASSEMBLER
57   if (FLAG_trace_ignition_codegen) {
58     OFStream os(stdout);
59     code->Disassemble(bytecode_name, os);
60     os << std::flush;
61   }
62 #endif
63
64   code_generated_ = true;
65   return code;
66 }
67
68
69 Node* InterpreterAssembler::GetAccumulator() {
70   return accumulator_;
71 }
72
73
74 void InterpreterAssembler::SetAccumulator(Node* value) {
75   accumulator_ = value;
76 }
77
78
79 Node* InterpreterAssembler::ContextTaggedPointer() {
80   return raw_assembler_->Parameter(Linkage::kInterpreterContextParameter);
81 }
82
83
84 Node* InterpreterAssembler::RegisterFileRawPointer() {
85   return raw_assembler_->Parameter(Linkage::kInterpreterRegisterFileParameter);
86 }
87
88
89 Node* InterpreterAssembler::BytecodeArrayTaggedPointer() {
90   return raw_assembler_->Parameter(Linkage::kInterpreterBytecodeArrayParameter);
91 }
92
93
94 Node* InterpreterAssembler::BytecodeOffset() {
95   return raw_assembler_->Parameter(
96       Linkage::kInterpreterBytecodeOffsetParameter);
97 }
98
99
100 Node* InterpreterAssembler::DispatchTableRawPointer() {
101   return raw_assembler_->Parameter(Linkage::kInterpreterDispatchTableParameter);
102 }
103
104
105 Node* InterpreterAssembler::RegisterFrameOffset(Node* index) {
106   return WordShl(index, kPointerSizeLog2);
107 }
108
109
110 Node* InterpreterAssembler::RegisterLocation(Node* reg_index) {
111   return IntPtrAdd(RegisterFileRawPointer(), RegisterFrameOffset(reg_index));
112 }
113
114
115 Node* InterpreterAssembler::LoadRegister(Node* reg_index) {
116   return raw_assembler_->Load(kMachAnyTagged, RegisterFileRawPointer(),
117                               RegisterFrameOffset(reg_index));
118 }
119
120
121 Node* InterpreterAssembler::StoreRegister(Node* value, Node* reg_index) {
122   return raw_assembler_->Store(kMachAnyTagged, RegisterFileRawPointer(),
123                                RegisterFrameOffset(reg_index), value);
124 }
125
126
127 Node* InterpreterAssembler::BytecodeOperand(int operand_index) {
128   DCHECK_LT(operand_index, interpreter::Bytecodes::NumberOfOperands(bytecode_));
129   return raw_assembler_->Load(
130       kMachUint8, BytecodeArrayTaggedPointer(),
131       IntPtrAdd(BytecodeOffset(), Int32Constant(1 + operand_index)));
132 }
133
134
135 Node* InterpreterAssembler::BytecodeOperandSignExtended(int operand_index) {
136   DCHECK_LT(operand_index, interpreter::Bytecodes::NumberOfOperands(bytecode_));
137   Node* load = raw_assembler_->Load(
138       kMachInt8, BytecodeArrayTaggedPointer(),
139       IntPtrAdd(BytecodeOffset(), Int32Constant(1 + operand_index)));
140   // Ensure that we sign extend to full pointer size
141   if (kPointerSize == 8) {
142     load = raw_assembler_->ChangeInt32ToInt64(load);
143   }
144   return load;
145 }
146
147
148 Node* InterpreterAssembler::BytecodeOperandCount(int operand_index) {
149   DCHECK_EQ(interpreter::OperandType::kCount,
150             interpreter::Bytecodes::GetOperandType(bytecode_, operand_index));
151   return BytecodeOperand(operand_index);
152 }
153
154
155 Node* InterpreterAssembler::BytecodeOperandImm8(int operand_index) {
156   DCHECK_EQ(interpreter::OperandType::kImm8,
157             interpreter::Bytecodes::GetOperandType(bytecode_, operand_index));
158   return BytecodeOperandSignExtended(operand_index);
159 }
160
161
162 Node* InterpreterAssembler::BytecodeOperandIdx(int operand_index) {
163   DCHECK_EQ(interpreter::OperandType::kIdx,
164             interpreter::Bytecodes::GetOperandType(bytecode_, operand_index));
165   return BytecodeOperand(operand_index);
166 }
167
168
169 Node* InterpreterAssembler::BytecodeOperandReg(int operand_index) {
170   DCHECK_EQ(interpreter::OperandType::kReg,
171             interpreter::Bytecodes::GetOperandType(bytecode_, operand_index));
172   return BytecodeOperandSignExtended(operand_index);
173 }
174
175
176 Node* InterpreterAssembler::Int32Constant(int value) {
177   return raw_assembler_->Int32Constant(value);
178 }
179
180
181 Node* InterpreterAssembler::IntPtrConstant(intptr_t value) {
182   return raw_assembler_->IntPtrConstant(value);
183 }
184
185
186 Node* InterpreterAssembler::NumberConstant(double value) {
187   return raw_assembler_->NumberConstant(value);
188 }
189
190
191 Node* InterpreterAssembler::HeapConstant(Handle<HeapObject> object) {
192   return raw_assembler_->HeapConstant(object);
193 }
194
195
196 Node* InterpreterAssembler::BooleanConstant(bool value) {
197   return raw_assembler_->BooleanConstant(value);
198 }
199
200
201 Node* InterpreterAssembler::SmiShiftBitsConstant() {
202   return Int32Constant(kSmiShiftSize + kSmiTagSize);
203 }
204
205
206 Node* InterpreterAssembler::SmiTag(Node* value) {
207   return raw_assembler_->WordShl(value, SmiShiftBitsConstant());
208 }
209
210
211 Node* InterpreterAssembler::SmiUntag(Node* value) {
212   return raw_assembler_->WordSar(value, SmiShiftBitsConstant());
213 }
214
215
216 Node* InterpreterAssembler::IntPtrAdd(Node* a, Node* b) {
217   return raw_assembler_->IntPtrAdd(a, b);
218 }
219
220
221 Node* InterpreterAssembler::IntPtrSub(Node* a, Node* b) {
222   return raw_assembler_->IntPtrSub(a, b);
223 }
224
225
226 Node* InterpreterAssembler::WordShl(Node* value, int shift) {
227   return raw_assembler_->WordShl(value, Int32Constant(shift));
228 }
229
230
231 Node* InterpreterAssembler::LoadConstantPoolEntry(Node* index) {
232   Node* constant_pool = LoadObjectField(BytecodeArrayTaggedPointer(),
233                                         BytecodeArray::kConstantPoolOffset);
234   Node* entry_offset =
235       IntPtrAdd(IntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag),
236                 WordShl(index, kPointerSizeLog2));
237   return raw_assembler_->Load(kMachAnyTagged, constant_pool, entry_offset);
238 }
239
240
241 Node* InterpreterAssembler::LoadObjectField(Node* object, int offset) {
242   return raw_assembler_->Load(kMachAnyTagged, object,
243                               IntPtrConstant(offset - kHeapObjectTag));
244 }
245
246
247 Node* InterpreterAssembler::LoadContextSlot(Node* context, int slot_index) {
248   return raw_assembler_->Load(kMachAnyTagged, context,
249                               IntPtrConstant(Context::SlotOffset(slot_index)));
250 }
251
252
253 Node* InterpreterAssembler::LoadContextSlot(int slot_index) {
254   return LoadContextSlot(ContextTaggedPointer(), slot_index);
255 }
256
257
258 Node* InterpreterAssembler::LoadTypeFeedbackVector() {
259   Node* function = raw_assembler_->Load(
260       kMachAnyTagged, RegisterFileRawPointer(),
261       IntPtrConstant(InterpreterFrameConstants::kFunctionFromRegisterPointer));
262   Node* shared_info =
263       LoadObjectField(function, JSFunction::kSharedFunctionInfoOffset);
264   Node* vector =
265       LoadObjectField(shared_info, SharedFunctionInfo::kFeedbackVectorOffset);
266   return vector;
267 }
268
269
270 Node* InterpreterAssembler::CallJS(Node* function, Node* first_arg,
271                                    Node* arg_count) {
272   Callable builtin = CodeFactory::PushArgsAndCall(isolate());
273   CallDescriptor* descriptor = Linkage::GetStubCallDescriptor(
274       isolate(), zone(), builtin.descriptor(), 0, CallDescriptor::kNoFlags);
275
276   Node* code_target = HeapConstant(builtin.code());
277
278   Node** args = zone()->NewArray<Node*>(4);
279   args[0] = arg_count;
280   args[1] = first_arg;
281   args[2] = function;
282   args[3] = ContextTaggedPointer();
283
284   return raw_assembler_->CallN(descriptor, code_target, args);
285 }
286
287
288 Node* InterpreterAssembler::CallIC(CallInterfaceDescriptor descriptor,
289                                    Node* target, Node** args) {
290   CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
291       isolate(), zone(), descriptor, 0, CallDescriptor::kNoFlags);
292   return raw_assembler_->CallN(call_descriptor, target, args);
293 }
294
295
296 Node* InterpreterAssembler::CallIC(CallInterfaceDescriptor descriptor,
297                                    Node* target, Node* arg1, Node* arg2,
298                                    Node* arg3, Node* arg4) {
299   Node** args = zone()->NewArray<Node*>(5);
300   args[0] = arg1;
301   args[1] = arg2;
302   args[2] = arg3;
303   args[3] = arg4;
304   args[4] = ContextTaggedPointer();
305   return CallIC(descriptor, target, args);
306 }
307
308
309 Node* InterpreterAssembler::CallIC(CallInterfaceDescriptor descriptor,
310                                    Node* target, Node* arg1, Node* arg2,
311                                    Node* arg3, Node* arg4, Node* arg5) {
312   Node** args = zone()->NewArray<Node*>(6);
313   args[0] = arg1;
314   args[1] = arg2;
315   args[2] = arg3;
316   args[3] = arg4;
317   args[4] = arg5;
318   args[5] = ContextTaggedPointer();
319   return CallIC(descriptor, target, args);
320 }
321
322
323 Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id,
324                                         Node* arg1) {
325   return raw_assembler_->CallRuntime1(function_id, arg1,
326                                       ContextTaggedPointer());
327 }
328
329
330 Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id,
331                                         Node* arg1, Node* arg2) {
332   return raw_assembler_->CallRuntime2(function_id, arg1, arg2,
333                                       ContextTaggedPointer());
334 }
335
336
337 void InterpreterAssembler::Return() {
338   Node* exit_trampoline_code_object =
339       HeapConstant(isolate()->builtins()->InterpreterExitTrampoline());
340   // If the order of the parameters you need to change the call signature below.
341   STATIC_ASSERT(0 == Linkage::kInterpreterAccumulatorParameter);
342   STATIC_ASSERT(1 == Linkage::kInterpreterRegisterFileParameter);
343   STATIC_ASSERT(2 == Linkage::kInterpreterBytecodeOffsetParameter);
344   STATIC_ASSERT(3 == Linkage::kInterpreterBytecodeArrayParameter);
345   STATIC_ASSERT(4 == Linkage::kInterpreterDispatchTableParameter);
346   STATIC_ASSERT(5 == Linkage::kInterpreterContextParameter);
347   Node* args[] = { GetAccumulator(),
348                    RegisterFileRawPointer(),
349                    BytecodeOffset(),
350                    BytecodeArrayTaggedPointer(),
351                    DispatchTableRawPointer(),
352                    ContextTaggedPointer() };
353   Node* tail_call = raw_assembler_->TailCallN(
354       call_descriptor(), exit_trampoline_code_object, args);
355   // This should always be the end node.
356   AddEndInput(tail_call);
357 }
358
359
360 Node* InterpreterAssembler::Advance(int delta) {
361   return IntPtrAdd(BytecodeOffset(), Int32Constant(delta));
362 }
363
364
365 Node* InterpreterAssembler::Advance(Node* delta) {
366   return raw_assembler_->IntPtrAdd(BytecodeOffset(), delta);
367 }
368
369
370 void InterpreterAssembler::Jump(Node* delta) { DispatchTo(Advance(delta)); }
371
372
373 void InterpreterAssembler::JumpIfWordEqual(Node* lhs, Node* rhs, Node* delta) {
374   RawMachineAssembler::Label match, no_match;
375   Node* condition = raw_assembler_->WordEqual(lhs, rhs);
376   raw_assembler_->Branch(condition, &match, &no_match);
377   raw_assembler_->Bind(&match);
378   DispatchTo(Advance(delta));
379   raw_assembler_->Bind(&no_match);
380   Dispatch();
381 }
382
383
384 void InterpreterAssembler::Dispatch() {
385   DispatchTo(Advance(interpreter::Bytecodes::Size(bytecode_)));
386 }
387
388
389 void InterpreterAssembler::DispatchTo(Node* new_bytecode_offset) {
390   Node* target_bytecode = raw_assembler_->Load(
391       kMachUint8, BytecodeArrayTaggedPointer(), new_bytecode_offset);
392
393   // TODO(rmcilroy): Create a code target dispatch table to avoid conversion
394   // from code object on every dispatch.
395   Node* target_code_object = raw_assembler_->Load(
396       kMachPtr, DispatchTableRawPointer(),
397       raw_assembler_->Word32Shl(target_bytecode,
398                                 Int32Constant(kPointerSizeLog2)));
399
400   // If the order of the parameters you need to change the call signature below.
401   STATIC_ASSERT(0 == Linkage::kInterpreterAccumulatorParameter);
402   STATIC_ASSERT(1 == Linkage::kInterpreterRegisterFileParameter);
403   STATIC_ASSERT(2 == Linkage::kInterpreterBytecodeOffsetParameter);
404   STATIC_ASSERT(3 == Linkage::kInterpreterBytecodeArrayParameter);
405   STATIC_ASSERT(4 == Linkage::kInterpreterDispatchTableParameter);
406   STATIC_ASSERT(5 == Linkage::kInterpreterContextParameter);
407   Node* args[] = { GetAccumulator(),
408                    RegisterFileRawPointer(),
409                    new_bytecode_offset,
410                    BytecodeArrayTaggedPointer(),
411                    DispatchTableRawPointer(),
412                    ContextTaggedPointer() };
413   Node* tail_call =
414       raw_assembler_->TailCallN(call_descriptor(), target_code_object, args);
415   // This should always be the end node.
416   AddEndInput(tail_call);
417 }
418
419
420 void InterpreterAssembler::AddEndInput(Node* input) {
421   DCHECK_NOT_NULL(input);
422   end_nodes_.push_back(input);
423 }
424
425
426 void InterpreterAssembler::End() {
427   DCHECK(!end_nodes_.empty());
428   int end_count = static_cast<int>(end_nodes_.size());
429   Node* end = graph()->NewNode(raw_assembler_->common()->End(end_count),
430                                end_count, &end_nodes_[0]);
431   graph()->SetEnd(end);
432 }
433
434
435 // RawMachineAssembler delegate helpers:
436 Isolate* InterpreterAssembler::isolate() { return raw_assembler_->isolate(); }
437
438
439 Graph* InterpreterAssembler::graph() { return raw_assembler_->graph(); }
440
441
442 CallDescriptor* InterpreterAssembler::call_descriptor() const {
443   return raw_assembler_->call_descriptor();
444 }
445
446
447 Schedule* InterpreterAssembler::schedule() {
448   return raw_assembler_->schedule();
449 }
450
451
452 Zone* InterpreterAssembler::zone() { return raw_assembler_->zone(); }
453
454
455 }  // namespace compiler
456 }  // namespace internal
457 }  // namespace v8