OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 2037 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2048 // to update the property details in the property dictionary to mark | 2048 // to update the property details in the property dictionary to mark |
2049 // it as no longer deleted. We deoptimize in that case. | 2049 // it as no longer deleted. We deoptimize in that case. |
2050 if (instr->hydrogen()->RequiresHoleCheck()) { | 2050 if (instr->hydrogen()->RequiresHoleCheck()) { |
2051 __ CompareRoot(Operand(address, 0), Heap::kTheHoleValueRootIndex); | 2051 __ CompareRoot(Operand(address, 0), Heap::kTheHoleValueRootIndex); |
2052 DeoptimizeIf(equal, instr->environment()); | 2052 DeoptimizeIf(equal, instr->environment()); |
2053 } | 2053 } |
2054 | 2054 |
2055 // Store the value. | 2055 // Store the value. |
2056 __ movq(Operand(address, 0), value); | 2056 __ movq(Operand(address, 0), value); |
2057 | 2057 |
2058 Label smi_store; | 2058 if (instr->hydrogen()->NeedsWriteBarrier()) { |
2059 __ JumpIfSmi(value, &smi_store, Label::kNear); | 2059 Label smi_store; |
| 2060 HType type = instr->hydrogen()->value()->type(); |
| 2061 if (!type.IsHeapNumber() && !type.IsString() && !type.IsNonPrimitive()) { |
| 2062 __ JumpIfSmi(value, &smi_store, Label::kNear); |
| 2063 } |
2060 | 2064 |
2061 int offset = JSGlobalPropertyCell::kValueOffset - kHeapObjectTag; | 2065 int offset = JSGlobalPropertyCell::kValueOffset - kHeapObjectTag; |
2062 __ lea(object, Operand(address, -offset)); | 2066 __ lea(object, Operand(address, -offset)); |
2063 // Cells are always in the remembered set. | 2067 // Cells are always in the remembered set. |
2064 __ RecordWrite(object, | 2068 __ RecordWrite(object, |
2065 address, | 2069 address, |
2066 value, | 2070 value, |
2067 kSaveFPRegs, | 2071 kSaveFPRegs, |
2068 OMIT_REMEMBERED_SET, | 2072 OMIT_REMEMBERED_SET, |
2069 OMIT_SMI_CHECK); | 2073 OMIT_SMI_CHECK); |
2070 __ bind(&smi_store); | 2074 __ bind(&smi_store); |
| 2075 } |
2071 } | 2076 } |
2072 | 2077 |
2073 | 2078 |
2074 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { | 2079 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { |
2075 ASSERT(ToRegister(instr->global_object()).is(rdx)); | 2080 ASSERT(ToRegister(instr->global_object()).is(rdx)); |
2076 ASSERT(ToRegister(instr->value()).is(rax)); | 2081 ASSERT(ToRegister(instr->value()).is(rax)); |
2077 | 2082 |
2078 __ Move(rcx, instr->name()); | 2083 __ Move(rcx, instr->name()); |
2079 Handle<Code> ic = instr->strict_mode() | 2084 Handle<Code> ic = instr->strict_mode() |
2080 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 2085 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
2081 : isolate()->builtins()->StoreIC_Initialize(); | 2086 : isolate()->builtins()->StoreIC_Initialize(); |
2082 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); | 2087 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); |
2083 } | 2088 } |
2084 | 2089 |
2085 | 2090 |
2086 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { | 2091 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { |
2087 Register context = ToRegister(instr->context()); | 2092 Register context = ToRegister(instr->context()); |
2088 Register result = ToRegister(instr->result()); | 2093 Register result = ToRegister(instr->result()); |
2089 __ movq(result, ContextOperand(context, instr->slot_index())); | 2094 __ movq(result, ContextOperand(context, instr->slot_index())); |
2090 } | 2095 } |
2091 | 2096 |
2092 | 2097 |
2093 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { | 2098 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { |
2094 Register context = ToRegister(instr->context()); | 2099 Register context = ToRegister(instr->context()); |
2095 Register value = ToRegister(instr->value()); | 2100 Register value = ToRegister(instr->value()); |
2096 __ movq(ContextOperand(context, instr->slot_index()), value); | 2101 __ movq(ContextOperand(context, instr->slot_index()), value); |
2097 if (instr->needs_write_barrier()) { | 2102 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 2103 HType type = instr->hydrogen()->value()->type(); |
| 2104 SmiCheck check_needed = |
| 2105 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
2098 int offset = Context::SlotOffset(instr->slot_index()); | 2106 int offset = Context::SlotOffset(instr->slot_index()); |
2099 Register scratch = ToRegister(instr->TempAt(0)); | 2107 Register scratch = ToRegister(instr->TempAt(0)); |
2100 __ RecordWriteContextSlot(context, offset, value, scratch, kSaveFPRegs); | 2108 __ RecordWriteContextSlot(context, |
| 2109 offset, |
| 2110 value, |
| 2111 scratch, |
| 2112 kSaveFPRegs, |
| 2113 EMIT_REMEMBERED_SET, |
| 2114 check_needed); |
2101 } | 2115 } |
2102 } | 2116 } |
2103 | 2117 |
2104 | 2118 |
2105 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 2119 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
2106 Register object = ToRegister(instr->InputAt(0)); | 2120 Register object = ToRegister(instr->InputAt(0)); |
2107 Register result = ToRegister(instr->result()); | 2121 Register result = ToRegister(instr->result()); |
2108 if (instr->hydrogen()->is_in_object()) { | 2122 if (instr->hydrogen()->is_in_object()) { |
2109 __ movq(result, FieldOperand(object, instr->hydrogen()->offset())); | 2123 __ movq(result, FieldOperand(object, instr->hydrogen()->offset())); |
2110 } else { | 2124 } else { |
(...skipping 943 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3054 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { | 3068 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { |
3055 Register object = ToRegister(instr->object()); | 3069 Register object = ToRegister(instr->object()); |
3056 Register value = ToRegister(instr->value()); | 3070 Register value = ToRegister(instr->value()); |
3057 int offset = instr->offset(); | 3071 int offset = instr->offset(); |
3058 | 3072 |
3059 if (!instr->transition().is_null()) { | 3073 if (!instr->transition().is_null()) { |
3060 __ Move(FieldOperand(object, HeapObject::kMapOffset), instr->transition()); | 3074 __ Move(FieldOperand(object, HeapObject::kMapOffset), instr->transition()); |
3061 } | 3075 } |
3062 | 3076 |
3063 // Do the store. | 3077 // Do the store. |
| 3078 HType type = instr->hydrogen()->value()->type(); |
| 3079 SmiCheck check_needed = |
| 3080 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
3064 if (instr->is_in_object()) { | 3081 if (instr->is_in_object()) { |
3065 __ movq(FieldOperand(object, offset), value); | 3082 __ movq(FieldOperand(object, offset), value); |
3066 if (instr->needs_write_barrier()) { | 3083 if (instr->hydrogen()->NeedsWriteBarrier()) { |
3067 Register temp = ToRegister(instr->TempAt(0)); | 3084 Register temp = ToRegister(instr->TempAt(0)); |
3068 // Update the write barrier for the object for in-object properties. | 3085 // Update the write barrier for the object for in-object properties. |
3069 __ RecordWriteField(object, offset, value, temp, kSaveFPRegs); | 3086 __ RecordWriteField(object, |
| 3087 offset, |
| 3088 value, |
| 3089 temp, |
| 3090 kSaveFPRegs, |
| 3091 EMIT_REMEMBERED_SET, |
| 3092 check_needed); |
3070 } | 3093 } |
3071 } else { | 3094 } else { |
3072 Register temp = ToRegister(instr->TempAt(0)); | 3095 Register temp = ToRegister(instr->TempAt(0)); |
3073 __ movq(temp, FieldOperand(object, JSObject::kPropertiesOffset)); | 3096 __ movq(temp, FieldOperand(object, JSObject::kPropertiesOffset)); |
3074 __ movq(FieldOperand(temp, offset), value); | 3097 __ movq(FieldOperand(temp, offset), value); |
3075 if (instr->needs_write_barrier()) { | 3098 if (instr->hydrogen()->NeedsWriteBarrier()) { |
3076 // Update the write barrier for the properties array. | 3099 // Update the write barrier for the properties array. |
3077 // object is used as a scratch register. | 3100 // object is used as a scratch register. |
3078 __ RecordWriteField(temp, offset, value, object, kSaveFPRegs); | 3101 __ RecordWriteField(temp, |
| 3102 offset, |
| 3103 value, |
| 3104 object, |
| 3105 kSaveFPRegs, |
| 3106 EMIT_REMEMBERED_SET, |
| 3107 check_needed); |
3079 } | 3108 } |
3080 } | 3109 } |
3081 } | 3110 } |
3082 | 3111 |
3083 | 3112 |
3084 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { | 3113 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { |
3085 ASSERT(ToRegister(instr->object()).is(rdx)); | 3114 ASSERT(ToRegister(instr->object()).is(rdx)); |
3086 ASSERT(ToRegister(instr->value()).is(rax)); | 3115 ASSERT(ToRegister(instr->value()).is(rax)); |
3087 | 3116 |
3088 __ Move(rcx, instr->hydrogen()->name()); | 3117 __ Move(rcx, instr->hydrogen()->name()); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3175 __ movq(FieldOperand(elements, offset), value); | 3204 __ movq(FieldOperand(elements, offset), value); |
3176 } else { | 3205 } else { |
3177 __ movq(FieldOperand(elements, | 3206 __ movq(FieldOperand(elements, |
3178 key, | 3207 key, |
3179 times_pointer_size, | 3208 times_pointer_size, |
3180 FixedArray::kHeaderSize), | 3209 FixedArray::kHeaderSize), |
3181 value); | 3210 value); |
3182 } | 3211 } |
3183 | 3212 |
3184 if (instr->hydrogen()->NeedsWriteBarrier()) { | 3213 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 3214 HType type = instr->hydrogen()->value()->type(); |
| 3215 SmiCheck check_needed = |
| 3216 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
3185 // Compute address of modified element and store it into key register. | 3217 // Compute address of modified element and store it into key register. |
3186 __ lea(key, FieldOperand(elements, | 3218 __ lea(key, FieldOperand(elements, |
3187 key, | 3219 key, |
3188 times_pointer_size, | 3220 times_pointer_size, |
3189 FixedArray::kHeaderSize)); | 3221 FixedArray::kHeaderSize)); |
3190 __ RecordWrite(elements, key, value, kSaveFPRegs); | 3222 __ RecordWrite(elements, |
| 3223 key, |
| 3224 value, |
| 3225 kSaveFPRegs, |
| 3226 EMIT_REMEMBERED_SET, |
| 3227 check_needed); |
3191 } | 3228 } |
3192 } | 3229 } |
3193 | 3230 |
3194 | 3231 |
3195 void LCodeGen::DoStoreKeyedFastDoubleElement( | 3232 void LCodeGen::DoStoreKeyedFastDoubleElement( |
3196 LStoreKeyedFastDoubleElement* instr) { | 3233 LStoreKeyedFastDoubleElement* instr) { |
3197 XMMRegister value = ToDoubleRegister(instr->value()); | 3234 XMMRegister value = ToDoubleRegister(instr->value()); |
3198 Label have_value; | 3235 Label have_value; |
3199 | 3236 |
3200 __ ucomisd(value, value); | 3237 __ ucomisd(value, value); |
(...skipping 767 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3968 } | 4005 } |
3969 | 4006 |
3970 | 4007 |
3971 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 4008 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
3972 Register input = ToRegister(instr->InputAt(0)); | 4009 Register input = ToRegister(instr->InputAt(0)); |
3973 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 4010 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
3974 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 4011 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
3975 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 4012 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
3976 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 4013 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
3977 | 4014 |
3978 Condition final_branch_condition = EmitTypeofIs(true_label, | 4015 Condition final_branch_condition = |
3979 false_label, | 4016 EmitTypeofIs(true_label, false_label, input, instr->type_literal()); |
3980 input, | 4017 if (final_branch_condition != no_condition) { |
3981 instr->type_literal()); | 4018 EmitBranch(true_block, false_block, final_branch_condition); |
3982 | 4019 } |
3983 EmitBranch(true_block, false_block, final_branch_condition); | |
3984 } | 4020 } |
3985 | 4021 |
3986 | 4022 |
3987 Condition LCodeGen::EmitTypeofIs(Label* true_label, | 4023 Condition LCodeGen::EmitTypeofIs(Label* true_label, |
3988 Label* false_label, | 4024 Label* false_label, |
3989 Register input, | 4025 Register input, |
3990 Handle<String> type_name) { | 4026 Handle<String> type_name) { |
3991 Condition final_branch_condition = no_condition; | 4027 Condition final_branch_condition = no_condition; |
3992 if (type_name->Equals(heap()->number_symbol())) { | 4028 if (type_name->Equals(heap()->number_symbol())) { |
3993 __ JumpIfSmi(input, true_label); | 4029 __ JumpIfSmi(input, true_label); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4041 __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input); | 4077 __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input); |
4042 __ j(below, false_label); | 4078 __ j(below, false_label); |
4043 __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); | 4079 __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); |
4044 __ j(above, false_label); | 4080 __ j(above, false_label); |
4045 // Check for undetectable objects => false. | 4081 // Check for undetectable objects => false. |
4046 __ testb(FieldOperand(input, Map::kBitFieldOffset), | 4082 __ testb(FieldOperand(input, Map::kBitFieldOffset), |
4047 Immediate(1 << Map::kIsUndetectable)); | 4083 Immediate(1 << Map::kIsUndetectable)); |
4048 final_branch_condition = zero; | 4084 final_branch_condition = zero; |
4049 | 4085 |
4050 } else { | 4086 } else { |
4051 final_branch_condition = never; | |
4052 __ jmp(false_label); | 4087 __ jmp(false_label); |
4053 } | 4088 } |
4054 | 4089 |
4055 return final_branch_condition; | 4090 return final_branch_condition; |
4056 } | 4091 } |
4057 | 4092 |
4058 | 4093 |
4059 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { | 4094 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
4060 Register temp = ToRegister(instr->TempAt(0)); | 4095 Register temp = ToRegister(instr->TempAt(0)); |
4061 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 4096 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4196 RegisterEnvironmentForDeoptimization(environment); | 4231 RegisterEnvironmentForDeoptimization(environment); |
4197 ASSERT(osr_pc_offset_ == -1); | 4232 ASSERT(osr_pc_offset_ == -1); |
4198 osr_pc_offset_ = masm()->pc_offset(); | 4233 osr_pc_offset_ = masm()->pc_offset(); |
4199 } | 4234 } |
4200 | 4235 |
4201 #undef __ | 4236 #undef __ |
4202 | 4237 |
4203 } } // namespace v8::internal | 4238 } } // namespace v8::internal |
4204 | 4239 |
4205 #endif // V8_TARGET_ARCH_X64 | 4240 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |