OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_COMPILER_RAW_MACHINE_ASSEMBLER_H_ | 5 #ifndef V8_COMPILER_RAW_MACHINE_ASSEMBLER_H_ |
6 #define V8_COMPILER_RAW_MACHINE_ASSEMBLER_H_ | 6 #define V8_COMPILER_RAW_MACHINE_ASSEMBLER_H_ |
7 | 7 |
| 8 #ifdef USE_SIMULATOR |
| 9 #define MACHINE_ASSEMBLER_SUPPORTS_CALL_C 0 |
| 10 #else |
| 11 #define MACHINE_ASSEMBLER_SUPPORTS_CALL_C 1 |
| 12 #endif |
| 13 |
8 #include "src/v8.h" | 14 #include "src/v8.h" |
9 | 15 |
10 #include "src/compiler/common-operator.h" | 16 #include "src/compiler/common-operator.h" |
11 #include "src/compiler/graph-builder.h" | 17 #include "src/compiler/graph-builder.h" |
12 #include "src/compiler/machine-node-factory.h" | |
13 #include "src/compiler/machine-operator.h" | 18 #include "src/compiler/machine-operator.h" |
14 #include "src/compiler/node.h" | 19 #include "src/compiler/node.h" |
15 #include "src/compiler/operator.h" | 20 #include "src/compiler/operator.h" |
16 | 21 |
17 | 22 |
18 namespace v8 { | 23 namespace v8 { |
19 namespace internal { | 24 namespace internal { |
20 namespace compiler { | 25 namespace compiler { |
21 | 26 |
22 class BasicBlock; | 27 class BasicBlock; |
23 class Schedule; | 28 class Schedule; |
24 | 29 |
25 | 30 |
26 class RawMachineAssembler : public GraphBuilder, | 31 class RawMachineAssembler : public GraphBuilder { |
27 public MachineNodeFactory<RawMachineAssembler> { | |
28 public: | 32 public: |
29 class Label { | 33 class Label { |
30 public: | 34 public: |
31 Label() : block_(NULL), used_(false), bound_(false) {} | 35 Label() : block_(NULL), used_(false), bound_(false) {} |
32 ~Label() { DCHECK(bound_ || !used_); } | 36 ~Label() { DCHECK(bound_ || !used_); } |
33 | 37 |
34 BasicBlock* block() { return block_; } | 38 BasicBlock* block() { return block_; } |
35 | 39 |
36 private: | 40 private: |
37 // Private constructor for exit label. | 41 // Private constructor for exit label. |
(...skipping 18 matching lines...) Expand all Loading... |
56 CallDescriptor* call_descriptor() const { return call_descriptor_; } | 60 CallDescriptor* call_descriptor() const { return call_descriptor_; } |
57 size_t parameter_count() const { return machine_sig_->parameter_count(); } | 61 size_t parameter_count() const { return machine_sig_->parameter_count(); } |
58 MachineSignature* machine_sig() const { return machine_sig_; } | 62 MachineSignature* machine_sig() const { return machine_sig_; } |
59 | 63 |
60 Node* UndefinedConstant() { | 64 Node* UndefinedConstant() { |
61 Unique<Object> unique = Unique<Object>::CreateImmovable( | 65 Unique<Object> unique = Unique<Object>::CreateImmovable( |
62 isolate()->factory()->undefined_value()); | 66 isolate()->factory()->undefined_value()); |
63 return NewNode(common()->HeapConstant(unique)); | 67 return NewNode(common()->HeapConstant(unique)); |
64 } | 68 } |
65 | 69 |
| 70 // Constants. |
| 71 Node* PointerConstant(void* value) { |
| 72 return IntPtrConstant(reinterpret_cast<intptr_t>(value)); |
| 73 } |
| 74 Node* IntPtrConstant(intptr_t value) { |
| 75 // TODO(dcarney): mark generated code as unserializable if value != 0. |
| 76 return kPointerSize == 8 ? Int64Constant(value) |
| 77 : Int32Constant(static_cast<int>(value)); |
| 78 } |
| 79 Node* Int32Constant(int32_t value) { |
| 80 return NewNode(common()->Int32Constant(value)); |
| 81 } |
| 82 Node* Int64Constant(int64_t value) { |
| 83 return NewNode(common()->Int64Constant(value)); |
| 84 } |
| 85 Node* NumberConstant(double value) { |
| 86 return NewNode(common()->NumberConstant(value)); |
| 87 } |
| 88 Node* Float64Constant(double value) { |
| 89 return NewNode(common()->Float64Constant(value)); |
| 90 } |
| 91 Node* HeapConstant(Handle<Object> object) { |
| 92 Unique<Object> val = Unique<Object>::CreateUninitialized(object); |
| 93 return NewNode(common()->HeapConstant(val)); |
| 94 } |
| 95 |
| 96 Node* Projection(int index, Node* a) { |
| 97 return NewNode(common()->Projection(index), a); |
| 98 } |
| 99 |
| 100 // Memory Operations. |
| 101 Node* Load(MachineType rep, Node* base) { |
| 102 return Load(rep, base, Int32Constant(0)); |
| 103 } |
| 104 Node* Load(MachineType rep, Node* base, Node* index) { |
| 105 return NewNode(machine()->Load(rep), base, index); |
| 106 } |
| 107 void Store(MachineType rep, Node* base, Node* value) { |
| 108 Store(rep, base, Int32Constant(0), value); |
| 109 } |
| 110 void Store(MachineType rep, Node* base, Node* index, Node* value) { |
| 111 NewNode(machine()->Store(rep, kNoWriteBarrier), base, index, value); |
| 112 } |
| 113 // Arithmetic Operations. |
| 114 Node* WordAnd(Node* a, Node* b) { |
| 115 return NewNode(machine()->WordAnd(), a, b); |
| 116 } |
| 117 Node* WordOr(Node* a, Node* b) { return NewNode(machine()->WordOr(), a, b); } |
| 118 Node* WordXor(Node* a, Node* b) { |
| 119 return NewNode(machine()->WordXor(), a, b); |
| 120 } |
| 121 Node* WordShl(Node* a, Node* b) { |
| 122 return NewNode(machine()->WordShl(), a, b); |
| 123 } |
| 124 Node* WordShr(Node* a, Node* b) { |
| 125 return NewNode(machine()->WordShr(), a, b); |
| 126 } |
| 127 Node* WordSar(Node* a, Node* b) { |
| 128 return NewNode(machine()->WordSar(), a, b); |
| 129 } |
| 130 Node* WordRor(Node* a, Node* b) { |
| 131 return NewNode(machine()->WordRor(), a, b); |
| 132 } |
| 133 Node* WordEqual(Node* a, Node* b) { |
| 134 return NewNode(machine()->WordEqual(), a, b); |
| 135 } |
| 136 Node* WordNotEqual(Node* a, Node* b) { |
| 137 return WordBinaryNot(WordEqual(a, b)); |
| 138 } |
| 139 Node* WordNot(Node* a) { |
| 140 if (machine()->is32()) { |
| 141 return Word32Not(a); |
| 142 } else { |
| 143 return Word64Not(a); |
| 144 } |
| 145 } |
| 146 Node* WordBinaryNot(Node* a) { |
| 147 if (machine()->is32()) { |
| 148 return Word32BinaryNot(a); |
| 149 } else { |
| 150 return Word64BinaryNot(a); |
| 151 } |
| 152 } |
| 153 |
| 154 Node* Word32And(Node* a, Node* b) { |
| 155 return NewNode(machine()->Word32And(), a, b); |
| 156 } |
| 157 Node* Word32Or(Node* a, Node* b) { |
| 158 return NewNode(machine()->Word32Or(), a, b); |
| 159 } |
| 160 Node* Word32Xor(Node* a, Node* b) { |
| 161 return NewNode(machine()->Word32Xor(), a, b); |
| 162 } |
| 163 Node* Word32Shl(Node* a, Node* b) { |
| 164 return NewNode(machine()->Word32Shl(), a, b); |
| 165 } |
| 166 Node* Word32Shr(Node* a, Node* b) { |
| 167 return NewNode(machine()->Word32Shr(), a, b); |
| 168 } |
| 169 Node* Word32Sar(Node* a, Node* b) { |
| 170 return NewNode(machine()->Word32Sar(), a, b); |
| 171 } |
| 172 Node* Word32Ror(Node* a, Node* b) { |
| 173 return NewNode(machine()->Word32Ror(), a, b); |
| 174 } |
| 175 Node* Word32Equal(Node* a, Node* b) { |
| 176 return NewNode(machine()->Word32Equal(), a, b); |
| 177 } |
| 178 Node* Word32NotEqual(Node* a, Node* b) { |
| 179 return Word32BinaryNot(Word32Equal(a, b)); |
| 180 } |
| 181 Node* Word32Not(Node* a) { return Word32Xor(a, Int32Constant(-1)); } |
| 182 Node* Word32BinaryNot(Node* a) { return Word32Equal(a, Int32Constant(0)); } |
| 183 |
| 184 Node* Word64And(Node* a, Node* b) { |
| 185 return NewNode(machine()->Word64And(), a, b); |
| 186 } |
| 187 Node* Word64Or(Node* a, Node* b) { |
| 188 return NewNode(machine()->Word64Or(), a, b); |
| 189 } |
| 190 Node* Word64Xor(Node* a, Node* b) { |
| 191 return NewNode(machine()->Word64Xor(), a, b); |
| 192 } |
| 193 Node* Word64Shl(Node* a, Node* b) { |
| 194 return NewNode(machine()->Word64Shl(), a, b); |
| 195 } |
| 196 Node* Word64Shr(Node* a, Node* b) { |
| 197 return NewNode(machine()->Word64Shr(), a, b); |
| 198 } |
| 199 Node* Word64Sar(Node* a, Node* b) { |
| 200 return NewNode(machine()->Word64Sar(), a, b); |
| 201 } |
| 202 Node* Word64Ror(Node* a, Node* b) { |
| 203 return NewNode(machine()->Word64Ror(), a, b); |
| 204 } |
| 205 Node* Word64Equal(Node* a, Node* b) { |
| 206 return NewNode(machine()->Word64Equal(), a, b); |
| 207 } |
| 208 Node* Word64NotEqual(Node* a, Node* b) { |
| 209 return Word64BinaryNot(Word64Equal(a, b)); |
| 210 } |
| 211 Node* Word64Not(Node* a) { return Word64Xor(a, Int64Constant(-1)); } |
| 212 Node* Word64BinaryNot(Node* a) { return Word64Equal(a, Int64Constant(0)); } |
| 213 |
| 214 Node* Int32Add(Node* a, Node* b) { |
| 215 return NewNode(machine()->Int32Add(), a, b); |
| 216 } |
| 217 Node* Int32AddWithOverflow(Node* a, Node* b) { |
| 218 return NewNode(machine()->Int32AddWithOverflow(), a, b); |
| 219 } |
| 220 Node* Int32Sub(Node* a, Node* b) { |
| 221 return NewNode(machine()->Int32Sub(), a, b); |
| 222 } |
| 223 Node* Int32SubWithOverflow(Node* a, Node* b) { |
| 224 return NewNode(machine()->Int32SubWithOverflow(), a, b); |
| 225 } |
| 226 Node* Int32Mul(Node* a, Node* b) { |
| 227 return NewNode(machine()->Int32Mul(), a, b); |
| 228 } |
| 229 Node* Int32Div(Node* a, Node* b) { |
| 230 return NewNode(machine()->Int32Div(), a, b); |
| 231 } |
| 232 Node* Int32UDiv(Node* a, Node* b) { |
| 233 return NewNode(machine()->Int32UDiv(), a, b); |
| 234 } |
| 235 Node* Int32Mod(Node* a, Node* b) { |
| 236 return NewNode(machine()->Int32Mod(), a, b); |
| 237 } |
| 238 Node* Int32UMod(Node* a, Node* b) { |
| 239 return NewNode(machine()->Int32UMod(), a, b); |
| 240 } |
| 241 Node* Int32LessThan(Node* a, Node* b) { |
| 242 return NewNode(machine()->Int32LessThan(), a, b); |
| 243 } |
| 244 Node* Int32LessThanOrEqual(Node* a, Node* b) { |
| 245 return NewNode(machine()->Int32LessThanOrEqual(), a, b); |
| 246 } |
| 247 Node* Uint32LessThan(Node* a, Node* b) { |
| 248 return NewNode(machine()->Uint32LessThan(), a, b); |
| 249 } |
| 250 Node* Uint32LessThanOrEqual(Node* a, Node* b) { |
| 251 return NewNode(machine()->Uint32LessThanOrEqual(), a, b); |
| 252 } |
| 253 Node* Int32GreaterThan(Node* a, Node* b) { return Int32LessThan(b, a); } |
| 254 Node* Int32GreaterThanOrEqual(Node* a, Node* b) { |
| 255 return Int32LessThanOrEqual(b, a); |
| 256 } |
| 257 Node* Int32Neg(Node* a) { return Int32Sub(Int32Constant(0), a); } |
| 258 |
| 259 Node* Int64Add(Node* a, Node* b) { |
| 260 return NewNode(machine()->Int64Add(), a, b); |
| 261 } |
| 262 Node* Int64Sub(Node* a, Node* b) { |
| 263 return NewNode(machine()->Int64Sub(), a, b); |
| 264 } |
| 265 Node* Int64Mul(Node* a, Node* b) { |
| 266 return NewNode(machine()->Int64Mul(), a, b); |
| 267 } |
| 268 Node* Int64Div(Node* a, Node* b) { |
| 269 return NewNode(machine()->Int64Div(), a, b); |
| 270 } |
| 271 Node* Int64UDiv(Node* a, Node* b) { |
| 272 return NewNode(machine()->Int64UDiv(), a, b); |
| 273 } |
| 274 Node* Int64Mod(Node* a, Node* b) { |
| 275 return NewNode(machine()->Int64Mod(), a, b); |
| 276 } |
| 277 Node* Int64UMod(Node* a, Node* b) { |
| 278 return NewNode(machine()->Int64UMod(), a, b); |
| 279 } |
| 280 Node* Int64Neg(Node* a) { return Int64Sub(Int64Constant(0), a); } |
| 281 Node* Int64LessThan(Node* a, Node* b) { |
| 282 return NewNode(machine()->Int64LessThan(), a, b); |
| 283 } |
| 284 Node* Int64LessThanOrEqual(Node* a, Node* b) { |
| 285 return NewNode(machine()->Int64LessThanOrEqual(), a, b); |
| 286 } |
| 287 Node* Int64GreaterThan(Node* a, Node* b) { return Int64LessThan(b, a); } |
| 288 Node* Int64GreaterThanOrEqual(Node* a, Node* b) { |
| 289 return Int64LessThanOrEqual(b, a); |
| 290 } |
| 291 |
| 292 // TODO(turbofan): What is this used for? |
| 293 Node* ConvertIntPtrToInt32(Node* a) { |
| 294 return kPointerSize == 8 ? NewNode(machine()->TruncateInt64ToInt32(), a) |
| 295 : a; |
| 296 } |
| 297 Node* ConvertInt32ToIntPtr(Node* a) { |
| 298 return kPointerSize == 8 ? NewNode(machine()->ChangeInt32ToInt64(), a) : a; |
| 299 } |
| 300 |
| 301 #define INTPTR_BINOP(prefix, name) \ |
| 302 Node* IntPtr##name(Node* a, Node* b) { \ |
| 303 return kPointerSize == 8 ? prefix##64##name(a, b) \ |
| 304 : prefix##32##name(a, b); \ |
| 305 } |
| 306 |
| 307 INTPTR_BINOP(Int, Add); |
| 308 INTPTR_BINOP(Int, Sub); |
| 309 INTPTR_BINOP(Int, LessThan); |
| 310 INTPTR_BINOP(Int, LessThanOrEqual); |
| 311 INTPTR_BINOP(Word, Equal); |
| 312 INTPTR_BINOP(Word, NotEqual); |
| 313 INTPTR_BINOP(Int, GreaterThanOrEqual); |
| 314 INTPTR_BINOP(Int, GreaterThan); |
| 315 |
| 316 #undef INTPTR_BINOP |
| 317 |
| 318 Node* Float64Add(Node* a, Node* b) { |
| 319 return NewNode(machine()->Float64Add(), a, b); |
| 320 } |
| 321 Node* Float64Sub(Node* a, Node* b) { |
| 322 return NewNode(machine()->Float64Sub(), a, b); |
| 323 } |
| 324 Node* Float64Mul(Node* a, Node* b) { |
| 325 return NewNode(machine()->Float64Mul(), a, b); |
| 326 } |
| 327 Node* Float64Div(Node* a, Node* b) { |
| 328 return NewNode(machine()->Float64Div(), a, b); |
| 329 } |
| 330 Node* Float64Mod(Node* a, Node* b) { |
| 331 return NewNode(machine()->Float64Mod(), a, b); |
| 332 } |
| 333 Node* Float64Equal(Node* a, Node* b) { |
| 334 return NewNode(machine()->Float64Equal(), a, b); |
| 335 } |
| 336 Node* Float64NotEqual(Node* a, Node* b) { |
| 337 return WordBinaryNot(Float64Equal(a, b)); |
| 338 } |
| 339 Node* Float64LessThan(Node* a, Node* b) { |
| 340 return NewNode(machine()->Float64LessThan(), a, b); |
| 341 } |
| 342 Node* Float64LessThanOrEqual(Node* a, Node* b) { |
| 343 return NewNode(machine()->Float64LessThanOrEqual(), a, b); |
| 344 } |
| 345 Node* Float64GreaterThan(Node* a, Node* b) { return Float64LessThan(b, a); } |
| 346 Node* Float64GreaterThanOrEqual(Node* a, Node* b) { |
| 347 return Float64LessThanOrEqual(b, a); |
| 348 } |
| 349 |
| 350 // Conversions. |
| 351 Node* ChangeInt32ToFloat64(Node* a) { |
| 352 return NewNode(machine()->ChangeInt32ToFloat64(), a); |
| 353 } |
| 354 Node* ChangeUint32ToFloat64(Node* a) { |
| 355 return NewNode(machine()->ChangeUint32ToFloat64(), a); |
| 356 } |
| 357 Node* ChangeFloat64ToInt32(Node* a) { |
| 358 return NewNode(machine()->ChangeFloat64ToInt32(), a); |
| 359 } |
| 360 Node* ChangeFloat64ToUint32(Node* a) { |
| 361 return NewNode(machine()->ChangeFloat64ToUint32(), a); |
| 362 } |
| 363 Node* ChangeInt32ToInt64(Node* a) { |
| 364 return NewNode(machine()->ChangeInt32ToInt64(), a); |
| 365 } |
| 366 Node* ChangeUint32ToUint64(Node* a) { |
| 367 return NewNode(machine()->ChangeUint32ToUint64(), a); |
| 368 } |
| 369 Node* TruncateFloat64ToInt32(Node* a) { |
| 370 return NewNode(machine()->TruncateFloat64ToInt32(), a); |
| 371 } |
| 372 Node* TruncateInt64ToInt32(Node* a) { |
| 373 return NewNode(machine()->TruncateInt64ToInt32(), a); |
| 374 } |
| 375 |
| 376 #ifdef MACHINE_ASSEMBLER_SUPPORTS_CALL_C |
| 377 // Call to C. |
| 378 Node* CallC(Node* function_address, MachineType return_type, |
| 379 MachineType* arg_types, Node** args, int n_args) { |
| 380 CallDescriptor* descriptor = |
| 381 Linkage::GetSimplifiedCDescriptor(zone(), machine_sig()); |
| 382 Node** passed_args = zone()->NewArray<Node*>(n_args + 1); |
| 383 passed_args[0] = function_address; |
| 384 for (int i = 0; i < n_args; ++i) { |
| 385 passed_args[i + 1] = args[i]; |
| 386 } |
| 387 return NewNode(common()->Call(descriptor), n_args + 1, passed_args); |
| 388 } |
| 389 #endif |
| 390 |
66 // Parameters. | 391 // Parameters. |
67 Node* Parameter(size_t index); | 392 Node* Parameter(size_t index); |
68 | 393 |
69 // Control flow. | 394 // Control flow. |
70 Label* Exit(); | 395 Label* Exit(); |
71 void Goto(Label* label); | 396 void Goto(Label* label); |
72 void Branch(Node* condition, Label* true_val, Label* false_val); | 397 void Branch(Node* condition, Label* true_val, Label* false_val); |
73 // Call through CallFunctionStub with lazy deopt and frame-state. | 398 // Call through CallFunctionStub with lazy deopt and frame-state. |
74 Node* CallFunctionStub0(Node* function, Node* receiver, Node* context, | 399 Node* CallFunctionStub0(Node* function, Node* receiver, Node* context, |
75 Node* frame_state, CallFunctionFlags flags); | 400 Node* frame_state, CallFunctionFlags flags); |
(...skipping 15 matching lines...) Expand all Loading... |
91 Node* Phi(Node* n1, Node* n2, Node* n3, Node* n4) { | 416 Node* Phi(Node* n1, Node* n2, Node* n3, Node* n4) { |
92 return NewNode(common()->Phi(4), n1, n2, n3, n4); | 417 return NewNode(common()->Phi(4), n1, n2, n3, n4); |
93 } | 418 } |
94 | 419 |
95 // MachineAssembler is invalid after export. | 420 // MachineAssembler is invalid after export. |
96 Schedule* Export(); | 421 Schedule* Export(); |
97 | 422 |
98 protected: | 423 protected: |
99 virtual Node* MakeNode(Operator* op, int input_count, Node** inputs); | 424 virtual Node* MakeNode(Operator* op, int input_count, Node** inputs); |
100 | 425 |
| 426 bool ScheduleValid() { return schedule_ != NULL; } |
| 427 |
101 Schedule* schedule() { | 428 Schedule* schedule() { |
102 DCHECK(ScheduleValid()); | 429 DCHECK(ScheduleValid()); |
103 return schedule_; | 430 return schedule_; |
104 } | 431 } |
105 | 432 |
106 private: | 433 private: |
107 bool ScheduleValid() { return schedule_ != NULL; } | |
108 | |
109 BasicBlock* Use(Label* label); | 434 BasicBlock* Use(Label* label); |
110 BasicBlock* EnsureBlock(Label* label); | 435 BasicBlock* EnsureBlock(Label* label); |
111 BasicBlock* CurrentBlock(); | 436 BasicBlock* CurrentBlock(); |
112 | 437 |
113 Schedule* schedule_; | 438 Schedule* schedule_; |
114 MachineOperatorBuilder machine_; | 439 MachineOperatorBuilder machine_; |
115 CommonOperatorBuilder common_; | 440 CommonOperatorBuilder common_; |
116 MachineSignature* machine_sig_; | 441 MachineSignature* machine_sig_; |
117 CallDescriptor* call_descriptor_; | 442 CallDescriptor* call_descriptor_; |
118 Node** parameters_; | 443 Node** parameters_; |
119 Label exit_label_; | 444 Label exit_label_; |
120 BasicBlock* current_block_; | 445 BasicBlock* current_block_; |
121 | 446 |
122 DISALLOW_COPY_AND_ASSIGN(RawMachineAssembler); | 447 DISALLOW_COPY_AND_ASSIGN(RawMachineAssembler); |
123 }; | 448 }; |
124 | 449 |
125 } // namespace compiler | 450 } // namespace compiler |
126 } // namespace internal | 451 } // namespace internal |
127 } // namespace v8 | 452 } // namespace v8 |
128 | 453 |
129 #endif // V8_COMPILER_RAW_MACHINE_ASSEMBLER_H_ | 454 #endif // V8_COMPILER_RAW_MACHINE_ASSEMBLER_H_ |
OLD | NEW |