Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(341)

Side by Side Diff: src/arm/stub-cache-arm.cc

Issue 14142005: Implement Polymorphic Store ICs (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/ic-arm.cc ('k') | src/ast.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 419 matching lines...) Expand 10 before | Expand all | Expand 10 after
430 Handle<Cell> cell = GlobalObject::EnsurePropertyCell(global, name); 430 Handle<Cell> cell = GlobalObject::EnsurePropertyCell(global, name);
431 ASSERT(cell->value()->IsTheHole()); 431 ASSERT(cell->value()->IsTheHole());
432 __ mov(scratch, Operand(cell)); 432 __ mov(scratch, Operand(cell));
433 __ ldr(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); 433 __ ldr(scratch, FieldMemOperand(scratch, Cell::kValueOffset));
434 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 434 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
435 __ cmp(scratch, ip); 435 __ cmp(scratch, ip);
436 __ b(ne, miss); 436 __ b(ne, miss);
437 } 437 }
438 438
439 439
440 void BaseStoreStubCompiler::GenerateNegativeHolderLookup(
441 MacroAssembler* masm,
442 Handle<JSObject> holder,
443 Register holder_reg,
444 Handle<Name> name,
445 Label* miss) {
446 if (holder->IsJSGlobalObject()) {
447 GenerateCheckPropertyCell(
448 masm, Handle<GlobalObject>::cast(holder), name, scratch1(), miss);
449 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) {
450 GenerateDictionaryNegativeLookup(
451 masm, miss, holder_reg, name, scratch1(), scratch2());
452 }
453 }
454
455
440 // Generate StoreTransition code, value is passed in r0 register. 456 // Generate StoreTransition code, value is passed in r0 register.
441 // When leaving generated code after success, the receiver_reg and name_reg 457 // When leaving generated code after success, the receiver_reg and name_reg
442 // may be clobbered. Upon branch to miss_label, the receiver and name 458 // may be clobbered. Upon branch to miss_label, the receiver and name
443 // registers have their original values. 459 // registers have their original values.
444 void StubCompiler::GenerateStoreTransition(MacroAssembler* masm, 460 void BaseStoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
445 Handle<JSObject> object, 461 Handle<JSObject> object,
446 LookupResult* lookup, 462 LookupResult* lookup,
447 Handle<Map> transition, 463 Handle<Map> transition,
448 Handle<Name> name, 464 Handle<Name> name,
449 Register receiver_reg, 465 Register receiver_reg,
450 Register name_reg, 466 Register storage_reg,
451 Register value_reg, 467 Register value_reg,
452 Register scratch1, 468 Register scratch1,
453 Register scratch2, 469 Register scratch2,
454 Register scratch3, 470 Register scratch3,
455 Label* miss_label, 471 Label* miss_label,
456 Label* miss_restore_name, 472 Label* slow) {
457 Label* slow) {
458 // r0 : value 473 // r0 : value
459 Label exit; 474 Label exit;
460 475
461 // Check that the map of the object hasn't changed.
462 __ CheckMap(receiver_reg, scratch1, Handle<Map>(object->map()), miss_label,
463 DO_SMI_CHECK);
464
465 // Perform global security token check if needed.
466 if (object->IsJSGlobalProxy()) {
467 __ CheckAccessGlobalProxy(receiver_reg, scratch1, miss_label);
468 }
469
470 int descriptor = transition->LastAdded(); 476 int descriptor = transition->LastAdded();
471 DescriptorArray* descriptors = transition->instance_descriptors(); 477 DescriptorArray* descriptors = transition->instance_descriptors();
472 PropertyDetails details = descriptors->GetDetails(descriptor); 478 PropertyDetails details = descriptors->GetDetails(descriptor);
473 Representation representation = details.representation(); 479 Representation representation = details.representation();
474 ASSERT(!representation.IsNone()); 480 ASSERT(!representation.IsNone());
475 481
476 // Ensure no transitions to deprecated maps are followed.
477 __ CheckMapDeprecated(transition, scratch1, miss_label);
478
479 // Check that we are allowed to write this.
480 if (object->GetPrototype()->IsJSObject()) {
481 JSObject* holder;
482 // holder == object indicates that no property was found.
483 if (lookup->holder() != *object) {
484 holder = lookup->holder();
485 } else {
486 // Find the top object.
487 holder = *object;
488 do {
489 holder = JSObject::cast(holder->GetPrototype());
490 } while (holder->GetPrototype()->IsJSObject());
491 }
492 Register holder_reg = CheckPrototypes(
493 object, receiver_reg, Handle<JSObject>(holder), name_reg,
494 scratch1, scratch2, name, miss_restore_name, SKIP_RECEIVER);
495 // If no property was found, and the holder (the last object in the
496 // prototype chain) is in slow mode, we need to do a negative lookup on the
497 // holder.
498 if (lookup->holder() == *object) {
499 if (holder->IsJSGlobalObject()) {
500 GenerateCheckPropertyCell(
501 masm,
502 Handle<GlobalObject>(GlobalObject::cast(holder)),
503 name,
504 scratch1,
505 miss_restore_name);
506 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) {
507 GenerateDictionaryNegativeLookup(
508 masm, miss_restore_name, holder_reg, name, scratch1, scratch2);
509 }
510 }
511 }
512
513 Register storage_reg = name_reg;
514
515 if (details.type() == CONSTANT_FUNCTION) { 482 if (details.type() == CONSTANT_FUNCTION) {
516 Handle<HeapObject> constant( 483 Handle<HeapObject> constant(
517 HeapObject::cast(descriptors->GetValue(descriptor))); 484 HeapObject::cast(descriptors->GetValue(descriptor)));
518 __ LoadHeapObject(scratch1, constant); 485 __ LoadHeapObject(scratch1, constant);
519 __ cmp(value_reg, scratch1); 486 __ cmp(value_reg, scratch1);
520 __ b(ne, miss_restore_name); 487 __ b(ne, miss_label);
521 } else if (FLAG_track_fields && representation.IsSmi()) { 488 } else if (FLAG_track_fields && representation.IsSmi()) {
522 __ JumpIfNotSmi(value_reg, miss_restore_name); 489 __ JumpIfNotSmi(value_reg, miss_label);
523 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { 490 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
524 __ JumpIfSmi(value_reg, miss_restore_name); 491 __ JumpIfSmi(value_reg, miss_label);
525 } else if (FLAG_track_double_fields && representation.IsDouble()) { 492 } else if (FLAG_track_double_fields && representation.IsDouble()) {
526 Label do_store, heap_number; 493 Label do_store, heap_number;
527 __ LoadRoot(scratch3, Heap::kHeapNumberMapRootIndex); 494 __ LoadRoot(scratch3, Heap::kHeapNumberMapRootIndex);
528 __ AllocateHeapNumber(storage_reg, scratch1, scratch2, scratch3, slow); 495 __ AllocateHeapNumber(storage_reg, scratch1, scratch2, scratch3, slow);
529 496
530 __ JumpIfNotSmi(value_reg, &heap_number); 497 __ JumpIfNotSmi(value_reg, &heap_number);
531 __ SmiUntag(scratch1, value_reg); 498 __ SmiUntag(scratch1, value_reg);
532 __ vmov(s0, scratch1); 499 __ vmov(s0, scratch1);
533 __ vcvt_f64_s32(d0, s0); 500 __ vcvt_f64_s32(d0, s0);
534 __ jmp(&do_store); 501 __ jmp(&do_store);
535 502
536 __ bind(&heap_number); 503 __ bind(&heap_number);
537 __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, 504 __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex,
538 miss_restore_name, DONT_DO_SMI_CHECK); 505 miss_label, DONT_DO_SMI_CHECK);
539 __ vldr(d0, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); 506 __ vldr(d0, FieldMemOperand(value_reg, HeapNumber::kValueOffset));
540 507
541 __ bind(&do_store); 508 __ bind(&do_store);
542 __ vstr(d0, FieldMemOperand(storage_reg, HeapNumber::kValueOffset)); 509 __ vstr(d0, FieldMemOperand(storage_reg, HeapNumber::kValueOffset));
543 } 510 }
544 511
545 // Stub never generated for non-global objects that require access 512 // Stub never generated for non-global objects that require access
546 // checks. 513 // checks.
547 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 514 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
548 515
(...skipping 10 matching lines...) Expand all
559 masm->isolate()), 526 masm->isolate()),
560 3, 527 3,
561 1); 528 1);
562 return; 529 return;
563 } 530 }
564 531
565 // Update the map of the object. 532 // Update the map of the object.
566 __ mov(scratch1, Operand(transition)); 533 __ mov(scratch1, Operand(transition));
567 __ str(scratch1, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); 534 __ str(scratch1, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
568 535
569 // Update the write barrier for the map field and pass the now unused 536 // Update the write barrier for the map field.
570 // name_reg as scratch register.
571 __ RecordWriteField(receiver_reg, 537 __ RecordWriteField(receiver_reg,
572 HeapObject::kMapOffset, 538 HeapObject::kMapOffset,
573 scratch1, 539 scratch1,
574 scratch2, 540 scratch2,
575 kLRHasNotBeenSaved, 541 kLRHasNotBeenSaved,
576 kDontSaveFPRegs, 542 kDontSaveFPRegs,
577 OMIT_REMEMBERED_SET, 543 OMIT_REMEMBERED_SET,
578 OMIT_SMI_CHECK); 544 OMIT_SMI_CHECK);
579 545
580 if (details.type() == CONSTANT_FUNCTION) { 546 if (details.type() == CONSTANT_FUNCTION) {
(...skipping 20 matching lines...) Expand all
601 __ str(storage_reg, FieldMemOperand(receiver_reg, offset)); 567 __ str(storage_reg, FieldMemOperand(receiver_reg, offset));
602 } else { 568 } else {
603 __ str(value_reg, FieldMemOperand(receiver_reg, offset)); 569 __ str(value_reg, FieldMemOperand(receiver_reg, offset));
604 } 570 }
605 571
606 if (!FLAG_track_fields || !representation.IsSmi()) { 572 if (!FLAG_track_fields || !representation.IsSmi()) {
607 // Skip updating write barrier if storing a smi. 573 // Skip updating write barrier if storing a smi.
608 __ JumpIfSmi(value_reg, &exit); 574 __ JumpIfSmi(value_reg, &exit);
609 575
610 // Update the write barrier for the array address. 576 // Update the write barrier for the array address.
611 // Pass the now unused name_reg as a scratch register.
612 if (!FLAG_track_double_fields || !representation.IsDouble()) { 577 if (!FLAG_track_double_fields || !representation.IsDouble()) {
613 __ mov(name_reg, value_reg); 578 __ mov(storage_reg, value_reg);
614 } else {
615 ASSERT(storage_reg.is(name_reg));
616 } 579 }
617 __ RecordWriteField(receiver_reg, 580 __ RecordWriteField(receiver_reg,
618 offset, 581 offset,
619 name_reg, 582 storage_reg,
620 scratch1, 583 scratch1,
621 kLRHasNotBeenSaved, 584 kLRHasNotBeenSaved,
622 kDontSaveFPRegs, 585 kDontSaveFPRegs,
623 EMIT_REMEMBERED_SET, 586 EMIT_REMEMBERED_SET,
624 smi_check); 587 smi_check);
625 } 588 }
626 } else { 589 } else {
627 // Write to the properties array. 590 // Write to the properties array.
628 int offset = index * kPointerSize + FixedArray::kHeaderSize; 591 int offset = index * kPointerSize + FixedArray::kHeaderSize;
629 // Get the properties array 592 // Get the properties array
630 __ ldr(scratch1, 593 __ ldr(scratch1,
631 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); 594 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
632 if (FLAG_track_double_fields && representation.IsDouble()) { 595 if (FLAG_track_double_fields && representation.IsDouble()) {
633 __ str(storage_reg, FieldMemOperand(scratch1, offset)); 596 __ str(storage_reg, FieldMemOperand(scratch1, offset));
634 } else { 597 } else {
635 __ str(value_reg, FieldMemOperand(scratch1, offset)); 598 __ str(value_reg, FieldMemOperand(scratch1, offset));
636 } 599 }
637 600
638 if (!FLAG_track_fields || !representation.IsSmi()) { 601 if (!FLAG_track_fields || !representation.IsSmi()) {
639 // Skip updating write barrier if storing a smi. 602 // Skip updating write barrier if storing a smi.
640 __ JumpIfSmi(value_reg, &exit); 603 __ JumpIfSmi(value_reg, &exit);
641 604
642 // Update the write barrier for the array address. 605 // Update the write barrier for the array address.
643 // Ok to clobber receiver_reg and name_reg, since we return.
644 if (!FLAG_track_double_fields || !representation.IsDouble()) { 606 if (!FLAG_track_double_fields || !representation.IsDouble()) {
645 __ mov(name_reg, value_reg); 607 __ mov(storage_reg, value_reg);
646 } else {
647 ASSERT(storage_reg.is(name_reg));
648 } 608 }
649 __ RecordWriteField(scratch1, 609 __ RecordWriteField(scratch1,
650 offset, 610 offset,
651 name_reg, 611 storage_reg,
652 receiver_reg, 612 receiver_reg,
653 kLRHasNotBeenSaved, 613 kLRHasNotBeenSaved,
654 kDontSaveFPRegs, 614 kDontSaveFPRegs,
655 EMIT_REMEMBERED_SET, 615 EMIT_REMEMBERED_SET,
656 smi_check); 616 smi_check);
657 } 617 }
658 } 618 }
659 619
660 // Return the value (register r0). 620 // Return the value (register r0).
661 ASSERT(value_reg.is(r0)); 621 ASSERT(value_reg.is(r0));
662 __ bind(&exit); 622 __ bind(&exit);
663 __ Ret(); 623 __ Ret();
664 } 624 }
665 625
666 626
667 // Generate StoreField code, value is passed in r0 register. 627 // Generate StoreField code, value is passed in r0 register.
668 // When leaving generated code after success, the receiver_reg and name_reg 628 // When leaving generated code after success, the receiver_reg and name_reg
669 // may be clobbered. Upon branch to miss_label, the receiver and name 629 // may be clobbered. Upon branch to miss_label, the receiver and name
670 // registers have their original values. 630 // registers have their original values.
671 void StubCompiler::GenerateStoreField(MacroAssembler* masm, 631 void BaseStoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
672 Handle<JSObject> object, 632 Handle<JSObject> object,
673 LookupResult* lookup, 633 LookupResult* lookup,
674 Register receiver_reg, 634 Register receiver_reg,
675 Register name_reg, 635 Register name_reg,
676 Register value_reg, 636 Register value_reg,
677 Register scratch1, 637 Register scratch1,
678 Register scratch2, 638 Register scratch2,
679 Label* miss_label) { 639 Label* miss_label) {
680 // r0 : value 640 // r0 : value
681 Label exit; 641 Label exit;
682 642
683 // Check that the map of the object hasn't changed.
684 __ CheckMap(receiver_reg, scratch1, Handle<Map>(object->map()), miss_label,
685 DO_SMI_CHECK);
686
687 // Perform global security token check if needed.
688 if (object->IsJSGlobalProxy()) {
689 __ CheckAccessGlobalProxy(receiver_reg, scratch1, miss_label);
690 }
691
692 // Stub never generated for non-global objects that require access 643 // Stub never generated for non-global objects that require access
693 // checks. 644 // checks.
694 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 645 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
695 646
696 int index = lookup->GetFieldIndex().field_index(); 647 int index = lookup->GetFieldIndex().field_index();
697 648
698 // Adjust for the number of properties stored in the object. Even in the 649 // Adjust for the number of properties stored in the object. Even in the
699 // face of a transition we can use the old map here because the size of the 650 // face of a transition we can use the old map here because the size of the
700 // object and the number of in-object properties is not going to change. 651 // object and the number of in-object properties is not going to change.
701 index -= object->map()->inobject_properties(); 652 index -= object->map()->inobject_properties();
(...skipping 633 matching lines...) Expand 10 before | Expand all | Expand 10 after
1335 // If we've skipped any global objects, it's not enough to verify that 1286 // If we've skipped any global objects, it's not enough to verify that
1336 // their maps haven't changed. We also need to check that the property 1287 // their maps haven't changed. We also need to check that the property
1337 // cell for the property is still empty. 1288 // cell for the property is still empty.
1338 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); 1289 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss);
1339 1290
1340 // Return the register containing the holder. 1291 // Return the register containing the holder.
1341 return reg; 1292 return reg;
1342 } 1293 }
1343 1294
1344 1295
1345 void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success, 1296 void BaseLoadStubCompiler::HandlerFrontendFooter(Handle<Name> name,
1297 Label* success,
1346 Label* miss) { 1298 Label* miss) {
1347 if (!miss->is_unused()) { 1299 if (!miss->is_unused()) {
1348 __ b(success); 1300 __ b(success);
1349 __ bind(miss); 1301 __ bind(miss);
1350 TailCallBuiltin(masm(), MissBuiltin(kind())); 1302 TailCallBuiltin(masm(), MissBuiltin(kind()));
1351 } 1303 }
1352 } 1304 }
1353 1305
1354 1306
1307 void BaseStoreStubCompiler::HandlerFrontendFooter(Handle<Name> name,
1308 Label* success,
1309 Label* miss) {
1310 if (!miss->is_unused()) {
1311 __ b(success);
1312 GenerateRestoreName(masm(), miss, name);
1313 TailCallBuiltin(masm(), MissBuiltin(kind()));
1314 }
1315 }
1316
1317
1355 Register BaseLoadStubCompiler::CallbackHandlerFrontend( 1318 Register BaseLoadStubCompiler::CallbackHandlerFrontend(
1356 Handle<JSObject> object, 1319 Handle<JSObject> object,
1357 Register object_reg, 1320 Register object_reg,
1358 Handle<JSObject> holder, 1321 Handle<JSObject> holder,
1359 Handle<Name> name, 1322 Handle<Name> name,
1360 Label* success, 1323 Label* success,
1361 Handle<ExecutableAccessorInfo> callback) { 1324 Handle<ExecutableAccessorInfo> callback) {
1362 Label miss; 1325 Label miss;
1363 1326
1364 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); 1327 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss);
(...skipping 22 matching lines...) Expand all
1387 // pointer into the dictionary. Check that the value is the callback. 1350 // pointer into the dictionary. Check that the value is the callback.
1388 Register pointer = scratch3(); 1351 Register pointer = scratch3();
1389 const int kElementsStartOffset = NameDictionary::kHeaderSize + 1352 const int kElementsStartOffset = NameDictionary::kHeaderSize +
1390 NameDictionary::kElementsStartIndex * kPointerSize; 1353 NameDictionary::kElementsStartIndex * kPointerSize;
1391 const int kValueOffset = kElementsStartOffset + kPointerSize; 1354 const int kValueOffset = kElementsStartOffset + kPointerSize;
1392 __ ldr(scratch2(), FieldMemOperand(pointer, kValueOffset)); 1355 __ ldr(scratch2(), FieldMemOperand(pointer, kValueOffset));
1393 __ cmp(scratch2(), Operand(callback)); 1356 __ cmp(scratch2(), Operand(callback));
1394 __ b(ne, &miss); 1357 __ b(ne, &miss);
1395 } 1358 }
1396 1359
1397 HandlerFrontendFooter(success, &miss); 1360 HandlerFrontendFooter(name, success, &miss);
1398 return reg; 1361 return reg;
1399 } 1362 }
1400 1363
1401 1364
1402 void BaseLoadStubCompiler::NonexistentHandlerFrontend( 1365 void BaseLoadStubCompiler::NonexistentHandlerFrontend(
1403 Handle<JSObject> object, 1366 Handle<JSObject> object,
1404 Handle<JSObject> last, 1367 Handle<JSObject> last,
1405 Handle<Name> name, 1368 Handle<Name> name,
1406 Label* success, 1369 Label* success,
1407 Handle<GlobalObject> global) { 1370 Handle<GlobalObject> global) {
1408 Label miss; 1371 Label miss;
1409 1372
1410 HandlerFrontendHeader(object, receiver(), last, name, &miss); 1373 HandlerFrontendHeader(object, receiver(), last, name, &miss);
1411 1374
1412 // If the last object in the prototype chain is a global object, 1375 // If the last object in the prototype chain is a global object,
1413 // check that the global property cell is empty. 1376 // check that the global property cell is empty.
1414 if (!global.is_null()) { 1377 if (!global.is_null()) {
1415 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); 1378 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss);
1416 } 1379 }
1417 1380
1418 HandlerFrontendFooter(success, &miss); 1381 HandlerFrontendFooter(name, success, &miss);
1419 } 1382 }
1420 1383
1421 1384
1422 void BaseLoadStubCompiler::GenerateLoadField(Register reg, 1385 void BaseLoadStubCompiler::GenerateLoadField(Register reg,
1423 Handle<JSObject> holder, 1386 Handle<JSObject> holder,
1424 PropertyIndex field, 1387 PropertyIndex field,
1425 Representation representation) { 1388 Representation representation) {
1426 if (!reg.is(receiver())) __ mov(receiver(), reg); 1389 if (!reg.is(receiver())) __ mov(receiver(), reg);
1427 if (kind() == Code::LOAD_IC) { 1390 if (kind() == Code::LOAD_IC) {
1428 LoadFieldStub stub(field.is_inobject(holder), 1391 LoadFieldStub stub(field.is_inobject(holder),
(...skipping 1388 matching lines...) Expand 10 before | Expand all | Expand 10 after
2817 __ bind(&miss); 2780 __ bind(&miss);
2818 __ IncrementCounter(counters->call_global_inline_miss(), 1, r1, r3); 2781 __ IncrementCounter(counters->call_global_inline_miss(), 1, r1, r3);
2819 GenerateMissBranch(); 2782 GenerateMissBranch();
2820 2783
2821 // Return the generated code. 2784 // Return the generated code.
2822 return GetCode(Code::NORMAL, name); 2785 return GetCode(Code::NORMAL, name);
2823 } 2786 }
2824 2787
2825 2788
2826 Handle<Code> StoreStubCompiler::CompileStoreCallback( 2789 Handle<Code> StoreStubCompiler::CompileStoreCallback(
2827 Handle<Name> name,
2828 Handle<JSObject> object, 2790 Handle<JSObject> object,
2829 Handle<JSObject> holder, 2791 Handle<JSObject> holder,
2792 Handle<Name> name,
2830 Handle<ExecutableAccessorInfo> callback) { 2793 Handle<ExecutableAccessorInfo> callback) {
2831 Label miss; 2794 Label success;
2832 // Check that the maps haven't changed. 2795 HandlerFrontend(object, receiver(), holder, name, &success);
2833 __ JumpIfSmi(receiver(), &miss); 2796 __ bind(&success);
2834 CheckPrototypes(object, receiver(), holder,
2835 scratch1(), scratch2(), scratch3(), name, &miss);
2836 2797
2837 // Stub never generated for non-global objects that require access checks. 2798 // Stub never generated for non-global objects that require access checks.
2838 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); 2799 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
2839 2800
2840 __ push(receiver()); // receiver 2801 __ push(receiver()); // receiver
2841 __ mov(ip, Operand(callback)); // callback info 2802 __ mov(ip, Operand(callback)); // callback info
2842 __ Push(ip, this->name(), value()); 2803 __ push(ip);
2804 __ mov(ip, Operand(name));
2805 __ Push(ip, value());
2843 2806
2844 // Do tail-call to the runtime system. 2807 // Do tail-call to the runtime system.
2845 ExternalReference store_callback_property = 2808 ExternalReference store_callback_property =
2846 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); 2809 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate());
2847 __ TailCallExternalReference(store_callback_property, 4, 1); 2810 __ TailCallExternalReference(store_callback_property, 4, 1);
2848 2811
2849 // Handle store cache miss.
2850 __ bind(&miss);
2851 TailCallBuiltin(masm(), MissBuiltin(kind()));
2852
2853 // Return the generated code. 2812 // Return the generated code.
2854 return GetICCode(kind(), Code::CALLBACKS, name); 2813 return GetCode(kind(), Code::CALLBACKS, name);
2855 } 2814 }
2856 2815
2857 2816
2858 #undef __ 2817 #undef __
2859 #define __ ACCESS_MASM(masm) 2818 #define __ ACCESS_MASM(masm)
2860 2819
2861 2820
2862 void StoreStubCompiler::GenerateStoreViaSetter( 2821 void StoreStubCompiler::GenerateStoreViaSetter(
2863 MacroAssembler* masm, 2822 MacroAssembler* masm,
2864 Handle<JSFunction> setter) { 2823 Handle<JSFunction> setter) {
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
3098 __ mov(r3, Operand(cell)); 3057 __ mov(r3, Operand(cell));
3099 __ ldr(r4, FieldMemOperand(r3, Cell::kValueOffset)); 3058 __ ldr(r4, FieldMemOperand(r3, Cell::kValueOffset));
3100 3059
3101 // Check for deleted property if property can actually be deleted. 3060 // Check for deleted property if property can actually be deleted.
3102 if (!is_dont_delete) { 3061 if (!is_dont_delete) {
3103 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 3062 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
3104 __ cmp(r4, ip); 3063 __ cmp(r4, ip);
3105 __ b(eq, &miss); 3064 __ b(eq, &miss);
3106 } 3065 }
3107 3066
3108 HandlerFrontendFooter(&success, &miss); 3067 HandlerFrontendFooter(name, &success, &miss);
3109 __ bind(&success); 3068 __ bind(&success);
3110 3069
3111 Counters* counters = isolate()->counters(); 3070 Counters* counters = isolate()->counters();
3112 __ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3); 3071 __ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3);
3113 __ mov(r0, r4); 3072 __ mov(r0, r4);
3114 __ Ret(); 3073 __ Ret();
3115 3074
3116 // Return the generated code. 3075 // Return the generated code.
3117 return GetICCode(kind(), Code::NORMAL, name); 3076 return GetICCode(kind(), Code::NORMAL, name);
3118 } 3077 }
3119 3078
3120 3079
3121 Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC( 3080 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC(
3122 MapHandleList* receiver_maps, 3081 MapHandleList* receiver_maps,
3123 CodeHandleList* handlers, 3082 CodeHandleList* handlers,
3124 Handle<Name> name, 3083 Handle<Name> name,
3125 Code::StubType type, 3084 Code::StubType type,
3126 IcCheckType check) { 3085 IcCheckType check) {
3127 Label miss; 3086 Label miss;
3128 3087
3129 if (check == PROPERTY) { 3088 if (check == PROPERTY) {
3130 GenerateNameCheck(name, this->name(), &miss); 3089 GenerateNameCheck(name, this->name(), &miss);
3131 } 3090 }
(...skipping 603 matching lines...) Expand 10 before | Expand all | Expand 10 after
3735 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); 3694 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
3736 } 3695 }
3737 } 3696 }
3738 3697
3739 3698
3740 #undef __ 3699 #undef __
3741 3700
3742 } } // namespace v8::internal 3701 } } // namespace v8::internal
3743 3702
3744 #endif // V8_TARGET_ARCH_ARM 3703 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/ic-arm.cc ('k') | src/ast.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698