OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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_IA32_LITHIUM_CODEGEN_IA32_H_ | 5 #ifndef V8_IA32_LITHIUM_CODEGEN_IA32_H_ |
6 #define V8_IA32_LITHIUM_CODEGEN_IA32_H_ | 6 #define V8_IA32_LITHIUM_CODEGEN_IA32_H_ |
7 | 7 |
8 #include "ia32/lithium-ia32.h" | 8 #include "ia32/lithium-ia32.h" |
9 | 9 |
10 #include "checks.h" | 10 #include "checks.h" |
(...skipping 20 matching lines...) Expand all Loading... |
31 jump_table_(4, info->zone()), | 31 jump_table_(4, info->zone()), |
32 deoptimization_literals_(8, info->zone()), | 32 deoptimization_literals_(8, info->zone()), |
33 inlined_function_count_(0), | 33 inlined_function_count_(0), |
34 scope_(info->scope()), | 34 scope_(info->scope()), |
35 translations_(info->zone()), | 35 translations_(info->zone()), |
36 deferred_(8, info->zone()), | 36 deferred_(8, info->zone()), |
37 dynamic_frame_alignment_(false), | 37 dynamic_frame_alignment_(false), |
38 support_aligned_spilled_doubles_(false), | 38 support_aligned_spilled_doubles_(false), |
39 osr_pc_offset_(-1), | 39 osr_pc_offset_(-1), |
40 frame_is_built_(false), | 40 frame_is_built_(false), |
41 x87_stack_(assembler), | |
42 safepoints_(info->zone()), | 41 safepoints_(info->zone()), |
43 resolver_(this), | 42 resolver_(this), |
44 expected_safepoint_kind_(Safepoint::kSimple) { | 43 expected_safepoint_kind_(Safepoint::kSimple) { |
45 PopulateDeoptimizationLiteralsWithInlinedFunctions(); | 44 PopulateDeoptimizationLiteralsWithInlinedFunctions(); |
46 } | 45 } |
47 | 46 |
48 int LookupDestination(int block_id) const { | 47 int LookupDestination(int block_id) const { |
49 return chunk()->LookupDestination(block_id); | 48 return chunk()->LookupDestination(block_id); |
50 } | 49 } |
51 | 50 |
52 bool IsNextEmittedBlock(int block_id) const { | 51 bool IsNextEmittedBlock(int block_id) const { |
53 return LookupDestination(block_id) == GetNextEmittedBlock(); | 52 return LookupDestination(block_id) == GetNextEmittedBlock(); |
54 } | 53 } |
55 | 54 |
56 bool NeedsEagerFrame() const { | 55 bool NeedsEagerFrame() const { |
57 return GetStackSlotCount() > 0 || | 56 return GetStackSlotCount() > 0 || |
58 info()->is_non_deferred_calling() || | 57 info()->is_non_deferred_calling() || |
59 !info()->IsStub() || | 58 !info()->IsStub() || |
60 info()->requires_frame(); | 59 info()->requires_frame(); |
61 } | 60 } |
62 bool NeedsDeferredFrame() const { | 61 bool NeedsDeferredFrame() const { |
63 return !NeedsEagerFrame() && info()->is_deferred_calling(); | 62 return !NeedsEagerFrame() && info()->is_deferred_calling(); |
64 } | 63 } |
65 | 64 |
66 // Support for converting LOperands to assembler types. | 65 // Support for converting LOperands to assembler types. |
67 Operand ToOperand(LOperand* op) const; | 66 Operand ToOperand(LOperand* op) const; |
68 Register ToRegister(LOperand* op) const; | 67 Register ToRegister(LOperand* op) const; |
69 XMMRegister ToDoubleRegister(LOperand* op) const; | 68 XMMRegister ToDoubleRegister(LOperand* op) const; |
70 X87Register ToX87Register(LOperand* op) const; | |
71 | 69 |
72 bool IsInteger32(LConstantOperand* op) const; | 70 bool IsInteger32(LConstantOperand* op) const; |
73 bool IsSmi(LConstantOperand* op) const; | 71 bool IsSmi(LConstantOperand* op) const; |
74 Immediate ToImmediate(LOperand* op, const Representation& r) const { | 72 Immediate ToImmediate(LOperand* op, const Representation& r) const { |
75 return Immediate(ToRepresentation(LConstantOperand::cast(op), r)); | 73 return Immediate(ToRepresentation(LConstantOperand::cast(op), r)); |
76 } | 74 } |
77 double ToDouble(LConstantOperand* op) const; | 75 double ToDouble(LConstantOperand* op) const; |
78 | 76 |
79 // Support for non-sse2 (x87) floating point stack handling. | |
80 // These functions maintain the mapping of physical stack registers to our | |
81 // virtual registers between instructions. | |
82 enum X87OperandType { kX87DoubleOperand, kX87FloatOperand, kX87IntOperand }; | |
83 | |
84 void X87Mov(X87Register reg, Operand src, | |
85 X87OperandType operand = kX87DoubleOperand); | |
86 void X87Mov(Operand src, X87Register reg, | |
87 X87OperandType operand = kX87DoubleOperand); | |
88 | |
89 void X87PrepareBinaryOp( | |
90 X87Register left, X87Register right, X87Register result); | |
91 | |
92 void X87LoadForUsage(X87Register reg); | |
93 void X87LoadForUsage(X87Register reg1, X87Register reg2); | |
94 void X87PrepareToWrite(X87Register reg) { x87_stack_.PrepareToWrite(reg); } | |
95 void X87CommitWrite(X87Register reg) { x87_stack_.CommitWrite(reg); } | |
96 | |
97 void X87Fxch(X87Register reg, int other_slot = 0) { | |
98 x87_stack_.Fxch(reg, other_slot); | |
99 } | |
100 void X87Free(X87Register reg) { | |
101 x87_stack_.Free(reg); | |
102 } | |
103 | |
104 | |
105 bool X87StackEmpty() { | |
106 return x87_stack_.depth() == 0; | |
107 } | |
108 | |
109 Handle<Object> ToHandle(LConstantOperand* op) const; | 77 Handle<Object> ToHandle(LConstantOperand* op) const; |
110 | 78 |
111 // The operand denoting the second word (the one with a higher address) of | 79 // The operand denoting the second word (the one with a higher address) of |
112 // a double stack slot. | 80 // a double stack slot. |
113 Operand HighOperand(LOperand* op); | 81 Operand HighOperand(LOperand* op); |
114 | 82 |
115 // Try to generate code for the entire chunk, but it may fail if the | 83 // Try to generate code for the entire chunk, but it may fail if the |
116 // chunk contains constructs we cannot handle. Returns true if the | 84 // chunk contains constructs we cannot handle. Returns true if the |
117 // code generation attempt succeeded. | 85 // code generation attempt succeeded. |
118 bool GenerateCode(); | 86 bool GenerateCode(); |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
258 bool is_uint32, | 226 bool is_uint32, |
259 int* object_index_pointer, | 227 int* object_index_pointer, |
260 int* dematerialized_index_pointer); | 228 int* dematerialized_index_pointer); |
261 void PopulateDeoptimizationData(Handle<Code> code); | 229 void PopulateDeoptimizationData(Handle<Code> code); |
262 int DefineDeoptimizationLiteral(Handle<Object> literal); | 230 int DefineDeoptimizationLiteral(Handle<Object> literal); |
263 | 231 |
264 void PopulateDeoptimizationLiteralsWithInlinedFunctions(); | 232 void PopulateDeoptimizationLiteralsWithInlinedFunctions(); |
265 | 233 |
266 Register ToRegister(int index) const; | 234 Register ToRegister(int index) const; |
267 XMMRegister ToDoubleRegister(int index) const; | 235 XMMRegister ToDoubleRegister(int index) const; |
268 X87Register ToX87Register(int index) const; | |
269 int32_t ToRepresentation(LConstantOperand* op, const Representation& r) const; | 236 int32_t ToRepresentation(LConstantOperand* op, const Representation& r) const; |
270 int32_t ToInteger32(LConstantOperand* op) const; | 237 int32_t ToInteger32(LConstantOperand* op) const; |
271 ExternalReference ToExternalReference(LConstantOperand* op) const; | 238 ExternalReference ToExternalReference(LConstantOperand* op) const; |
272 | 239 |
273 Operand BuildFastArrayOperand(LOperand* elements_pointer, | 240 Operand BuildFastArrayOperand(LOperand* elements_pointer, |
274 LOperand* key, | 241 LOperand* key, |
275 Representation key_representation, | 242 Representation key_representation, |
276 ElementsKind elements_kind, | 243 ElementsKind elements_kind, |
277 uint32_t offset, | 244 uint32_t offset, |
278 uint32_t additional_index = 0); | 245 uint32_t additional_index = 0); |
(...skipping 27 matching lines...) Expand all Loading... |
306 void EmitFalseBranch(InstrType instr, Condition cc); | 273 void EmitFalseBranch(InstrType instr, Condition cc); |
307 void EmitNumberUntagD( | 274 void EmitNumberUntagD( |
308 Register input, | 275 Register input, |
309 Register temp, | 276 Register temp, |
310 XMMRegister result, | 277 XMMRegister result, |
311 bool allow_undefined_as_nan, | 278 bool allow_undefined_as_nan, |
312 bool deoptimize_on_minus_zero, | 279 bool deoptimize_on_minus_zero, |
313 LEnvironment* env, | 280 LEnvironment* env, |
314 NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED); | 281 NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED); |
315 | 282 |
316 void EmitNumberUntagDNoSSE2( | |
317 Register input, | |
318 Register temp, | |
319 X87Register res_reg, | |
320 bool allow_undefined_as_nan, | |
321 bool deoptimize_on_minus_zero, | |
322 LEnvironment* env, | |
323 NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED); | |
324 | |
325 // Emits optimized code for typeof x == "y". Modifies input register. | 283 // Emits optimized code for typeof x == "y". Modifies input register. |
326 // Returns the condition on which a final split to | 284 // Returns the condition on which a final split to |
327 // true and false label should be made, to optimize fallthrough. | 285 // true and false label should be made, to optimize fallthrough. |
328 Condition EmitTypeofIs(LTypeofIsAndBranch* instr, Register input); | 286 Condition EmitTypeofIs(LTypeofIsAndBranch* instr, Register input); |
329 | 287 |
330 // Emits optimized code for %_IsObject(x). Preserves input register. | 288 // Emits optimized code for %_IsObject(x). Preserves input register. |
331 // Returns the condition on which a final split to | 289 // Returns the condition on which a final split to |
332 // true and false label should be made, to optimize fallthrough. | 290 // true and false label should be made, to optimize fallthrough. |
333 Condition EmitIsObject(Register input, | 291 Condition EmitIsObject(Register input, |
334 Register temp1, | 292 Register temp1, |
(...skipping 27 matching lines...) Expand all Loading... |
362 void DoStoreKeyedExternalArray(LStoreKeyed* instr); | 320 void DoStoreKeyedExternalArray(LStoreKeyed* instr); |
363 void DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr); | 321 void DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr); |
364 void DoStoreKeyedFixedArray(LStoreKeyed* instr); | 322 void DoStoreKeyedFixedArray(LStoreKeyed* instr); |
365 | 323 |
366 void EmitReturn(LReturn* instr, bool dynamic_frame_alignment); | 324 void EmitReturn(LReturn* instr, bool dynamic_frame_alignment); |
367 | 325 |
368 // Emits code for pushing either a tagged constant, a (non-double) | 326 // Emits code for pushing either a tagged constant, a (non-double) |
369 // register, or a stack slot operand. | 327 // register, or a stack slot operand. |
370 void EmitPushTaggedOperand(LOperand* operand); | 328 void EmitPushTaggedOperand(LOperand* operand); |
371 | 329 |
372 void X87Fld(Operand src, X87OperandType opts); | |
373 | |
374 void EmitFlushX87ForDeopt(); | |
375 void FlushX87StackIfNecessary(LInstruction* instr) { | |
376 x87_stack_.FlushIfNecessary(instr, this); | |
377 } | |
378 friend class LGapResolver; | 330 friend class LGapResolver; |
379 | 331 |
380 #ifdef _MSC_VER | 332 #ifdef _MSC_VER |
381 // On windows, you may not access the stack more than one page below | 333 // On windows, you may not access the stack more than one page below |
382 // the most recently mapped page. To make the allocated area randomly | 334 // the most recently mapped page. To make the allocated area randomly |
383 // accessible, we write an arbitrary value to each page in range | 335 // accessible, we write an arbitrary value to each page in range |
384 // esp + offset - page_size .. esp in turn. | 336 // esp + offset - page_size .. esp in turn. |
385 void MakeSureStackPagesMapped(int offset); | 337 void MakeSureStackPagesMapped(int offset); |
386 #endif | 338 #endif |
387 | 339 |
388 ZoneList<LEnvironment*> deoptimizations_; | 340 ZoneList<LEnvironment*> deoptimizations_; |
389 ZoneList<Deoptimizer::JumpTableEntry> jump_table_; | 341 ZoneList<Deoptimizer::JumpTableEntry> jump_table_; |
390 ZoneList<Handle<Object> > deoptimization_literals_; | 342 ZoneList<Handle<Object> > deoptimization_literals_; |
391 int inlined_function_count_; | 343 int inlined_function_count_; |
392 Scope* const scope_; | 344 Scope* const scope_; |
393 TranslationBuffer translations_; | 345 TranslationBuffer translations_; |
394 ZoneList<LDeferredCode*> deferred_; | 346 ZoneList<LDeferredCode*> deferred_; |
395 bool dynamic_frame_alignment_; | 347 bool dynamic_frame_alignment_; |
396 bool support_aligned_spilled_doubles_; | 348 bool support_aligned_spilled_doubles_; |
397 int osr_pc_offset_; | 349 int osr_pc_offset_; |
398 bool frame_is_built_; | 350 bool frame_is_built_; |
399 | 351 |
400 class X87Stack { | |
401 public: | |
402 explicit X87Stack(MacroAssembler* masm) | |
403 : stack_depth_(0), is_mutable_(true), masm_(masm) { } | |
404 explicit X87Stack(const X87Stack& other) | |
405 : stack_depth_(other.stack_depth_), is_mutable_(false), masm_(masm()) { | |
406 for (int i = 0; i < stack_depth_; i++) { | |
407 stack_[i] = other.stack_[i]; | |
408 } | |
409 } | |
410 bool operator==(const X87Stack& other) const { | |
411 if (stack_depth_ != other.stack_depth_) return false; | |
412 for (int i = 0; i < stack_depth_; i++) { | |
413 if (!stack_[i].is(other.stack_[i])) return false; | |
414 } | |
415 return true; | |
416 } | |
417 bool Contains(X87Register reg); | |
418 void Fxch(X87Register reg, int other_slot = 0); | |
419 void Free(X87Register reg); | |
420 void PrepareToWrite(X87Register reg); | |
421 void CommitWrite(X87Register reg); | |
422 void FlushIfNecessary(LInstruction* instr, LCodeGen* cgen); | |
423 void LeavingBlock(int current_block_id, LGoto* goto_instr); | |
424 int depth() const { return stack_depth_; } | |
425 void pop() { | |
426 ASSERT(is_mutable_); | |
427 stack_depth_--; | |
428 } | |
429 void push(X87Register reg) { | |
430 ASSERT(is_mutable_); | |
431 ASSERT(stack_depth_ < X87Register::kNumAllocatableRegisters); | |
432 stack_[stack_depth_] = reg; | |
433 stack_depth_++; | |
434 } | |
435 | |
436 MacroAssembler* masm() const { return masm_; } | |
437 Isolate* isolate() const { return masm_->isolate(); } | |
438 | |
439 private: | |
440 int ArrayIndex(X87Register reg); | |
441 int st2idx(int pos); | |
442 | |
443 X87Register stack_[X87Register::kNumAllocatableRegisters]; | |
444 int stack_depth_; | |
445 bool is_mutable_; | |
446 MacroAssembler* masm_; | |
447 }; | |
448 X87Stack x87_stack_; | |
449 | |
450 // Builder that keeps track of safepoints in the code. The table | 352 // Builder that keeps track of safepoints in the code. The table |
451 // itself is emitted at the end of the generated code. | 353 // itself is emitted at the end of the generated code. |
452 SafepointTableBuilder safepoints_; | 354 SafepointTableBuilder safepoints_; |
453 | 355 |
454 // Compiler from a set of parallel moves to a sequential list of moves. | 356 // Compiler from a set of parallel moves to a sequential list of moves. |
455 LGapResolver resolver_; | 357 LGapResolver resolver_; |
456 | 358 |
457 Safepoint::Kind expected_safepoint_kind_; | 359 Safepoint::Kind expected_safepoint_kind_; |
458 | 360 |
459 class PushSafepointRegistersScope V8_FINAL BASE_EMBEDDED { | 361 class PushSafepointRegistersScope V8_FINAL BASE_EMBEDDED { |
(...skipping 18 matching lines...) Expand all Loading... |
478 | 380 |
479 friend class LDeferredCode; | 381 friend class LDeferredCode; |
480 friend class LEnvironment; | 382 friend class LEnvironment; |
481 friend class SafepointGenerator; | 383 friend class SafepointGenerator; |
482 DISALLOW_COPY_AND_ASSIGN(LCodeGen); | 384 DISALLOW_COPY_AND_ASSIGN(LCodeGen); |
483 }; | 385 }; |
484 | 386 |
485 | 387 |
486 class LDeferredCode : public ZoneObject { | 388 class LDeferredCode : public ZoneObject { |
487 public: | 389 public: |
488 explicit LDeferredCode(LCodeGen* codegen, const LCodeGen::X87Stack& x87_stack) | 390 explicit LDeferredCode(LCodeGen* codegen) |
489 : codegen_(codegen), | 391 : codegen_(codegen), |
490 external_exit_(NULL), | 392 external_exit_(NULL), |
491 instruction_index_(codegen->current_instruction_), | 393 instruction_index_(codegen->current_instruction_) { |
492 x87_stack_(x87_stack) { | |
493 codegen->AddDeferredCode(this); | 394 codegen->AddDeferredCode(this); |
494 } | 395 } |
495 | 396 |
496 virtual ~LDeferredCode() {} | 397 virtual ~LDeferredCode() {} |
497 virtual void Generate() = 0; | 398 virtual void Generate() = 0; |
498 virtual LInstruction* instr() = 0; | 399 virtual LInstruction* instr() = 0; |
499 | 400 |
500 void SetExit(Label* exit) { external_exit_ = exit; } | 401 void SetExit(Label* exit) { external_exit_ = exit; } |
501 Label* entry() { return &entry_; } | 402 Label* entry() { return &entry_; } |
502 Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; } | 403 Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; } |
503 Label* done() { return codegen_->NeedsDeferredFrame() ? &done_ : exit(); } | 404 Label* done() { return codegen_->NeedsDeferredFrame() ? &done_ : exit(); } |
504 int instruction_index() const { return instruction_index_; } | 405 int instruction_index() const { return instruction_index_; } |
505 const LCodeGen::X87Stack& x87_stack() const { return x87_stack_; } | |
506 | 406 |
507 protected: | 407 protected: |
508 LCodeGen* codegen() const { return codegen_; } | 408 LCodeGen* codegen() const { return codegen_; } |
509 MacroAssembler* masm() const { return codegen_->masm(); } | 409 MacroAssembler* masm() const { return codegen_->masm(); } |
510 | 410 |
511 private: | 411 private: |
512 LCodeGen* codegen_; | 412 LCodeGen* codegen_; |
513 Label entry_; | 413 Label entry_; |
514 Label exit_; | 414 Label exit_; |
515 Label* external_exit_; | 415 Label* external_exit_; |
516 Label done_; | 416 Label done_; |
517 int instruction_index_; | 417 int instruction_index_; |
518 LCodeGen::X87Stack x87_stack_; | |
519 }; | 418 }; |
520 | 419 |
521 } } // namespace v8::internal | 420 } } // namespace v8::internal |
522 | 421 |
523 #endif // V8_IA32_LITHIUM_CODEGEN_IA32_H_ | 422 #endif // V8_IA32_LITHIUM_CODEGEN_IA32_H_ |
OLD | NEW |