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