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 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
678 } | 678 } |
679 | 679 |
680 | 680 |
681 double LCodeGen::ToDouble(LConstantOperand* op) const { | 681 double LCodeGen::ToDouble(LConstantOperand* op) const { |
682 HConstant* constant = chunk_->LookupConstant(op); | 682 HConstant* constant = chunk_->LookupConstant(op); |
683 ASSERT(constant->HasDoubleValue()); | 683 ASSERT(constant->HasDoubleValue()); |
684 return constant->DoubleValue(); | 684 return constant->DoubleValue(); |
685 } | 685 } |
686 | 686 |
687 | 687 |
688 ExternalReference LCodeGen::ToExternalReference(LConstantOperand* op) const { | |
689 HConstant* constant = chunk_->LookupConstant(op); | |
690 ASSERT(constant->HasExternalReferenceValue()); | |
691 return constant->ExternalReferenceValue(); | |
692 } | |
693 | |
694 | |
695 bool LCodeGen::IsInteger32(LConstantOperand* op) const { | 688 bool LCodeGen::IsInteger32(LConstantOperand* op) const { |
696 return chunk_->LookupLiteralRepresentation(op).IsSmiOrInteger32(); | 689 return chunk_->LookupLiteralRepresentation(op).IsSmiOrInteger32(); |
697 } | 690 } |
698 | 691 |
699 | 692 |
700 bool LCodeGen::IsSmi(LConstantOperand* op) const { | 693 bool LCodeGen::IsSmi(LConstantOperand* op) const { |
701 return chunk_->LookupLiteralRepresentation(op).IsSmi(); | 694 return chunk_->LookupLiteralRepresentation(op).IsSmi(); |
702 } | 695 } |
703 | 696 |
704 | 697 |
(...skipping 1057 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1762 case Token::SHR: | 1755 case Token::SHR: |
1763 if (shift_count == 0 && instr->can_deopt()) { | 1756 if (shift_count == 0 && instr->can_deopt()) { |
1764 __ test(ToRegister(left), Immediate(0x80000000)); | 1757 __ test(ToRegister(left), Immediate(0x80000000)); |
1765 DeoptimizeIf(not_zero, instr->environment()); | 1758 DeoptimizeIf(not_zero, instr->environment()); |
1766 } else { | 1759 } else { |
1767 __ shr(ToRegister(left), shift_count); | 1760 __ shr(ToRegister(left), shift_count); |
1768 } | 1761 } |
1769 break; | 1762 break; |
1770 case Token::SHL: | 1763 case Token::SHL: |
1771 if (shift_count != 0) { | 1764 if (shift_count != 0) { |
1772 if (instr->hydrogen_value()->representation().IsSmi() && | 1765 __ shl(ToRegister(left), shift_count); |
1773 instr->can_deopt()) { | |
1774 __ shl(ToRegister(left), shift_count - 1); | |
1775 __ SmiTag(ToRegister(left)); | |
1776 DeoptimizeIf(overflow, instr->environment()); | |
1777 } else { | |
1778 __ shl(ToRegister(left), shift_count); | |
1779 } | |
1780 } | 1766 } |
1781 break; | 1767 break; |
1782 default: | 1768 default: |
1783 UNREACHABLE(); | 1769 UNREACHABLE(); |
1784 break; | 1770 break; |
1785 } | 1771 } |
1786 } | 1772 } |
1787 } | 1773 } |
1788 | 1774 |
1789 | 1775 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1853 __ Set(temp, Immediate(lower)); | 1839 __ Set(temp, Immediate(lower)); |
1854 __ movd(xmm0, Operand(temp)); | 1840 __ movd(xmm0, Operand(temp)); |
1855 __ por(res, xmm0); | 1841 __ por(res, xmm0); |
1856 } | 1842 } |
1857 } | 1843 } |
1858 } | 1844 } |
1859 } | 1845 } |
1860 } | 1846 } |
1861 | 1847 |
1862 | 1848 |
1863 void LCodeGen::DoConstantE(LConstantE* instr) { | |
1864 __ lea(ToRegister(instr->result()), Operand::StaticVariable(instr->value())); | |
1865 } | |
1866 | |
1867 | |
1868 void LCodeGen::DoConstantT(LConstantT* instr) { | 1849 void LCodeGen::DoConstantT(LConstantT* instr) { |
1869 Register reg = ToRegister(instr->result()); | 1850 Register reg = ToRegister(instr->result()); |
1870 Handle<Object> handle = instr->value(); | 1851 Handle<Object> handle = instr->value(); |
1871 AllowDeferredHandleDereference smi_check; | 1852 AllowDeferredHandleDereference smi_check; |
1872 __ LoadObject(reg, handle); | 1853 __ LoadObject(reg, handle); |
1873 } | 1854 } |
1874 | 1855 |
1875 | 1856 |
1876 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { | 1857 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { |
1877 Register result = ToRegister(instr->result()); | 1858 Register result = ToRegister(instr->result()); |
(...skipping 1176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3054 check_needed); | 3035 check_needed); |
3055 } | 3036 } |
3056 | 3037 |
3057 __ bind(&skip_assignment); | 3038 __ bind(&skip_assignment); |
3058 } | 3039 } |
3059 | 3040 |
3060 | 3041 |
3061 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 3042 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
3062 HObjectAccess access = instr->hydrogen()->access(); | 3043 HObjectAccess access = instr->hydrogen()->access(); |
3063 int offset = access.offset(); | 3044 int offset = access.offset(); |
3064 | |
3065 if (access.IsExternalMemory()) { | |
3066 Register result = ToRegister(instr->result()); | |
3067 if (instr->object()->IsConstantOperand()) { | |
3068 ExternalReference external_reference = ToExternalReference( | |
3069 LConstantOperand::cast(instr->object())); | |
3070 __ mov(result, MemOperand::StaticVariable(external_reference)); | |
3071 } else { | |
3072 __ mov(result, MemOperand(ToRegister(instr->object()), offset)); | |
3073 } | |
3074 return; | |
3075 } | |
3076 | |
3077 Register object = ToRegister(instr->object()); | 3045 Register object = ToRegister(instr->object()); |
3078 if (FLAG_track_double_fields && | 3046 if (FLAG_track_double_fields && |
3079 instr->hydrogen()->representation().IsDouble()) { | 3047 instr->hydrogen()->representation().IsDouble()) { |
3080 if (CpuFeatures::IsSupported(SSE2)) { | 3048 if (CpuFeatures::IsSupported(SSE2)) { |
3081 CpuFeatureScope scope(masm(), SSE2); | 3049 CpuFeatureScope scope(masm(), SSE2); |
3082 XMMRegister result = ToDoubleRegister(instr->result()); | 3050 XMMRegister result = ToDoubleRegister(instr->result()); |
3083 __ movdbl(result, FieldOperand(object, offset)); | 3051 __ movdbl(result, FieldOperand(object, offset)); |
3084 } else { | 3052 } else { |
3085 X87Mov(ToX87Register(instr->result()), FieldOperand(object, offset)); | 3053 X87Mov(ToX87Register(instr->result()), FieldOperand(object, offset)); |
3086 } | 3054 } |
(...skipping 1259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4346 void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) { | 4314 void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) { |
4347 Register result = ToRegister(instr->result()); | 4315 Register result = ToRegister(instr->result()); |
4348 Register base = ToRegister(instr->base_object()); | 4316 Register base = ToRegister(instr->base_object()); |
4349 __ lea(result, Operand(base, instr->offset())); | 4317 __ lea(result, Operand(base, instr->offset())); |
4350 } | 4318 } |
4351 | 4319 |
4352 | 4320 |
4353 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { | 4321 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { |
4354 Representation representation = instr->representation(); | 4322 Representation representation = instr->representation(); |
4355 | 4323 |
| 4324 Register object = ToRegister(instr->object()); |
4356 HObjectAccess access = instr->hydrogen()->access(); | 4325 HObjectAccess access = instr->hydrogen()->access(); |
4357 int offset = access.offset(); | 4326 int offset = access.offset(); |
4358 | 4327 |
4359 if (access.IsExternalMemory()) { | |
4360 MemOperand operand = instr->object()->IsConstantOperand() | |
4361 ? MemOperand::StaticVariable( | |
4362 ToExternalReference(LConstantOperand::cast(instr->object()))) | |
4363 : MemOperand(ToRegister(instr->object()), offset); | |
4364 if (instr->value()->IsConstantOperand()) { | |
4365 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); | |
4366 __ mov(operand, Immediate(ToInteger32(operand_value))); | |
4367 } else { | |
4368 Register value = ToRegister(instr->value()); | |
4369 __ mov(operand, value); | |
4370 } | |
4371 return; | |
4372 } | |
4373 | |
4374 Register object = ToRegister(instr->object()); | |
4375 Handle<Map> transition = instr->transition(); | 4328 Handle<Map> transition = instr->transition(); |
4376 | 4329 |
4377 if (FLAG_track_fields && representation.IsSmi()) { | 4330 if (FLAG_track_fields && representation.IsSmi()) { |
4378 if (instr->value()->IsConstantOperand()) { | 4331 if (instr->value()->IsConstantOperand()) { |
4379 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); | 4332 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); |
4380 if (!IsSmi(operand_value)) { | 4333 if (!IsSmi(operand_value)) { |
4381 DeoptimizeIf(no_condition, instr->environment()); | 4334 DeoptimizeIf(no_condition, instr->environment()); |
4382 } | 4335 } |
4383 } | 4336 } |
4384 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { | 4337 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4429 } | 4382 } |
4430 | 4383 |
4431 // Do the store. | 4384 // Do the store. |
4432 SmiCheck check_needed = | 4385 SmiCheck check_needed = |
4433 instr->hydrogen()->value()->IsHeapObject() | 4386 instr->hydrogen()->value()->IsHeapObject() |
4434 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 4387 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
4435 | 4388 |
4436 Register write_register = object; | 4389 Register write_register = object; |
4437 if (!access.IsInobject()) { | 4390 if (!access.IsInobject()) { |
4438 write_register = ToRegister(instr->temp()); | 4391 write_register = ToRegister(instr->temp()); |
4439 __ mov(write_register, FieldOperand(object, JSObject::kPropertiesOffset)); | 4392 __ mov(write_register, |
| 4393 FieldOperand(object, JSObject::kPropertiesOffset)); |
4440 } | 4394 } |
4441 | 4395 |
4442 if (instr->value()->IsConstantOperand()) { | 4396 if (instr->value()->IsConstantOperand()) { |
4443 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); | 4397 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); |
4444 if (operand_value->IsRegister()) { | 4398 if (operand_value->IsRegister()) { |
4445 __ mov(FieldOperand(write_register, offset), ToRegister(operand_value)); | 4399 __ mov(FieldOperand(write_register, offset), ToRegister(operand_value)); |
4446 } else { | 4400 } else { |
4447 Handle<Object> handle_value = ToHandle(operand_value); | 4401 Handle<Object> handle_value = ToHandle(operand_value); |
4448 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); | 4402 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); |
4449 __ mov(FieldOperand(write_register, offset), handle_value); | 4403 __ mov(FieldOperand(write_register, offset), handle_value); |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4747 if (is_simple_map_transition) { | 4701 if (is_simple_map_transition) { |
4748 Register new_map_reg = ToRegister(instr->new_map_temp()); | 4702 Register new_map_reg = ToRegister(instr->new_map_temp()); |
4749 Handle<Map> map = instr->hydrogen()->transitioned_map(); | 4703 Handle<Map> map = instr->hydrogen()->transitioned_map(); |
4750 __ mov(FieldOperand(object_reg, HeapObject::kMapOffset), | 4704 __ mov(FieldOperand(object_reg, HeapObject::kMapOffset), |
4751 Immediate(map)); | 4705 Immediate(map)); |
4752 // Write barrier. | 4706 // Write barrier. |
4753 ASSERT_NE(instr->temp(), NULL); | 4707 ASSERT_NE(instr->temp(), NULL); |
4754 __ RecordWriteForMap(object_reg, to_map, new_map_reg, | 4708 __ RecordWriteForMap(object_reg, to_map, new_map_reg, |
4755 ToRegister(instr->temp()), | 4709 ToRegister(instr->temp()), |
4756 kDontSaveFPRegs); | 4710 kDontSaveFPRegs); |
4757 } else { | 4711 } else if (FLAG_compiled_transitions) { |
4758 PushSafepointRegistersScope scope(this); | 4712 PushSafepointRegistersScope scope(this); |
4759 if (!object_reg.is(eax)) { | 4713 if (!object_reg.is(eax)) { |
4760 __ push(object_reg); | 4714 __ push(object_reg); |
4761 } | 4715 } |
4762 LoadContextFromDeferred(instr->context()); | 4716 LoadContextFromDeferred(instr->context()); |
4763 if (!object_reg.is(eax)) { | 4717 if (!object_reg.is(eax)) { |
4764 __ pop(eax); | 4718 __ pop(eax); |
4765 } | 4719 } |
4766 __ mov(ebx, to_map); | 4720 __ mov(ebx, to_map); |
4767 TransitionElementsKindStub stub(from_kind, to_kind); | 4721 TransitionElementsKindStub stub(from_kind, to_kind); |
4768 __ CallStub(&stub); | 4722 __ CallStub(&stub); |
4769 RecordSafepointWithRegisters( | 4723 RecordSafepointWithRegisters( |
4770 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | 4724 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
| 4725 } else if (IsFastSmiElementsKind(from_kind) && |
| 4726 IsFastDoubleElementsKind(to_kind)) { |
| 4727 Register new_map_reg = ToRegister(instr->new_map_temp()); |
| 4728 __ mov(new_map_reg, to_map); |
| 4729 Register fixed_object_reg = ToRegister(instr->temp()); |
| 4730 ASSERT(fixed_object_reg.is(edx)); |
| 4731 ASSERT(new_map_reg.is(ebx)); |
| 4732 __ mov(fixed_object_reg, object_reg); |
| 4733 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), |
| 4734 RelocInfo::CODE_TARGET, instr); |
| 4735 } else if (IsFastDoubleElementsKind(from_kind) && |
| 4736 IsFastObjectElementsKind(to_kind)) { |
| 4737 Register new_map_reg = ToRegister(instr->new_map_temp()); |
| 4738 __ mov(new_map_reg, to_map); |
| 4739 Register fixed_object_reg = ToRegister(instr->temp()); |
| 4740 ASSERT(fixed_object_reg.is(edx)); |
| 4741 ASSERT(new_map_reg.is(ebx)); |
| 4742 __ mov(fixed_object_reg, object_reg); |
| 4743 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), |
| 4744 RelocInfo::CODE_TARGET, instr); |
| 4745 } else { |
| 4746 UNREACHABLE(); |
4771 } | 4747 } |
4772 __ bind(¬_applicable); | 4748 __ bind(¬_applicable); |
4773 } | 4749 } |
4774 | 4750 |
4775 | 4751 |
4776 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { | 4752 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { |
4777 class DeferredStringCharCodeAt: public LDeferredCode { | 4753 class DeferredStringCharCodeAt: public LDeferredCode { |
4778 public: | 4754 public: |
4779 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) | 4755 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) |
4780 : LDeferredCode(codegen), instr_(instr) { } | 4756 : LDeferredCode(codegen), instr_(instr) { } |
(...skipping 1742 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6523 FixedArray::kHeaderSize - kPointerSize)); | 6499 FixedArray::kHeaderSize - kPointerSize)); |
6524 __ bind(&done); | 6500 __ bind(&done); |
6525 } | 6501 } |
6526 | 6502 |
6527 | 6503 |
6528 #undef __ | 6504 #undef __ |
6529 | 6505 |
6530 } } // namespace v8::internal | 6506 } } // namespace v8::internal |
6531 | 6507 |
6532 #endif // V8_TARGET_ARCH_IA32 | 6508 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |