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 2098 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2109 // it as no longer deleted. We deoptimize in that case. | 2109 // it as no longer deleted. We deoptimize in that case. |
2110 if (instr->hydrogen()->RequiresHoleCheck()) { | 2110 if (instr->hydrogen()->RequiresHoleCheck()) { |
2111 __ cmp(FieldOperand(object, offset), factory()->the_hole_value()); | 2111 __ cmp(FieldOperand(object, offset), factory()->the_hole_value()); |
2112 DeoptimizeIf(equal, instr->environment()); | 2112 DeoptimizeIf(equal, instr->environment()); |
2113 } | 2113 } |
2114 | 2114 |
2115 // Store the value. | 2115 // Store the value. |
2116 __ mov(FieldOperand(object, offset), value); | 2116 __ mov(FieldOperand(object, offset), value); |
2117 | 2117 |
2118 // Cells are always in the remembered set. | 2118 // Cells are always in the remembered set. |
2119 __ RecordWriteField(object, | 2119 if (instr->hydrogen()->NeedsWriteBarrier()) { |
2120 offset, | 2120 HType type = instr->hydrogen()->value()->type(); |
2121 value, | 2121 SmiCheck check_needed = |
2122 address, | 2122 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
2123 kSaveFPRegs, | 2123 __ RecordWriteField(object, |
2124 OMIT_REMEMBERED_SET); | 2124 offset, |
| 2125 value, |
| 2126 address, |
| 2127 kSaveFPRegs, |
| 2128 OMIT_REMEMBERED_SET, |
| 2129 check_needed); |
| 2130 } |
2125 } | 2131 } |
2126 | 2132 |
2127 | 2133 |
2128 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { | 2134 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { |
2129 ASSERT(ToRegister(instr->context()).is(esi)); | 2135 ASSERT(ToRegister(instr->context()).is(esi)); |
2130 ASSERT(ToRegister(instr->global_object()).is(edx)); | 2136 ASSERT(ToRegister(instr->global_object()).is(edx)); |
2131 ASSERT(ToRegister(instr->value()).is(eax)); | 2137 ASSERT(ToRegister(instr->value()).is(eax)); |
2132 | 2138 |
2133 __ mov(ecx, instr->name()); | 2139 __ mov(ecx, instr->name()); |
2134 Handle<Code> ic = instr->strict_mode() | 2140 Handle<Code> ic = instr->strict_mode() |
2135 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 2141 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
2136 : isolate()->builtins()->StoreIC_Initialize(); | 2142 : isolate()->builtins()->StoreIC_Initialize(); |
2137 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); | 2143 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); |
2138 } | 2144 } |
2139 | 2145 |
2140 | 2146 |
2141 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { | 2147 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { |
2142 Register context = ToRegister(instr->context()); | 2148 Register context = ToRegister(instr->context()); |
2143 Register result = ToRegister(instr->result()); | 2149 Register result = ToRegister(instr->result()); |
2144 __ mov(result, ContextOperand(context, instr->slot_index())); | 2150 __ mov(result, ContextOperand(context, instr->slot_index())); |
2145 } | 2151 } |
2146 | 2152 |
2147 | 2153 |
2148 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { | 2154 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { |
2149 Register context = ToRegister(instr->context()); | 2155 Register context = ToRegister(instr->context()); |
2150 Register value = ToRegister(instr->value()); | 2156 Register value = ToRegister(instr->value()); |
2151 __ mov(ContextOperand(context, instr->slot_index()), value); | 2157 __ mov(ContextOperand(context, instr->slot_index()), value); |
2152 if (instr->needs_write_barrier()) { | 2158 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 2159 HType type = instr->hydrogen()->value()->type(); |
| 2160 SmiCheck check_needed = |
| 2161 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
2153 Register temp = ToRegister(instr->TempAt(0)); | 2162 Register temp = ToRegister(instr->TempAt(0)); |
2154 int offset = Context::SlotOffset(instr->slot_index()); | 2163 int offset = Context::SlotOffset(instr->slot_index()); |
2155 __ RecordWriteContextSlot(context, offset, value, temp, kSaveFPRegs); | 2164 __ RecordWriteContextSlot(context, |
| 2165 offset, |
| 2166 value, |
| 2167 temp, |
| 2168 kSaveFPRegs, |
| 2169 EMIT_REMEMBERED_SET, |
| 2170 check_needed); |
2156 } | 2171 } |
2157 } | 2172 } |
2158 | 2173 |
2159 | 2174 |
2160 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 2175 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
2161 Register object = ToRegister(instr->object()); | 2176 Register object = ToRegister(instr->object()); |
2162 Register result = ToRegister(instr->result()); | 2177 Register result = ToRegister(instr->result()); |
2163 if (instr->hydrogen()->is_in_object()) { | 2178 if (instr->hydrogen()->is_in_object()) { |
2164 __ mov(result, FieldOperand(object, instr->hydrogen()->offset())); | 2179 __ mov(result, FieldOperand(object, instr->hydrogen()->offset())); |
2165 } else { | 2180 } else { |
(...skipping 973 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3139 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { | 3154 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { |
3140 Register object = ToRegister(instr->object()); | 3155 Register object = ToRegister(instr->object()); |
3141 Register value = ToRegister(instr->value()); | 3156 Register value = ToRegister(instr->value()); |
3142 int offset = instr->offset(); | 3157 int offset = instr->offset(); |
3143 | 3158 |
3144 if (!instr->transition().is_null()) { | 3159 if (!instr->transition().is_null()) { |
3145 __ mov(FieldOperand(object, HeapObject::kMapOffset), instr->transition()); | 3160 __ mov(FieldOperand(object, HeapObject::kMapOffset), instr->transition()); |
3146 } | 3161 } |
3147 | 3162 |
3148 // Do the store. | 3163 // Do the store. |
| 3164 HType type = instr->hydrogen()->value()->type(); |
| 3165 SmiCheck check_needed = |
| 3166 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
3149 if (instr->is_in_object()) { | 3167 if (instr->is_in_object()) { |
3150 __ mov(FieldOperand(object, offset), value); | 3168 __ mov(FieldOperand(object, offset), value); |
3151 if (instr->needs_write_barrier()) { | 3169 if (instr->hydrogen()->NeedsWriteBarrier()) { |
3152 Register temp = ToRegister(instr->TempAt(0)); | 3170 Register temp = ToRegister(instr->TempAt(0)); |
3153 // Update the write barrier for the object for in-object properties. | 3171 // Update the write barrier for the object for in-object properties. |
3154 __ RecordWriteField(object, offset, value, temp, kSaveFPRegs); | 3172 __ RecordWriteField(object, |
| 3173 offset, |
| 3174 value, |
| 3175 temp, |
| 3176 kSaveFPRegs, |
| 3177 EMIT_REMEMBERED_SET, |
| 3178 check_needed); |
3155 } | 3179 } |
3156 } else { | 3180 } else { |
3157 Register temp = ToRegister(instr->TempAt(0)); | 3181 Register temp = ToRegister(instr->TempAt(0)); |
3158 __ mov(temp, FieldOperand(object, JSObject::kPropertiesOffset)); | 3182 __ mov(temp, FieldOperand(object, JSObject::kPropertiesOffset)); |
3159 __ mov(FieldOperand(temp, offset), value); | 3183 __ mov(FieldOperand(temp, offset), value); |
3160 if (instr->needs_write_barrier()) { | 3184 if (instr->hydrogen()->NeedsWriteBarrier()) { |
3161 // Update the write barrier for the properties array. | 3185 // Update the write barrier for the properties array. |
3162 // object is used as a scratch register. | 3186 // object is used as a scratch register. |
3163 __ RecordWriteField(temp, offset, value, object, kSaveFPRegs); | 3187 __ RecordWriteField(temp, |
| 3188 offset, |
| 3189 value, |
| 3190 object, |
| 3191 kSaveFPRegs, |
| 3192 EMIT_REMEMBERED_SET, |
| 3193 check_needed); |
3164 } | 3194 } |
3165 } | 3195 } |
3166 } | 3196 } |
3167 | 3197 |
3168 | 3198 |
3169 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { | 3199 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { |
3170 ASSERT(ToRegister(instr->context()).is(esi)); | 3200 ASSERT(ToRegister(instr->context()).is(esi)); |
3171 ASSERT(ToRegister(instr->object()).is(edx)); | 3201 ASSERT(ToRegister(instr->object()).is(edx)); |
3172 ASSERT(ToRegister(instr->value()).is(eax)); | 3202 ASSERT(ToRegister(instr->value()).is(eax)); |
3173 | 3203 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3252 __ mov(FieldOperand(elements, offset), value); | 3282 __ mov(FieldOperand(elements, offset), value); |
3253 } else { | 3283 } else { |
3254 __ mov(FieldOperand(elements, | 3284 __ mov(FieldOperand(elements, |
3255 key, | 3285 key, |
3256 times_pointer_size, | 3286 times_pointer_size, |
3257 FixedArray::kHeaderSize), | 3287 FixedArray::kHeaderSize), |
3258 value); | 3288 value); |
3259 } | 3289 } |
3260 | 3290 |
3261 if (instr->hydrogen()->NeedsWriteBarrier()) { | 3291 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 3292 HType type = instr->hydrogen()->value()->type(); |
| 3293 SmiCheck check_needed = |
| 3294 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
3262 // Compute address of modified element and store it into key register. | 3295 // Compute address of modified element and store it into key register. |
3263 __ lea(key, | 3296 __ lea(key, |
3264 FieldOperand(elements, | 3297 FieldOperand(elements, |
3265 key, | 3298 key, |
3266 times_pointer_size, | 3299 times_pointer_size, |
3267 FixedArray::kHeaderSize)); | 3300 FixedArray::kHeaderSize)); |
3268 __ RecordWrite(elements, key, value, kSaveFPRegs); | 3301 __ RecordWrite(elements, |
| 3302 key, |
| 3303 value, |
| 3304 kSaveFPRegs, |
| 3305 EMIT_REMEMBERED_SET, |
| 3306 check_needed); |
3269 } | 3307 } |
3270 } | 3308 } |
3271 | 3309 |
3272 | 3310 |
3273 void LCodeGen::DoStoreKeyedFastDoubleElement( | 3311 void LCodeGen::DoStoreKeyedFastDoubleElement( |
3274 LStoreKeyedFastDoubleElement* instr) { | 3312 LStoreKeyedFastDoubleElement* instr) { |
3275 XMMRegister value = ToDoubleRegister(instr->value()); | 3313 XMMRegister value = ToDoubleRegister(instr->value()); |
3276 Label have_value; | 3314 Label have_value; |
3277 | 3315 |
3278 __ ucomisd(value, value); | 3316 __ ucomisd(value, value); |
(...skipping 961 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4240 } | 4278 } |
4241 | 4279 |
4242 | 4280 |
4243 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 4281 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
4244 Register input = ToRegister(instr->InputAt(0)); | 4282 Register input = ToRegister(instr->InputAt(0)); |
4245 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 4283 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
4246 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 4284 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
4247 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 4285 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
4248 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 4286 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
4249 | 4287 |
4250 Condition final_branch_condition = EmitTypeofIs(true_label, | 4288 Condition final_branch_condition = |
4251 false_label, | 4289 EmitTypeofIs(true_label, false_label, input, instr->type_literal()); |
4252 input, | 4290 if (final_branch_condition != no_condition) { |
4253 instr->type_literal()); | 4291 EmitBranch(true_block, false_block, final_branch_condition); |
4254 | 4292 } |
4255 EmitBranch(true_block, false_block, final_branch_condition); | |
4256 } | 4293 } |
4257 | 4294 |
4258 | 4295 |
4259 Condition LCodeGen::EmitTypeofIs(Label* true_label, | 4296 Condition LCodeGen::EmitTypeofIs(Label* true_label, |
4260 Label* false_label, | 4297 Label* false_label, |
4261 Register input, | 4298 Register input, |
4262 Handle<String> type_name) { | 4299 Handle<String> type_name) { |
4263 Condition final_branch_condition = no_condition; | 4300 Condition final_branch_condition = no_condition; |
4264 if (type_name->Equals(heap()->number_symbol())) { | 4301 if (type_name->Equals(heap()->number_symbol())) { |
4265 __ JumpIfSmi(input, true_label); | 4302 __ JumpIfSmi(input, true_label); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4312 __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input); | 4349 __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input); |
4313 __ j(below, false_label); | 4350 __ j(below, false_label); |
4314 __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); | 4351 __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); |
4315 __ j(above, false_label); | 4352 __ j(above, false_label); |
4316 // Check for undetectable objects => false. | 4353 // Check for undetectable objects => false. |
4317 __ test_b(FieldOperand(input, Map::kBitFieldOffset), | 4354 __ test_b(FieldOperand(input, Map::kBitFieldOffset), |
4318 1 << Map::kIsUndetectable); | 4355 1 << Map::kIsUndetectable); |
4319 final_branch_condition = zero; | 4356 final_branch_condition = zero; |
4320 | 4357 |
4321 } else { | 4358 } else { |
4322 final_branch_condition = not_equal; | |
4323 __ jmp(false_label); | 4359 __ jmp(false_label); |
4324 // A dead branch instruction will be generated after this point. | |
4325 } | 4360 } |
4326 | |
4327 return final_branch_condition; | 4361 return final_branch_condition; |
4328 } | 4362 } |
4329 | 4363 |
4330 | 4364 |
4331 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { | 4365 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
4332 Register temp = ToRegister(instr->TempAt(0)); | 4366 Register temp = ToRegister(instr->TempAt(0)); |
4333 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 4367 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
4334 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 4368 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
4335 | 4369 |
4336 EmitIsConstructCall(temp); | 4370 EmitIsConstructCall(temp); |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4489 env->deoptimization_index()); | 4523 env->deoptimization_index()); |
4490 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); | 4524 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); |
4491 } | 4525 } |
4492 | 4526 |
4493 | 4527 |
4494 #undef __ | 4528 #undef __ |
4495 | 4529 |
4496 } } // namespace v8::internal | 4530 } } // namespace v8::internal |
4497 | 4531 |
4498 #endif // V8_TARGET_ARCH_IA32 | 4532 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |