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

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

Issue 18595006: MIPS: Implement Polymorphic Store ICs. (Closed) Base URL: https://github.com/v8/v8.git@gbl
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
« no previous file with comments | « src/mips/ic-mips.cc ('k') | no next file » | 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 411 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 Label* miss) { 422 Label* miss) {
423 Handle<Cell> cell = GlobalObject::EnsurePropertyCell(global, name); 423 Handle<Cell> cell = GlobalObject::EnsurePropertyCell(global, name);
424 ASSERT(cell->value()->IsTheHole()); 424 ASSERT(cell->value()->IsTheHole());
425 __ li(scratch, Operand(cell)); 425 __ li(scratch, Operand(cell));
426 __ lw(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); 426 __ lw(scratch, FieldMemOperand(scratch, Cell::kValueOffset));
427 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 427 __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
428 __ Branch(miss, ne, scratch, Operand(at)); 428 __ Branch(miss, ne, scratch, Operand(at));
429 } 429 }
430 430
431 431
432 void BaseStoreStubCompiler::GenerateNegativeHolderLookup(
433 MacroAssembler* masm,
434 Handle<JSObject> holder,
435 Register holder_reg,
436 Handle<Name> name,
437 Label* miss) {
438 if (holder->IsJSGlobalObject()) {
439 GenerateCheckPropertyCell(
440 masm, Handle<GlobalObject>::cast(holder), name, scratch1(), miss);
441 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) {
442 GenerateDictionaryNegativeLookup(
443 masm, miss, holder_reg, name, scratch1(), scratch2());
444 }
445 }
446
447
432 // Generate StoreTransition code, value is passed in a0 register. 448 // Generate StoreTransition code, value is passed in a0 register.
433 // After executing generated code, the receiver_reg and name_reg 449 // After executing generated code, the receiver_reg and name_reg
434 // may be clobbered. 450 // may be clobbered.
435 void StubCompiler::GenerateStoreTransition(MacroAssembler* masm, 451 void BaseStoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
436 Handle<JSObject> object, 452 Handle<JSObject> object,
437 LookupResult* lookup, 453 LookupResult* lookup,
438 Handle<Map> transition, 454 Handle<Map> transition,
439 Handle<Name> name, 455 Handle<Name> name,
440 Register receiver_reg, 456 Register receiver_reg,
441 Register name_reg, 457 Register storage_reg,
442 Register value_reg, 458 Register value_reg,
443 Register scratch1, 459 Register scratch1,
444 Register scratch2, 460 Register scratch2,
445 Register scratch3, 461 Register scratch3,
446 Label* miss_label, 462 Label* miss_label,
447 Label* miss_restore_name, 463 Label* slow) {
448 Label* slow) {
449 // a0 : value. 464 // a0 : value.
450 Label exit; 465 Label exit;
451 466
452 // Check that the map of the object hasn't changed.
453 __ CheckMap(receiver_reg, scratch1, Handle<Map>(object->map()), miss_label,
454 DO_SMI_CHECK);
455
456 // Perform global security token check if needed.
457 if (object->IsJSGlobalProxy()) {
458 __ CheckAccessGlobalProxy(receiver_reg, scratch1, miss_label);
459 }
460
461 int descriptor = transition->LastAdded(); 467 int descriptor = transition->LastAdded();
462 DescriptorArray* descriptors = transition->instance_descriptors(); 468 DescriptorArray* descriptors = transition->instance_descriptors();
463 PropertyDetails details = descriptors->GetDetails(descriptor); 469 PropertyDetails details = descriptors->GetDetails(descriptor);
464 Representation representation = details.representation(); 470 Representation representation = details.representation();
465 ASSERT(!representation.IsNone()); 471 ASSERT(!representation.IsNone());
466 472
467 // Ensure no transitions to deprecated maps are followed.
468 __ CheckMapDeprecated(transition, scratch1, miss_label);
469
470 // Check that we are allowed to write this.
471 if (object->GetPrototype()->IsJSObject()) {
472 JSObject* holder;
473 // holder == object indicates that no property was found.
474 if (lookup->holder() != *object) {
475 holder = lookup->holder();
476 } else {
477 // Find the top object.
478 holder = *object;
479 do {
480 holder = JSObject::cast(holder->GetPrototype());
481 } while (holder->GetPrototype()->IsJSObject());
482 }
483 Register holder_reg = CheckPrototypes(
484 object, receiver_reg, Handle<JSObject>(holder), name_reg,
485 scratch1, scratch2, name, miss_restore_name, SKIP_RECEIVER);
486 // If no property was found, and the holder (the last object in the
487 // prototype chain) is in slow mode, we need to do a negative lookup on the
488 // holder.
489 if (lookup->holder() == *object) {
490 if (holder->IsJSGlobalObject()) {
491 GenerateCheckPropertyCell(
492 masm,
493 Handle<GlobalObject>(GlobalObject::cast(holder)),
494 name,
495 scratch1,
496 miss_restore_name);
497 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) {
498 GenerateDictionaryNegativeLookup(
499 masm, miss_restore_name, holder_reg, name, scratch1, scratch2);
500 }
501 }
502 }
503
504 Register storage_reg = name_reg;
505
506 if (details.type() == CONSTANT_FUNCTION) { 473 if (details.type() == CONSTANT_FUNCTION) {
507 Handle<HeapObject> constant( 474 Handle<HeapObject> constant(
508 HeapObject::cast(descriptors->GetValue(descriptor))); 475 HeapObject::cast(descriptors->GetValue(descriptor)));
509 __ LoadHeapObject(scratch1, constant); 476 __ LoadHeapObject(scratch1, constant);
510 __ Branch(miss_restore_name, ne, value_reg, Operand(scratch1)); 477 __ Branch(miss_label, ne, value_reg, Operand(scratch1));
511 } else if (FLAG_track_fields && representation.IsSmi()) { 478 } else if (FLAG_track_fields && representation.IsSmi()) {
512 __ JumpIfNotSmi(value_reg, miss_restore_name); 479 __ JumpIfNotSmi(value_reg, miss_label);
513 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { 480 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) {
514 __ JumpIfSmi(value_reg, miss_restore_name); 481 __ JumpIfSmi(value_reg, miss_label);
515 } else if (FLAG_track_double_fields && representation.IsDouble()) { 482 } else if (FLAG_track_double_fields && representation.IsDouble()) {
516 Label do_store, heap_number; 483 Label do_store, heap_number;
517 __ LoadRoot(scratch3, Heap::kHeapNumberMapRootIndex); 484 __ LoadRoot(scratch3, Heap::kHeapNumberMapRootIndex);
518 __ AllocateHeapNumber(storage_reg, scratch1, scratch2, scratch3, slow); 485 __ AllocateHeapNumber(storage_reg, scratch1, scratch2, scratch3, slow);
519 486
520 __ JumpIfNotSmi(value_reg, &heap_number); 487 __ JumpIfNotSmi(value_reg, &heap_number);
521 __ SmiUntag(scratch1, value_reg); 488 __ SmiUntag(scratch1, value_reg);
522 __ mtc1(scratch1, f6); 489 __ mtc1(scratch1, f6);
523 __ cvt_d_w(f4, f6); 490 __ cvt_d_w(f4, f6);
524 __ jmp(&do_store); 491 __ jmp(&do_store);
525 492
526 __ bind(&heap_number); 493 __ bind(&heap_number);
527 __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, 494 __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex,
528 miss_restore_name, DONT_DO_SMI_CHECK); 495 miss_label, DONT_DO_SMI_CHECK);
529 __ ldc1(f4, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); 496 __ ldc1(f4, FieldMemOperand(value_reg, HeapNumber::kValueOffset));
530 497
531 __ bind(&do_store); 498 __ bind(&do_store);
532 __ sdc1(f4, FieldMemOperand(storage_reg, HeapNumber::kValueOffset)); 499 __ sdc1(f4, FieldMemOperand(storage_reg, HeapNumber::kValueOffset));
533 } 500 }
534 501
535 // Stub never generated for non-global objects that require access 502 // Stub never generated for non-global objects that require access
536 // checks. 503 // checks.
537 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 504 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
538 505
539 // Perform map transition for the receiver if necessary. 506 // Perform map transition for the receiver if necessary.
540 if (details.type() == FIELD && 507 if (details.type() == FIELD &&
541 object->map()->unused_property_fields() == 0) { 508 object->map()->unused_property_fields() == 0) {
542 // The properties must be extended before we can store the value. 509 // The properties must be extended before we can store the value.
543 // We jump to a runtime call that extends the properties array. 510 // We jump to a runtime call that extends the properties array.
544 __ push(receiver_reg); 511 __ push(receiver_reg);
545 __ li(a2, Operand(transition)); 512 __ li(a2, Operand(transition));
546 __ Push(a2, a0); 513 __ Push(a2, a0);
547 __ TailCallExternalReference( 514 __ TailCallExternalReference(
548 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), 515 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
549 masm->isolate()), 516 masm->isolate()),
550 3, 1); 517 3, 1);
551 return; 518 return;
552 } 519 }
553 520
554 // Update the map of the object. 521 // Update the map of the object.
555 __ li(scratch1, Operand(transition)); 522 __ li(scratch1, Operand(transition));
556 __ sw(scratch1, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); 523 __ sw(scratch1, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
557 524
558 // Update the write barrier for the map field and pass the now unused 525 // Update the write barrier for the map field.
559 // name_reg as scratch register.
560 __ RecordWriteField(receiver_reg, 526 __ RecordWriteField(receiver_reg,
561 HeapObject::kMapOffset, 527 HeapObject::kMapOffset,
562 scratch1, 528 scratch1,
563 scratch2, 529 scratch2,
564 kRAHasNotBeenSaved, 530 kRAHasNotBeenSaved,
565 kDontSaveFPRegs, 531 kDontSaveFPRegs,
566 OMIT_REMEMBERED_SET, 532 OMIT_REMEMBERED_SET,
567 OMIT_SMI_CHECK); 533 OMIT_SMI_CHECK);
568 534
569 if (details.type() == CONSTANT_FUNCTION) { 535 if (details.type() == CONSTANT_FUNCTION) {
(...skipping 21 matching lines...) Expand all
591 __ sw(storage_reg, FieldMemOperand(receiver_reg, offset)); 557 __ sw(storage_reg, FieldMemOperand(receiver_reg, offset));
592 } else { 558 } else {
593 __ sw(value_reg, FieldMemOperand(receiver_reg, offset)); 559 __ sw(value_reg, FieldMemOperand(receiver_reg, offset));
594 } 560 }
595 561
596 if (!FLAG_track_fields || !representation.IsSmi()) { 562 if (!FLAG_track_fields || !representation.IsSmi()) {
597 // Skip updating write barrier if storing a smi. 563 // Skip updating write barrier if storing a smi.
598 __ JumpIfSmi(value_reg, &exit); 564 __ JumpIfSmi(value_reg, &exit);
599 565
600 // Update the write barrier for the array address. 566 // Update the write barrier for the array address.
601 // Pass the now unused name_reg as a scratch register.
602 if (!FLAG_track_double_fields || !representation.IsDouble()) { 567 if (!FLAG_track_double_fields || !representation.IsDouble()) {
603 __ mov(name_reg, value_reg); 568 __ mov(storage_reg, value_reg);
604 } else {
605 ASSERT(storage_reg.is(name_reg));
606 } 569 }
607 __ RecordWriteField(receiver_reg, 570 __ RecordWriteField(receiver_reg,
608 offset, 571 offset,
609 name_reg, 572 storage_reg,
610 scratch1, 573 scratch1,
611 kRAHasNotBeenSaved, 574 kRAHasNotBeenSaved,
612 kDontSaveFPRegs, 575 kDontSaveFPRegs,
613 EMIT_REMEMBERED_SET, 576 EMIT_REMEMBERED_SET,
614 smi_check); 577 smi_check);
615 } 578 }
616 } else { 579 } else {
617 // Write to the properties array. 580 // Write to the properties array.
618 int offset = index * kPointerSize + FixedArray::kHeaderSize; 581 int offset = index * kPointerSize + FixedArray::kHeaderSize;
619 // Get the properties array 582 // Get the properties array
620 __ lw(scratch1, 583 __ lw(scratch1,
621 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); 584 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
622 if (FLAG_track_double_fields && representation.IsDouble()) { 585 if (FLAG_track_double_fields && representation.IsDouble()) {
623 __ sw(storage_reg, FieldMemOperand(scratch1, offset)); 586 __ sw(storage_reg, FieldMemOperand(scratch1, offset));
624 } else { 587 } else {
625 __ sw(value_reg, FieldMemOperand(scratch1, offset)); 588 __ sw(value_reg, FieldMemOperand(scratch1, offset));
626 } 589 }
627 590
628 if (!FLAG_track_fields || !representation.IsSmi()) { 591 if (!FLAG_track_fields || !representation.IsSmi()) {
629 // Skip updating write barrier if storing a smi. 592 // Skip updating write barrier if storing a smi.
630 __ JumpIfSmi(value_reg, &exit); 593 __ JumpIfSmi(value_reg, &exit);
631 594
632 // Update the write barrier for the array address. 595 // Update the write barrier for the array address.
633 // Ok to clobber receiver_reg and name_reg, since we return.
634 if (!FLAG_track_double_fields || !representation.IsDouble()) { 596 if (!FLAG_track_double_fields || !representation.IsDouble()) {
635 __ mov(name_reg, value_reg); 597 __ mov(storage_reg, value_reg);
636 } else {
637 ASSERT(storage_reg.is(name_reg));
638 } 598 }
639 __ RecordWriteField(scratch1, 599 __ RecordWriteField(scratch1,
640 offset, 600 offset,
641 name_reg, 601 storage_reg,
642 receiver_reg, 602 receiver_reg,
643 kRAHasNotBeenSaved, 603 kRAHasNotBeenSaved,
644 kDontSaveFPRegs, 604 kDontSaveFPRegs,
645 EMIT_REMEMBERED_SET, 605 EMIT_REMEMBERED_SET,
646 smi_check); 606 smi_check);
647 } 607 }
648 } 608 }
649 609
650 // Return the value (register v0). 610 // Return the value (register v0).
651 ASSERT(value_reg.is(a0)); 611 ASSERT(value_reg.is(a0));
652 __ bind(&exit); 612 __ bind(&exit);
653 __ Ret(USE_DELAY_SLOT); 613 __ Ret(USE_DELAY_SLOT);
654 __ mov(v0, a0); 614 __ mov(v0, a0);
655 } 615 }
656 616
657 617
658 // Generate StoreField code, value is passed in a0 register. 618 // Generate StoreField code, value is passed in a0 register.
659 // When leaving generated code after success, the receiver_reg and name_reg 619 // When leaving generated code after success, the receiver_reg and name_reg
660 // may be clobbered. Upon branch to miss_label, the receiver and name 620 // may be clobbered. Upon branch to miss_label, the receiver and name
661 // registers have their original values. 621 // registers have their original values.
662 void StubCompiler::GenerateStoreField(MacroAssembler* masm, 622 void BaseStoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
663 Handle<JSObject> object, 623 Handle<JSObject> object,
664 LookupResult* lookup, 624 LookupResult* lookup,
665 Register receiver_reg, 625 Register receiver_reg,
666 Register name_reg, 626 Register name_reg,
667 Register value_reg, 627 Register value_reg,
668 Register scratch1, 628 Register scratch1,
669 Register scratch2, 629 Register scratch2,
670 Label* miss_label) { 630 Label* miss_label) {
671 // a0 : value 631 // a0 : value
672 Label exit; 632 Label exit;
673 633
674 // Check that the map of the object hasn't changed.
675 __ CheckMap(receiver_reg, scratch1, Handle<Map>(object->map()), miss_label,
676 DO_SMI_CHECK);
677
678 // Perform global security token check if needed.
679 if (object->IsJSGlobalProxy()) {
680 __ CheckAccessGlobalProxy(receiver_reg, scratch1, miss_label);
681 }
682
683 // Stub never generated for non-global objects that require access 634 // Stub never generated for non-global objects that require access
684 // checks. 635 // checks.
685 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 636 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
686 637
687 int index = lookup->GetFieldIndex().field_index(); 638 int index = lookup->GetFieldIndex().field_index();
688 639
689 // Adjust for the number of properties stored in the object. Even in the 640 // Adjust for the number of properties stored in the object. Even in the
690 // face of a transition we can use the old map here because the size of the 641 // face of a transition we can use the old map here because the size of the
691 // object and the number of in-object properties is not going to change. 642 // object and the number of in-object properties is not going to change.
692 index -= object->map()->inobject_properties(); 643 index -= object->map()->inobject_properties();
(...skipping 648 matching lines...) Expand 10 before | Expand all | Expand 10 after
1341 // If we've skipped any global objects, it's not enough to verify that 1292 // If we've skipped any global objects, it's not enough to verify that
1342 // their maps haven't changed. We also need to check that the property 1293 // their maps haven't changed. We also need to check that the property
1343 // cell for the property is still empty. 1294 // cell for the property is still empty.
1344 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); 1295 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss);
1345 1296
1346 // Return the register containing the holder. 1297 // Return the register containing the holder.
1347 return reg; 1298 return reg;
1348 } 1299 }
1349 1300
1350 1301
1351 void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success, 1302 void BaseLoadStubCompiler::HandlerFrontendFooter(Handle<Name> name,
1303 Label* success,
1352 Label* miss) { 1304 Label* miss) {
1353 if (!miss->is_unused()) { 1305 if (!miss->is_unused()) {
1354 __ Branch(success); 1306 __ Branch(success);
1355 __ bind(miss); 1307 __ bind(miss);
1356 TailCallBuiltin(masm(), MissBuiltin(kind())); 1308 TailCallBuiltin(masm(), MissBuiltin(kind()));
1357 } 1309 }
1358 } 1310 }
1359 1311
1360 1312
1313 void BaseStoreStubCompiler::HandlerFrontendFooter(Handle<Name> name,
1314 Label* success,
1315 Label* miss) {
1316 if (!miss->is_unused()) {
1317 __ b(success);
1318 GenerateRestoreName(masm(), miss, name);
1319 TailCallBuiltin(masm(), MissBuiltin(kind()));
1320 }
1321 }
1322
1323
1361 Register BaseLoadStubCompiler::CallbackHandlerFrontend( 1324 Register BaseLoadStubCompiler::CallbackHandlerFrontend(
1362 Handle<JSObject> object, 1325 Handle<JSObject> object,
1363 Register object_reg, 1326 Register object_reg,
1364 Handle<JSObject> holder, 1327 Handle<JSObject> holder,
1365 Handle<Name> name, 1328 Handle<Name> name,
1366 Label* success, 1329 Label* success,
1367 Handle<ExecutableAccessorInfo> callback) { 1330 Handle<ExecutableAccessorInfo> callback) {
1368 Label miss; 1331 Label miss;
1369 1332
1370 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); 1333 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss);
(...skipping 21 matching lines...) Expand all
1392 // If probing finds an entry in the dictionary, scratch3 contains the 1355 // If probing finds an entry in the dictionary, scratch3 contains the
1393 // pointer into the dictionary. Check that the value is the callback. 1356 // pointer into the dictionary. Check that the value is the callback.
1394 Register pointer = scratch3(); 1357 Register pointer = scratch3();
1395 const int kElementsStartOffset = NameDictionary::kHeaderSize + 1358 const int kElementsStartOffset = NameDictionary::kHeaderSize +
1396 NameDictionary::kElementsStartIndex * kPointerSize; 1359 NameDictionary::kElementsStartIndex * kPointerSize;
1397 const int kValueOffset = kElementsStartOffset + kPointerSize; 1360 const int kValueOffset = kElementsStartOffset + kPointerSize;
1398 __ lw(scratch2(), FieldMemOperand(pointer, kValueOffset)); 1361 __ lw(scratch2(), FieldMemOperand(pointer, kValueOffset));
1399 __ Branch(&miss, ne, scratch2(), Operand(callback)); 1362 __ Branch(&miss, ne, scratch2(), Operand(callback));
1400 } 1363 }
1401 1364
1402 HandlerFrontendFooter(success, &miss); 1365 HandlerFrontendFooter(name, success, &miss);
1403 return reg; 1366 return reg;
1404 } 1367 }
1405 1368
1406 1369
1407 void BaseLoadStubCompiler::NonexistentHandlerFrontend( 1370 void BaseLoadStubCompiler::NonexistentHandlerFrontend(
1408 Handle<JSObject> object, 1371 Handle<JSObject> object,
1409 Handle<JSObject> last, 1372 Handle<JSObject> last,
1410 Handle<Name> name, 1373 Handle<Name> name,
1411 Label* success, 1374 Label* success,
1412 Handle<GlobalObject> global) { 1375 Handle<GlobalObject> global) {
1413 Label miss; 1376 Label miss;
1414 1377
1415 HandlerFrontendHeader(object, receiver(), last, name, &miss); 1378 HandlerFrontendHeader(object, receiver(), last, name, &miss);
1416 1379
1417 // If the last object in the prototype chain is a global object, 1380 // If the last object in the prototype chain is a global object,
1418 // check that the global property cell is empty. 1381 // check that the global property cell is empty.
1419 if (!global.is_null()) { 1382 if (!global.is_null()) {
1420 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); 1383 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss);
1421 } 1384 }
1422 1385
1423 HandlerFrontendFooter(success, &miss); 1386 HandlerFrontendFooter(name, success, &miss);
1424 } 1387 }
1425 1388
1426 1389
1427 void BaseLoadStubCompiler::GenerateLoadField(Register reg, 1390 void BaseLoadStubCompiler::GenerateLoadField(Register reg,
1428 Handle<JSObject> holder, 1391 Handle<JSObject> holder,
1429 PropertyIndex field, 1392 PropertyIndex field,
1430 Representation representation) { 1393 Representation representation) {
1431 if (!reg.is(receiver())) __ mov(receiver(), reg); 1394 if (!reg.is(receiver())) __ mov(receiver(), reg);
1432 if (kind() == Code::LOAD_IC) { 1395 if (kind() == Code::LOAD_IC) {
1433 LoadFieldStub stub(field.is_inobject(holder), 1396 LoadFieldStub stub(field.is_inobject(holder),
(...skipping 1425 matching lines...) Expand 10 before | Expand all | Expand 10 after
2859 __ bind(&miss); 2822 __ bind(&miss);
2860 __ IncrementCounter(counters->call_global_inline_miss(), 1, a1, a3); 2823 __ IncrementCounter(counters->call_global_inline_miss(), 1, a1, a3);
2861 GenerateMissBranch(); 2824 GenerateMissBranch();
2862 2825
2863 // Return the generated code. 2826 // Return the generated code.
2864 return GetCode(Code::NORMAL, name); 2827 return GetCode(Code::NORMAL, name);
2865 } 2828 }
2866 2829
2867 2830
2868 Handle<Code> StoreStubCompiler::CompileStoreCallback( 2831 Handle<Code> StoreStubCompiler::CompileStoreCallback(
2869 Handle<Name> name,
2870 Handle<JSObject> object, 2832 Handle<JSObject> object,
2871 Handle<JSObject> holder, 2833 Handle<JSObject> holder,
2834 Handle<Name> name,
2872 Handle<ExecutableAccessorInfo> callback) { 2835 Handle<ExecutableAccessorInfo> callback) {
2873 Label miss; 2836 Label success;
2874 // Check that the maps haven't changed. 2837 HandlerFrontend(object, receiver(), holder, name, &success);
2875 __ JumpIfSmi(receiver(), &miss); 2838 __ bind(&success);
2876 CheckPrototypes(object, receiver(), holder,
2877 scratch1(), scratch2(), scratch3(), name, &miss);
2878 2839
2879 // Stub never generated for non-global objects that require access 2840 // Stub never generated for non-global objects that require access
2880 // checks. 2841 // checks.
2881 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); 2842 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
2882 2843
2883 __ push(receiver()); // Receiver. 2844 __ push(receiver()); // Receiver.
2884 __ li(at, Operand(callback)); // Callback info. 2845 __ li(at, Operand(callback)); // Callback info.
2885 __ Push(at, this->name(), value()); 2846 __ push(at);
2847 __ li(at, Operand(name));
2848 __ Push(at, value());
2886 2849
2887 // Do tail-call to the runtime system. 2850 // Do tail-call to the runtime system.
2888 ExternalReference store_callback_property = 2851 ExternalReference store_callback_property =
2889 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); 2852 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate());
2890 __ TailCallExternalReference(store_callback_property, 4, 1); 2853 __ TailCallExternalReference(store_callback_property, 4, 1);
2891 2854
2892 // Handle store cache miss.
2893 __ bind(&miss);
2894 TailCallBuiltin(masm(), MissBuiltin(kind()));
2895
2896 // Return the generated code. 2855 // Return the generated code.
2897 return GetICCode(kind(), Code::CALLBACKS, name); 2856 return GetCode(kind(), Code::CALLBACKS, name);
2898 } 2857 }
2899 2858
2900 2859
2901 #undef __ 2860 #undef __
2902 #define __ ACCESS_MASM(masm) 2861 #define __ ACCESS_MASM(masm)
2903 2862
2904 2863
2905 void StoreStubCompiler::GenerateStoreViaSetter( 2864 void StoreStubCompiler::GenerateStoreViaSetter(
2906 MacroAssembler* masm, 2865 MacroAssembler* masm,
2907 Handle<JSFunction> setter) { 2866 Handle<JSFunction> setter) {
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
3137 // Get the value from the cell. 3096 // Get the value from the cell.
3138 __ li(a3, Operand(cell)); 3097 __ li(a3, Operand(cell));
3139 __ lw(t0, FieldMemOperand(a3, Cell::kValueOffset)); 3098 __ lw(t0, FieldMemOperand(a3, Cell::kValueOffset));
3140 3099
3141 // Check for deleted property if property can actually be deleted. 3100 // Check for deleted property if property can actually be deleted.
3142 if (!is_dont_delete) { 3101 if (!is_dont_delete) {
3143 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 3102 __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
3144 __ Branch(&miss, eq, t0, Operand(at)); 3103 __ Branch(&miss, eq, t0, Operand(at));
3145 } 3104 }
3146 3105
3147 HandlerFrontendFooter(&success, &miss); 3106 HandlerFrontendFooter(name, &success, &miss);
3148 __ bind(&success); 3107 __ bind(&success);
3149 3108
3150 Counters* counters = isolate()->counters(); 3109 Counters* counters = isolate()->counters();
3151 __ IncrementCounter(counters->named_load_global_stub(), 1, a1, a3); 3110 __ IncrementCounter(counters->named_load_global_stub(), 1, a1, a3);
3152 __ Ret(USE_DELAY_SLOT); 3111 __ Ret(USE_DELAY_SLOT);
3153 __ mov(v0, t0); 3112 __ mov(v0, t0);
3154 3113
3155 // Return the generated code. 3114 // Return the generated code.
3156 return GetICCode(kind(), Code::NORMAL, name); 3115 return GetICCode(kind(), Code::NORMAL, name);
3157 } 3116 }
3158 3117
3159 3118
3160 Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC( 3119 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC(
3161 MapHandleList* receiver_maps, 3120 MapHandleList* receiver_maps,
3162 CodeHandleList* handlers, 3121 CodeHandleList* handlers,
3163 Handle<Name> name, 3122 Handle<Name> name,
3164 Code::StubType type, 3123 Code::StubType type,
3165 IcCheckType check) { 3124 IcCheckType check) {
3166 Label miss; 3125 Label miss;
3167 3126
3168 if (check == PROPERTY) { 3127 if (check == PROPERTY) {
3169 GenerateNameCheck(name, this->name(), &miss); 3128 GenerateNameCheck(name, this->name(), &miss);
3170 } 3129 }
(...skipping 664 matching lines...) Expand 10 before | Expand all | Expand 10 after
3835 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow); 3794 TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
3836 } 3795 }
3837 } 3796 }
3838 3797
3839 3798
3840 #undef __ 3799 #undef __
3841 3800
3842 } } // namespace v8::internal 3801 } } // namespace v8::internal
3843 3802
3844 #endif // V8_TARGET_ARCH_MIPS 3803 #endif // V8_TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « src/mips/ic-mips.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698