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 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
416 __ Ret(); | 416 __ Ret(); |
417 } | 417 } |
418 | 418 |
419 | 419 |
420 // Generate StoreField code, value is passed in r0 register. | 420 // Generate StoreField code, value is passed in r0 register. |
421 // When leaving generated code after success, the receiver_reg and name_reg | 421 // When leaving generated code after success, the receiver_reg and name_reg |
422 // may be clobbered. Upon branch to miss_label, the receiver and name | 422 // may be clobbered. Upon branch to miss_label, the receiver and name |
423 // registers have their original values. | 423 // registers have their original values. |
424 void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 424 void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
425 Handle<JSObject> object, | 425 Handle<JSObject> object, |
426 int index, | 426 LookupResult* lookup, |
427 Handle<Map> transition, | 427 Handle<Map> transition, |
428 Handle<Name> name, | 428 Handle<Name> name, |
429 Register receiver_reg, | 429 Register receiver_reg, |
430 Register name_reg, | 430 Register name_reg, |
431 Register value_reg, | 431 Register value_reg, |
432 Register scratch1, | 432 Register scratch1, |
433 Register scratch2, | 433 Register scratch2, |
434 Label* miss_label, | 434 Label* miss_label, |
435 Label* miss_restore_name) { | 435 Label* miss_restore_name) { |
436 // r0 : value | 436 // r0 : value |
437 Label exit; | 437 Label exit; |
438 | 438 |
439 LookupResult lookup(masm->isolate()); | |
440 object->Lookup(*name, &lookup); | |
441 if (lookup.IsFound() && (lookup.IsReadOnly() || !lookup.IsCacheable())) { | |
442 // In sloppy mode, we could just return the value and be done. However, we | |
443 // might be in strict mode, where we have to throw. Since we cannot tell, | |
444 // go into slow case unconditionally. | |
445 __ jmp(miss_label); | |
446 return; | |
447 } | |
448 | |
449 // Check that the map of the object hasn't changed. | 439 // Check that the map of the object hasn't changed. |
450 CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS | 440 CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS |
451 : REQUIRE_EXACT_MAP; | 441 : REQUIRE_EXACT_MAP; |
452 __ CheckMap(receiver_reg, scratch1, Handle<Map>(object->map()), miss_label, | 442 __ CheckMap(receiver_reg, scratch1, Handle<Map>(object->map()), miss_label, |
453 DO_SMI_CHECK, mode); | 443 DO_SMI_CHECK, mode); |
454 | 444 |
455 // Perform global security token check if needed. | 445 // Perform global security token check if needed. |
456 if (object->IsJSGlobalProxy()) { | 446 if (object->IsJSGlobalProxy()) { |
457 __ CheckAccessGlobalProxy(receiver_reg, scratch1, miss_label); | 447 __ CheckAccessGlobalProxy(receiver_reg, scratch1, miss_label); |
458 } | 448 } |
459 | 449 |
460 // Check that we are allowed to write this. | 450 // Check that we are allowed to write this. |
461 if (!transition.is_null() && object->GetPrototype()->IsJSObject()) { | 451 if (!transition.is_null() && object->GetPrototype()->IsJSObject()) { |
462 JSObject* holder; | 452 JSObject* holder; |
463 if (lookup.IsFound()) { | 453 if (lookup->IsFound()) { |
464 holder = lookup.holder(); | 454 holder = lookup->holder(); |
465 } else { | 455 } else { |
466 // Find the top object. | 456 // Find the top object. |
467 holder = *object; | 457 holder = *object; |
468 do { | 458 do { |
469 holder = JSObject::cast(holder->GetPrototype()); | 459 holder = JSObject::cast(holder->GetPrototype()); |
470 } while (holder->GetPrototype()->IsJSObject()); | 460 } while (holder->GetPrototype()->IsJSObject()); |
471 } | 461 } |
472 CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg, | 462 CheckPrototypes(object, receiver_reg, Handle<JSObject>(holder), name_reg, |
473 scratch1, scratch2, name, miss_restore_name); | 463 scratch1, scratch2, name, miss_restore_name); |
474 } | 464 } |
(...skipping 10 matching lines...) Expand all Loading... |
485 __ mov(r2, Operand(transition)); | 475 __ mov(r2, Operand(transition)); |
486 __ Push(r2, r0); | 476 __ Push(r2, r0); |
487 __ TailCallExternalReference( | 477 __ TailCallExternalReference( |
488 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), | 478 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), |
489 masm->isolate()), | 479 masm->isolate()), |
490 3, | 480 3, |
491 1); | 481 1); |
492 return; | 482 return; |
493 } | 483 } |
494 | 484 |
| 485 int index; |
495 if (!transition.is_null()) { | 486 if (!transition.is_null()) { |
496 // Update the map of the object. | 487 // Update the map of the object. |
497 __ mov(scratch1, Operand(transition)); | 488 __ mov(scratch1, Operand(transition)); |
498 __ str(scratch1, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); | 489 __ str(scratch1, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); |
499 | 490 |
500 // Update the write barrier for the map field and pass the now unused | 491 // Update the write barrier for the map field and pass the now unused |
501 // name_reg as scratch register. | 492 // name_reg as scratch register. |
502 __ RecordWriteField(receiver_reg, | 493 __ RecordWriteField(receiver_reg, |
503 HeapObject::kMapOffset, | 494 HeapObject::kMapOffset, |
504 scratch1, | 495 scratch1, |
505 name_reg, | 496 name_reg, |
506 kLRHasNotBeenSaved, | 497 kLRHasNotBeenSaved, |
507 kDontSaveFPRegs, | 498 kDontSaveFPRegs, |
508 OMIT_REMEMBERED_SET, | 499 OMIT_REMEMBERED_SET, |
509 OMIT_SMI_CHECK); | 500 OMIT_SMI_CHECK); |
| 501 index = transition->instance_descriptors()->GetFieldIndex( |
| 502 transition->LastAdded()); |
| 503 } else { |
| 504 index = lookup->GetFieldIndex().field_index(); |
510 } | 505 } |
511 | 506 |
512 // Adjust for the number of properties stored in the object. Even in the | 507 // Adjust for the number of properties stored in the object. Even in the |
513 // face of a transition we can use the old map here because the size of the | 508 // face of a transition we can use the old map here because the size of the |
514 // object and the number of in-object properties is not going to change. | 509 // object and the number of in-object properties is not going to change. |
515 index -= object->map()->inobject_properties(); | 510 index -= object->map()->inobject_properties(); |
516 | 511 |
517 if (index < 0) { | 512 if (index < 0) { |
518 // Set the property straight into the object. | 513 // Set the property straight into the object. |
519 int offset = object->map()->instance_size() + (index * kPointerSize); | 514 int offset = object->map()->instance_size() + (index * kPointerSize); |
(...skipping 3322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3842 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); | 3837 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); |
3843 } | 3838 } |
3844 } | 3839 } |
3845 | 3840 |
3846 | 3841 |
3847 #undef __ | 3842 #undef __ |
3848 | 3843 |
3849 } } // namespace v8::internal | 3844 } } // namespace v8::internal |
3850 | 3845 |
3851 #endif // V8_TARGET_ARCH_ARM | 3846 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |