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 2233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2244 FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); | 2244 FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); |
2245 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 2245 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
2246 __ cmp(scratch2, ip); | 2246 __ cmp(scratch2, ip); |
2247 DeoptimizeIf(eq, instr->environment()); | 2247 DeoptimizeIf(eq, instr->environment()); |
2248 } | 2248 } |
2249 | 2249 |
2250 // Store the value. | 2250 // Store the value. |
2251 __ str(value, FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); | 2251 __ str(value, FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); |
2252 | 2252 |
2253 // Cells are always in the remembered set. | 2253 // Cells are always in the remembered set. |
2254 __ RecordWriteField(scratch, | 2254 if (instr->hydrogen()->NeedsWriteBarrier()) { |
2255 JSGlobalPropertyCell::kValueOffset, | 2255 HType type = instr->hydrogen()->value()->type(); |
2256 value, | 2256 SmiCheck check_needed = |
2257 scratch2, | 2257 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
2258 kLRHasBeenSaved, | 2258 __ RecordWriteField(scratch, |
2259 kSaveFPRegs, | 2259 JSGlobalPropertyCell::kValueOffset, |
2260 OMIT_REMEMBERED_SET); | 2260 value, |
| 2261 scratch2, |
| 2262 kLRHasBeenSaved, |
| 2263 kSaveFPRegs, |
| 2264 OMIT_REMEMBERED_SET, |
| 2265 check_needed); |
| 2266 } |
2261 } | 2267 } |
2262 | 2268 |
2263 | 2269 |
2264 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { | 2270 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { |
2265 ASSERT(ToRegister(instr->global_object()).is(r1)); | 2271 ASSERT(ToRegister(instr->global_object()).is(r1)); |
2266 ASSERT(ToRegister(instr->value()).is(r0)); | 2272 ASSERT(ToRegister(instr->value()).is(r0)); |
2267 | 2273 |
2268 __ mov(r2, Operand(instr->name())); | 2274 __ mov(r2, Operand(instr->name())); |
2269 Handle<Code> ic = instr->strict_mode() | 2275 Handle<Code> ic = instr->strict_mode() |
2270 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 2276 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
2271 : isolate()->builtins()->StoreIC_Initialize(); | 2277 : isolate()->builtins()->StoreIC_Initialize(); |
2272 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); | 2278 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); |
2273 } | 2279 } |
2274 | 2280 |
2275 | 2281 |
2276 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { | 2282 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { |
2277 Register context = ToRegister(instr->context()); | 2283 Register context = ToRegister(instr->context()); |
2278 Register result = ToRegister(instr->result()); | 2284 Register result = ToRegister(instr->result()); |
2279 __ ldr(result, ContextOperand(context, instr->slot_index())); | 2285 __ ldr(result, ContextOperand(context, instr->slot_index())); |
2280 } | 2286 } |
2281 | 2287 |
2282 | 2288 |
2283 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { | 2289 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { |
2284 Register context = ToRegister(instr->context()); | 2290 Register context = ToRegister(instr->context()); |
2285 Register value = ToRegister(instr->value()); | 2291 Register value = ToRegister(instr->value()); |
2286 MemOperand target = ContextOperand(context, instr->slot_index()); | 2292 MemOperand target = ContextOperand(context, instr->slot_index()); |
2287 __ str(value, target); | 2293 __ str(value, target); |
2288 if (instr->needs_write_barrier()) { | 2294 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 2295 HType type = instr->hydrogen()->value()->type(); |
| 2296 SmiCheck check_needed = |
| 2297 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
2289 __ RecordWriteContextSlot(context, | 2298 __ RecordWriteContextSlot(context, |
2290 target.offset(), | 2299 target.offset(), |
2291 value, | 2300 value, |
2292 scratch0(), | 2301 scratch0(), |
2293 kLRHasBeenSaved, | 2302 kLRHasBeenSaved, |
2294 kSaveFPRegs); | 2303 kSaveFPRegs, |
| 2304 EMIT_REMEMBERED_SET, |
| 2305 check_needed); |
2295 } | 2306 } |
2296 } | 2307 } |
2297 | 2308 |
2298 | 2309 |
2299 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 2310 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
2300 Register object = ToRegister(instr->InputAt(0)); | 2311 Register object = ToRegister(instr->InputAt(0)); |
2301 Register result = ToRegister(instr->result()); | 2312 Register result = ToRegister(instr->result()); |
2302 if (instr->hydrogen()->is_in_object()) { | 2313 if (instr->hydrogen()->is_in_object()) { |
2303 __ ldr(result, FieldMemOperand(object, instr->hydrogen()->offset())); | 2314 __ ldr(result, FieldMemOperand(object, instr->hydrogen()->offset())); |
2304 } else { | 2315 } else { |
(...skipping 985 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3290 int offset = instr->offset(); | 3301 int offset = instr->offset(); |
3291 | 3302 |
3292 ASSERT(!object.is(value)); | 3303 ASSERT(!object.is(value)); |
3293 | 3304 |
3294 if (!instr->transition().is_null()) { | 3305 if (!instr->transition().is_null()) { |
3295 __ mov(scratch, Operand(instr->transition())); | 3306 __ mov(scratch, Operand(instr->transition())); |
3296 __ str(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); | 3307 __ str(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); |
3297 } | 3308 } |
3298 | 3309 |
3299 // Do the store. | 3310 // Do the store. |
| 3311 HType type = instr->hydrogen()->value()->type(); |
| 3312 SmiCheck check_needed = |
| 3313 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
3300 if (instr->is_in_object()) { | 3314 if (instr->is_in_object()) { |
3301 __ str(value, FieldMemOperand(object, offset)); | 3315 __ str(value, FieldMemOperand(object, offset)); |
3302 if (instr->needs_write_barrier()) { | 3316 if (instr->hydrogen()->NeedsWriteBarrier()) { |
3303 // Update the write barrier for the object for in-object properties. | 3317 // Update the write barrier for the object for in-object properties. |
3304 __ RecordWriteField( | 3318 __ RecordWriteField(object, |
3305 object, offset, value, scratch, kLRHasBeenSaved, kSaveFPRegs); | 3319 offset, |
| 3320 value, |
| 3321 scratch, |
| 3322 kLRHasBeenSaved, |
| 3323 kSaveFPRegs, |
| 3324 EMIT_REMEMBERED_SET, |
| 3325 check_needed); |
3306 } | 3326 } |
3307 } else { | 3327 } else { |
3308 __ ldr(scratch, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 3328 __ ldr(scratch, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
3309 __ str(value, FieldMemOperand(scratch, offset)); | 3329 __ str(value, FieldMemOperand(scratch, offset)); |
3310 if (instr->needs_write_barrier()) { | 3330 if (instr->hydrogen()->NeedsWriteBarrier()) { |
3311 // Update the write barrier for the properties array. | 3331 // Update the write barrier for the properties array. |
3312 // object is used as a scratch register. | 3332 // object is used as a scratch register. |
3313 __ RecordWriteField( | 3333 __ RecordWriteField(scratch, |
3314 scratch, offset, value, object, kLRHasBeenSaved, kSaveFPRegs); | 3334 offset, |
| 3335 value, |
| 3336 object, |
| 3337 kLRHasBeenSaved, |
| 3338 kSaveFPRegs, |
| 3339 EMIT_REMEMBERED_SET, |
| 3340 check_needed); |
3315 } | 3341 } |
3316 } | 3342 } |
3317 } | 3343 } |
3318 | 3344 |
3319 | 3345 |
3320 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { | 3346 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { |
3321 ASSERT(ToRegister(instr->object()).is(r1)); | 3347 ASSERT(ToRegister(instr->object()).is(r1)); |
3322 ASSERT(ToRegister(instr->value()).is(r0)); | 3348 ASSERT(ToRegister(instr->value()).is(r0)); |
3323 | 3349 |
3324 // Name is always in r2. | 3350 // Name is always in r2. |
(...skipping 30 matching lines...) Expand all Loading... |
3355 LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); | 3381 LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); |
3356 int offset = | 3382 int offset = |
3357 ToInteger32(const_operand) * kPointerSize + FixedArray::kHeaderSize; | 3383 ToInteger32(const_operand) * kPointerSize + FixedArray::kHeaderSize; |
3358 __ str(value, FieldMemOperand(elements, offset)); | 3384 __ str(value, FieldMemOperand(elements, offset)); |
3359 } else { | 3385 } else { |
3360 __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); | 3386 __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); |
3361 __ str(value, FieldMemOperand(scratch, FixedArray::kHeaderSize)); | 3387 __ str(value, FieldMemOperand(scratch, FixedArray::kHeaderSize)); |
3362 } | 3388 } |
3363 | 3389 |
3364 if (instr->hydrogen()->NeedsWriteBarrier()) { | 3390 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 3391 HType type = instr->hydrogen()->value()->type(); |
| 3392 SmiCheck check_needed = |
| 3393 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
3365 // Compute address of modified element and store it into key register. | 3394 // Compute address of modified element and store it into key register. |
3366 __ add(key, scratch, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 3395 __ add(key, scratch, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
3367 __ RecordWrite(elements, key, value, kLRHasBeenSaved, kSaveFPRegs); | 3396 __ RecordWrite(elements, |
| 3397 key, |
| 3398 value, |
| 3399 kLRHasBeenSaved, |
| 3400 kSaveFPRegs, |
| 3401 EMIT_REMEMBERED_SET, |
| 3402 check_needed); |
3368 } | 3403 } |
3369 } | 3404 } |
3370 | 3405 |
3371 | 3406 |
3372 void LCodeGen::DoStoreKeyedFastDoubleElement( | 3407 void LCodeGen::DoStoreKeyedFastDoubleElement( |
3373 LStoreKeyedFastDoubleElement* instr) { | 3408 LStoreKeyedFastDoubleElement* instr) { |
3374 DwVfpRegister value = ToDoubleRegister(instr->value()); | 3409 DwVfpRegister value = ToDoubleRegister(instr->value()); |
3375 Register elements = ToRegister(instr->elements()); | 3410 Register elements = ToRegister(instr->elements()); |
3376 Register key = no_reg; | 3411 Register key = no_reg; |
3377 Register scratch = scratch0(); | 3412 Register scratch = scratch0(); |
(...skipping 964 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4342 Register input = ToRegister(instr->InputAt(0)); | 4377 Register input = ToRegister(instr->InputAt(0)); |
4343 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 4378 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
4344 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 4379 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
4345 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 4380 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
4346 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 4381 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
4347 | 4382 |
4348 Condition final_branch_condition = EmitTypeofIs(true_label, | 4383 Condition final_branch_condition = EmitTypeofIs(true_label, |
4349 false_label, | 4384 false_label, |
4350 input, | 4385 input, |
4351 instr->type_literal()); | 4386 instr->type_literal()); |
4352 | 4387 if (final_branch_condition != kNoCondition) { |
4353 EmitBranch(true_block, false_block, final_branch_condition); | 4388 EmitBranch(true_block, false_block, final_branch_condition); |
| 4389 } |
4354 } | 4390 } |
4355 | 4391 |
4356 | 4392 |
4357 Condition LCodeGen::EmitTypeofIs(Label* true_label, | 4393 Condition LCodeGen::EmitTypeofIs(Label* true_label, |
4358 Label* false_label, | 4394 Label* false_label, |
4359 Register input, | 4395 Register input, |
4360 Handle<String> type_name) { | 4396 Handle<String> type_name) { |
4361 Condition final_branch_condition = kNoCondition; | 4397 Condition final_branch_condition = kNoCondition; |
4362 Register scratch = scratch0(); | 4398 Register scratch = scratch0(); |
4363 if (type_name->Equals(heap()->number_symbol())) { | 4399 if (type_name->Equals(heap()->number_symbol())) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4413 FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); | 4449 FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); |
4414 __ b(lt, false_label); | 4450 __ b(lt, false_label); |
4415 __ CompareInstanceType(input, scratch, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); | 4451 __ CompareInstanceType(input, scratch, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); |
4416 __ b(gt, false_label); | 4452 __ b(gt, false_label); |
4417 // Check for undetectable objects => false. | 4453 // Check for undetectable objects => false. |
4418 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset)); | 4454 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset)); |
4419 __ tst(ip, Operand(1 << Map::kIsUndetectable)); | 4455 __ tst(ip, Operand(1 << Map::kIsUndetectable)); |
4420 final_branch_condition = eq; | 4456 final_branch_condition = eq; |
4421 | 4457 |
4422 } else { | 4458 } else { |
4423 final_branch_condition = ne; | |
4424 __ b(false_label); | 4459 __ b(false_label); |
4425 // A dead branch instruction will be generated after this point. | |
4426 } | 4460 } |
4427 | 4461 |
4428 return final_branch_condition; | 4462 return final_branch_condition; |
4429 } | 4463 } |
4430 | 4464 |
4431 | 4465 |
4432 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { | 4466 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
4433 Register temp1 = ToRegister(instr->TempAt(0)); | 4467 Register temp1 = ToRegister(instr->TempAt(0)); |
4434 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 4468 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
4435 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 4469 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4566 ASSERT(osr_pc_offset_ == -1); | 4600 ASSERT(osr_pc_offset_ == -1); |
4567 osr_pc_offset_ = masm()->pc_offset(); | 4601 osr_pc_offset_ = masm()->pc_offset(); |
4568 } | 4602 } |
4569 | 4603 |
4570 | 4604 |
4571 | 4605 |
4572 | 4606 |
4573 #undef __ | 4607 #undef __ |
4574 | 4608 |
4575 } } // namespace v8::internal | 4609 } } // namespace v8::internal |
OLD | NEW |