| 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 |