OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
442 for (int i = 0; i < translation_size; ++i) { | 442 for (int i = 0; i < translation_size; ++i) { |
443 LOperand* value = environment->values()->at(i); | 443 LOperand* value = environment->values()->at(i); |
444 // spilled_registers_ and spilled_double_registers_ are either | 444 // spilled_registers_ and spilled_double_registers_ are either |
445 // both NULL or both set. | 445 // both NULL or both set. |
446 if (environment->spilled_registers() != NULL && value != NULL) { | 446 if (environment->spilled_registers() != NULL && value != NULL) { |
447 if (value->IsRegister() && | 447 if (value->IsRegister() && |
448 environment->spilled_registers()[value->index()] != NULL) { | 448 environment->spilled_registers()[value->index()] != NULL) { |
449 translation->MarkDuplicate(); | 449 translation->MarkDuplicate(); |
450 AddToTranslation(translation, | 450 AddToTranslation(translation, |
451 environment->spilled_registers()[value->index()], | 451 environment->spilled_registers()[value->index()], |
452 environment->HasTaggedValueAt(i)); | 452 environment->HasTaggedValueAt(i), |
| 453 environment->HasUint32ValueAt(i)); |
453 } else if ( | 454 } else if ( |
454 value->IsDoubleRegister() && | 455 value->IsDoubleRegister() && |
455 environment->spilled_double_registers()[value->index()] != NULL) { | 456 environment->spilled_double_registers()[value->index()] != NULL) { |
456 translation->MarkDuplicate(); | 457 translation->MarkDuplicate(); |
457 AddToTranslation( | 458 AddToTranslation( |
458 translation, | 459 translation, |
459 environment->spilled_double_registers()[value->index()], | 460 environment->spilled_double_registers()[value->index()], |
| 461 false, |
460 false); | 462 false); |
461 } | 463 } |
462 } | 464 } |
463 | 465 |
464 AddToTranslation(translation, value, environment->HasTaggedValueAt(i)); | 466 AddToTranslation(translation, |
| 467 value, |
| 468 environment->HasTaggedValueAt(i), |
| 469 environment->HasUint32ValueAt(i)); |
465 } | 470 } |
466 } | 471 } |
467 | 472 |
468 | 473 |
469 void LCodeGen::AddToTranslation(Translation* translation, | 474 void LCodeGen::AddToTranslation(Translation* translation, |
470 LOperand* op, | 475 LOperand* op, |
471 bool is_tagged) { | 476 bool is_tagged, |
| 477 bool is_uint32) { |
472 if (op == NULL) { | 478 if (op == NULL) { |
473 // TODO(twuerthinger): Introduce marker operands to indicate that this value | 479 // TODO(twuerthinger): Introduce marker operands to indicate that this value |
474 // is not present and must be reconstructed from the deoptimizer. Currently | 480 // is not present and must be reconstructed from the deoptimizer. Currently |
475 // this is only used for the arguments object. | 481 // this is only used for the arguments object. |
476 translation->StoreArgumentsObject(); | 482 translation->StoreArgumentsObject(); |
477 } else if (op->IsStackSlot()) { | 483 } else if (op->IsStackSlot()) { |
478 if (is_tagged) { | 484 if (is_tagged) { |
479 translation->StoreStackSlot(op->index()); | 485 translation->StoreStackSlot(op->index()); |
| 486 } else if (is_uint32) { |
| 487 translation->StoreUint32StackSlot(op->index()); |
480 } else { | 488 } else { |
481 translation->StoreInt32StackSlot(op->index()); | 489 translation->StoreInt32StackSlot(op->index()); |
482 } | 490 } |
483 } else if (op->IsDoubleStackSlot()) { | 491 } else if (op->IsDoubleStackSlot()) { |
484 translation->StoreDoubleStackSlot(op->index()); | 492 translation->StoreDoubleStackSlot(op->index()); |
485 } else if (op->IsArgument()) { | 493 } else if (op->IsArgument()) { |
486 ASSERT(is_tagged); | 494 ASSERT(is_tagged); |
487 int src_index = GetStackSlotCount() + op->index(); | 495 int src_index = GetStackSlotCount() + op->index(); |
488 translation->StoreStackSlot(src_index); | 496 translation->StoreStackSlot(src_index); |
489 } else if (op->IsRegister()) { | 497 } else if (op->IsRegister()) { |
490 Register reg = ToRegister(op); | 498 Register reg = ToRegister(op); |
491 if (is_tagged) { | 499 if (is_tagged) { |
492 translation->StoreRegister(reg); | 500 translation->StoreRegister(reg); |
| 501 } else if (is_uint32) { |
| 502 translation->StoreUint32Register(reg); |
493 } else { | 503 } else { |
494 translation->StoreInt32Register(reg); | 504 translation->StoreInt32Register(reg); |
495 } | 505 } |
496 } else if (op->IsDoubleRegister()) { | 506 } else if (op->IsDoubleRegister()) { |
497 XMMRegister reg = ToDoubleRegister(op); | 507 XMMRegister reg = ToDoubleRegister(op); |
498 translation->StoreDoubleRegister(reg); | 508 translation->StoreDoubleRegister(reg); |
499 } else if (op->IsConstantOperand()) { | 509 } else if (op->IsConstantOperand()) { |
500 HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op)); | 510 HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op)); |
501 int src_index = DefineDeoptimizationLiteral(constant->handle()); | 511 int src_index = DefineDeoptimizationLiteral(constant->handle()); |
502 translation->StoreLiteral(src_index); | 512 translation->StoreLiteral(src_index); |
(...skipping 2325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2828 __ movsx_w(result, operand); | 2838 __ movsx_w(result, operand); |
2829 break; | 2839 break; |
2830 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 2840 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
2831 __ movzx_w(result, operand); | 2841 __ movzx_w(result, operand); |
2832 break; | 2842 break; |
2833 case EXTERNAL_INT_ELEMENTS: | 2843 case EXTERNAL_INT_ELEMENTS: |
2834 __ mov(result, operand); | 2844 __ mov(result, operand); |
2835 break; | 2845 break; |
2836 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 2846 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
2837 __ mov(result, operand); | 2847 __ mov(result, operand); |
2838 __ test(result, Operand(result)); | 2848 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { |
2839 // TODO(danno): we could be more clever here, perhaps having a special | 2849 __ test(result, Operand(result)); |
2840 // version of the stub that detects if the overflow case actually | 2850 DeoptimizeIf(negative, instr->environment()); |
2841 // happens, and generate code that returns a double rather than int. | 2851 } |
2842 DeoptimizeIf(negative, instr->environment()); | |
2843 break; | 2852 break; |
2844 case EXTERNAL_FLOAT_ELEMENTS: | 2853 case EXTERNAL_FLOAT_ELEMENTS: |
2845 case EXTERNAL_DOUBLE_ELEMENTS: | 2854 case EXTERNAL_DOUBLE_ELEMENTS: |
2846 case FAST_SMI_ELEMENTS: | 2855 case FAST_SMI_ELEMENTS: |
2847 case FAST_ELEMENTS: | 2856 case FAST_ELEMENTS: |
2848 case FAST_DOUBLE_ELEMENTS: | 2857 case FAST_DOUBLE_ELEMENTS: |
2849 case FAST_HOLEY_SMI_ELEMENTS: | 2858 case FAST_HOLEY_SMI_ELEMENTS: |
2850 case FAST_HOLEY_ELEMENTS: | 2859 case FAST_HOLEY_ELEMENTS: |
2851 case FAST_HOLEY_DOUBLE_ELEMENTS: | 2860 case FAST_HOLEY_DOUBLE_ELEMENTS: |
2852 case DICTIONARY_ELEMENTS: | 2861 case DICTIONARY_ELEMENTS: |
(...skipping 1198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4051 | 4060 |
4052 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 4061 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
4053 LOperand* input = instr->InputAt(0); | 4062 LOperand* input = instr->InputAt(0); |
4054 ASSERT(input->IsRegister() || input->IsStackSlot()); | 4063 ASSERT(input->IsRegister() || input->IsStackSlot()); |
4055 LOperand* output = instr->result(); | 4064 LOperand* output = instr->result(); |
4056 ASSERT(output->IsDoubleRegister()); | 4065 ASSERT(output->IsDoubleRegister()); |
4057 __ cvtsi2sd(ToDoubleRegister(output), ToOperand(input)); | 4066 __ cvtsi2sd(ToDoubleRegister(output), ToOperand(input)); |
4058 } | 4067 } |
4059 | 4068 |
4060 | 4069 |
| 4070 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { |
| 4071 LOperand* input = instr->InputAt(0); |
| 4072 LOperand* output = instr->result(); |
| 4073 LOperand* temp = instr->TempAt(0); |
| 4074 |
| 4075 __ LoadUint32(ToDoubleRegister(output), |
| 4076 ToRegister(input), |
| 4077 ToDoubleRegister(temp)); |
| 4078 } |
| 4079 |
| 4080 |
4061 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { | 4081 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
4062 class DeferredNumberTagI: public LDeferredCode { | 4082 class DeferredNumberTagI: public LDeferredCode { |
4063 public: | 4083 public: |
4064 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) | 4084 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) |
4065 : LDeferredCode(codegen), instr_(instr) { } | 4085 : LDeferredCode(codegen), instr_(instr) { } |
4066 virtual void Generate() { codegen()->DoDeferredNumberTagI(instr_); } | 4086 virtual void Generate() { |
| 4087 codegen()->DoDeferredNumberTagI(instr_, SIGNED_INT32); |
| 4088 } |
4067 virtual LInstruction* instr() { return instr_; } | 4089 virtual LInstruction* instr() { return instr_; } |
4068 private: | 4090 private: |
4069 LNumberTagI* instr_; | 4091 LNumberTagI* instr_; |
4070 }; | 4092 }; |
4071 | 4093 |
4072 LOperand* input = instr->InputAt(0); | 4094 LOperand* input = instr->InputAt(0); |
4073 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 4095 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
4074 Register reg = ToRegister(input); | 4096 Register reg = ToRegister(input); |
4075 | 4097 |
4076 DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr); | 4098 DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr); |
4077 __ SmiTag(reg); | 4099 __ SmiTag(reg); |
4078 __ j(overflow, deferred->entry()); | 4100 __ j(overflow, deferred->entry()); |
4079 __ bind(deferred->exit()); | 4101 __ bind(deferred->exit()); |
4080 } | 4102 } |
4081 | 4103 |
4082 | 4104 |
4083 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { | 4105 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { |
| 4106 class DeferredNumberTagU: public LDeferredCode { |
| 4107 public: |
| 4108 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) |
| 4109 : LDeferredCode(codegen), instr_(instr) { } |
| 4110 virtual void Generate() { |
| 4111 codegen()->DoDeferredNumberTagI(instr_, UNSIGNED_INT32); |
| 4112 } |
| 4113 virtual LInstruction* instr() { return instr_; } |
| 4114 private: |
| 4115 LNumberTagU* instr_; |
| 4116 }; |
| 4117 |
| 4118 LOperand* input = instr->InputAt(0); |
| 4119 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
| 4120 Register reg = ToRegister(input); |
| 4121 |
| 4122 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); |
| 4123 __ cmp(reg, Immediate(Smi::kMaxValue)); |
| 4124 __ j(above, deferred->entry()); |
| 4125 __ SmiTag(reg); |
| 4126 __ bind(deferred->exit()); |
| 4127 } |
| 4128 |
| 4129 |
| 4130 void LCodeGen::DoDeferredNumberTagI(LInstruction* instr, |
| 4131 IntegerSignedness signedness) { |
4084 Label slow; | 4132 Label slow; |
4085 Register reg = ToRegister(instr->InputAt(0)); | 4133 Register reg = ToRegister(instr->InputAt(0)); |
4086 Register tmp = reg.is(eax) ? ecx : eax; | 4134 Register tmp = reg.is(eax) ? ecx : eax; |
4087 | 4135 |
4088 // Preserve the value of all registers. | 4136 // Preserve the value of all registers. |
4089 PushSafepointRegistersScope scope(this); | 4137 PushSafepointRegistersScope scope(this); |
4090 | 4138 |
4091 // There was overflow, so bits 30 and 31 of the original integer | |
4092 // disagree. Try to allocate a heap number in new space and store | |
4093 // the value in there. If that fails, call the runtime system. | |
4094 Label done; | 4139 Label done; |
4095 __ SmiUntag(reg); | 4140 |
4096 __ xor_(reg, 0x80000000); | 4141 if (signedness == SIGNED_INT32) { |
4097 __ cvtsi2sd(xmm0, Operand(reg)); | 4142 // There was overflow, so bits 30 and 31 of the original integer |
| 4143 // disagree. Try to allocate a heap number in new space and store |
| 4144 // the value in there. If that fails, call the runtime system. |
| 4145 __ SmiUntag(reg); |
| 4146 __ xor_(reg, 0x80000000); |
| 4147 __ cvtsi2sd(xmm0, Operand(reg)); |
| 4148 } else { |
| 4149 __ LoadUint32(xmm0, reg, xmm1); |
| 4150 } |
| 4151 |
4098 if (FLAG_inline_new) { | 4152 if (FLAG_inline_new) { |
4099 __ AllocateHeapNumber(reg, tmp, no_reg, &slow); | 4153 __ AllocateHeapNumber(reg, tmp, no_reg, &slow); |
4100 __ jmp(&done, Label::kNear); | 4154 __ jmp(&done, Label::kNear); |
4101 } | 4155 } |
4102 | 4156 |
4103 // Slow case: Call the runtime system to do the number allocation. | 4157 // Slow case: Call the runtime system to do the number allocation. |
4104 __ bind(&slow); | 4158 __ bind(&slow); |
4105 | 4159 |
4106 // TODO(3095996): Put a valid pointer value in the stack slot where the result | 4160 // TODO(3095996): Put a valid pointer value in the stack slot where the result |
4107 // register is stored, as this register is in the pointer map, but contains an | 4161 // register is stored, as this register is in the pointer map, but contains an |
(...skipping 1314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5422 FixedArray::kHeaderSize - kPointerSize)); | 5476 FixedArray::kHeaderSize - kPointerSize)); |
5423 __ bind(&done); | 5477 __ bind(&done); |
5424 } | 5478 } |
5425 | 5479 |
5426 | 5480 |
5427 #undef __ | 5481 #undef __ |
5428 | 5482 |
5429 } } // namespace v8::internal | 5483 } } // namespace v8::internal |
5430 | 5484 |
5431 #endif // V8_TARGET_ARCH_IA32 | 5485 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |