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

Side by Side Diff: src/ic.cc

Issue 8404030: Version 3.7.1 (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: Created 9 years, 1 month 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/ic.h ('k') | src/incremental-marking.h » ('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 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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 } else { 93 } else {
94 PrintF("<unknown>"); 94 PrintF("<unknown>");
95 } 95 }
96 PrintF(" (%c->%c)", 96 PrintF(" (%c->%c)",
97 TransitionMarkFromState(old_state), 97 TransitionMarkFromState(old_state),
98 TransitionMarkFromState(new_state)); 98 TransitionMarkFromState(new_state));
99 name->Print(); 99 name->Print();
100 PrintF("]\n"); 100 PrintF("]\n");
101 } 101 }
102 } 102 }
103 #endif 103 #endif // DEBUG
104
105
106 #define TRACE_IC(type, name, old_state, new_target) \
107 ASSERT((TraceIC(type, name, old_state, new_target), true))
104 108
105 109
106 IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) { 110 IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) {
107 ASSERT(isolate == Isolate::Current()); 111 ASSERT(isolate == Isolate::Current());
108 // To improve the performance of the (much used) IC code, we unfold 112 // To improve the performance of the (much used) IC code, we unfold
109 // a few levels of the stack frame iteration code. This yields a 113 // a few levels of the stack frame iteration code. This yields a
110 // ~35% speedup when running DeltaBlue with the '--nouse-ic' flag. 114 // ~35% speedup when running DeltaBlue with the '--nouse-ic' flag.
111 const Address entry = 115 const Address entry =
112 Isolate::c_entry_fp(isolate->thread_local_top()); 116 Isolate::c_entry_fp(isolate->thread_local_top());
113 Address* pc_address = 117 Address* pc_address =
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 ? initialize_stub_strict() 365 ? initialize_stub_strict()
362 : initialize_stub()); 366 : initialize_stub());
363 } 367 }
364 368
365 369
366 static bool HasInterceptorGetter(JSObject* object) { 370 static bool HasInterceptorGetter(JSObject* object) {
367 return !object->GetNamedInterceptor()->getter()->IsUndefined(); 371 return !object->GetNamedInterceptor()->getter()->IsUndefined();
368 } 372 }
369 373
370 374
371 static void LookupForRead(Object* object, 375 static void LookupForRead(Handle<Object> object,
372 String* name, 376 Handle<String> name,
373 LookupResult* lookup) { 377 LookupResult* lookup) {
374 AssertNoAllocation no_gc; // pointers must stay valid
375
376 // Skip all the objects with named interceptors, but 378 // Skip all the objects with named interceptors, but
377 // without actual getter. 379 // without actual getter.
378 while (true) { 380 while (true) {
379 object->Lookup(name, lookup); 381 object->Lookup(*name, lookup);
380 // Besides normal conditions (property not found or it's not 382 // Besides normal conditions (property not found or it's not
381 // an interceptor), bail out if lookup is not cacheable: we won't 383 // an interceptor), bail out if lookup is not cacheable: we won't
382 // be able to IC it anyway and regular lookup should work fine. 384 // be able to IC it anyway and regular lookup should work fine.
383 if (!lookup->IsFound() 385 if (!lookup->IsFound()
384 || (lookup->type() != INTERCEPTOR) 386 || (lookup->type() != INTERCEPTOR)
385 || !lookup->IsCacheable()) { 387 || !lookup->IsCacheable()) {
386 return; 388 return;
387 } 389 }
388 390
389 JSObject* holder = lookup->holder(); 391 Handle<JSObject> holder(lookup->holder());
390 if (HasInterceptorGetter(holder)) { 392 if (HasInterceptorGetter(*holder)) {
391 return; 393 return;
392 } 394 }
393 395
394 holder->LocalLookupRealNamedProperty(name, lookup); 396 holder->LocalLookupRealNamedProperty(*name, lookup);
395 if (lookup->IsProperty()) { 397 if (lookup->IsProperty()) {
396 ASSERT(lookup->type() != INTERCEPTOR); 398 ASSERT(lookup->type() != INTERCEPTOR);
397 return; 399 return;
398 } 400 }
399 401
400 Object* proto = holder->GetPrototype(); 402 Handle<Object> proto(holder->GetPrototype());
401 if (proto->IsNull()) { 403 if (proto->IsNull()) {
402 lookup->NotFound(); 404 lookup->NotFound();
403 return; 405 return;
404 } 406 }
405 407
406 object = proto; 408 object = proto;
407 } 409 }
408 } 410 }
409 411
410 412
411 Object* CallICBase::TryCallAsFunction(Object* object) { 413 Handle<Object> CallICBase::TryCallAsFunction(Handle<Object> object) {
412 HandleScope scope(isolate()); 414 Handle<Object> delegate = Execution::GetFunctionDelegate(object);
413 Handle<Object> target(object, isolate());
414 Handle<Object> delegate = Execution::GetFunctionDelegate(target);
415 415
416 if (delegate->IsJSFunction()) { 416 if (delegate->IsJSFunction() && !object->IsJSFunctionProxy()) {
417 // Patch the receiver and use the delegate as the function to 417 // Patch the receiver and use the delegate as the function to
418 // invoke. This is used for invoking objects as if they were 418 // invoke. This is used for invoking objects as if they were functions.
419 // functions. 419 const int argc = target()->arguments_count();
420 const int argc = this->target()->arguments_count();
421 StackFrameLocator locator; 420 StackFrameLocator locator;
422 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); 421 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
423 int index = frame->ComputeExpressionsCount() - (argc + 1); 422 int index = frame->ComputeExpressionsCount() - (argc + 1);
424 frame->SetExpression(index, *target); 423 frame->SetExpression(index, *object);
425 } 424 }
426 425
427 return *delegate; 426 return delegate;
428 } 427 }
429 428
430 429
431 void CallICBase::ReceiverToObjectIfRequired(Handle<Object> callee, 430 void CallICBase::ReceiverToObjectIfRequired(Handle<Object> callee,
432 Handle<Object> object) { 431 Handle<Object> object) {
432 while (callee->IsJSFunctionProxy()) {
433 callee = Handle<Object>(JSFunctionProxy::cast(*callee)->call_trap());
434 }
435
433 if (callee->IsJSFunction()) { 436 if (callee->IsJSFunction()) {
434 Handle<JSFunction> function = Handle<JSFunction>::cast(callee); 437 Handle<JSFunction> function = Handle<JSFunction>::cast(callee);
435 if (function->shared()->strict_mode() || function->IsBuiltin()) { 438 if (function->shared()->strict_mode() || function->IsBuiltin()) {
436 // Do not wrap receiver for strict mode functions or for builtins. 439 // Do not wrap receiver for strict mode functions or for builtins.
437 return; 440 return;
438 } 441 }
439 } 442 }
440 443
441 // And only wrap string, number or boolean. 444 // And only wrap string, number or boolean.
442 if (object->IsString() || object->IsNumber() || object->IsBoolean()) { 445 if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
(...skipping 14 matching lines...) Expand all
457 // If the object is undefined or null it's illegal to try to get any 460 // If the object is undefined or null it's illegal to try to get any
458 // of its properties; throw a TypeError in that case. 461 // of its properties; throw a TypeError in that case.
459 if (object->IsUndefined() || object->IsNull()) { 462 if (object->IsUndefined() || object->IsNull()) {
460 return TypeError("non_object_property_call", object, name); 463 return TypeError("non_object_property_call", object, name);
461 } 464 }
462 465
463 // Check if the name is trivially convertible to an index and get 466 // Check if the name is trivially convertible to an index and get
464 // the element if so. 467 // the element if so.
465 uint32_t index; 468 uint32_t index;
466 if (name->AsArrayIndex(&index)) { 469 if (name->AsArrayIndex(&index)) {
467 Object* result; 470 Handle<Object> result = Object::GetElement(object, index);
468 { MaybeObject* maybe_result = object->GetElement(index); 471 RETURN_IF_EMPTY_HANDLE(isolate(), result);
469 if (!maybe_result->ToObject(&result)) return maybe_result; 472 if (result->IsJSFunction()) return *result;
470 }
471
472 if (result->IsJSFunction()) return result;
473 473
474 // Try to find a suitable function delegate for the object at hand. 474 // Try to find a suitable function delegate for the object at hand.
475 result = TryCallAsFunction(result); 475 result = TryCallAsFunction(result);
476 if (result->IsJSFunction()) return result; 476 if (result->IsJSFunction()) return *result;
477 477
478 // Otherwise, it will fail in the lookup step. 478 // Otherwise, it will fail in the lookup step.
479 } 479 }
480 480
481 // Lookup the property in the object. 481 // Lookup the property in the object.
482 LookupResult lookup; 482 LookupResult lookup(isolate());
483 LookupForRead(*object, *name, &lookup); 483 LookupForRead(object, name, &lookup);
484 484
485 if (!lookup.IsProperty()) { 485 if (!lookup.IsProperty()) {
486 // If the object does not have the requested property, check which 486 // If the object does not have the requested property, check which
487 // exception we need to throw. 487 // exception we need to throw.
488 if (IsContextual(object)) { 488 return IsContextual(object)
489 return ReferenceError("not_defined", name); 489 ? ReferenceError("not_defined", name)
490 } 490 : TypeError("undefined_method", object, name);
491 return TypeError("undefined_method", object, name);
492 } 491 }
493 492
494 // Lookup is valid: Update inline cache and stub cache. 493 // Lookup is valid: Update inline cache and stub cache.
495 if (FLAG_use_ic) { 494 if (FLAG_use_ic) {
496 UpdateCaches(&lookup, state, extra_ic_state, object, name); 495 UpdateCaches(&lookup, state, extra_ic_state, object, name);
497 } 496 }
498 497
499 // Get the property. 498 // Get the property.
500 PropertyAttributes attr; 499 PropertyAttributes attr;
501 Object* result; 500 Handle<Object> result =
502 { MaybeObject* maybe_result = 501 Object::GetProperty(object, object, &lookup, name, &attr);
503 object->GetProperty(*object, &lookup, *name, &attr); 502 RETURN_IF_EMPTY_HANDLE(isolate(), result);
504 if (!maybe_result->ToObject(&result)) return maybe_result;
505 }
506 503
507 if (lookup.type() == INTERCEPTOR) { 504 if (lookup.type() == INTERCEPTOR && attr == ABSENT) {
508 // If the object does not have the requested property, check which 505 // If the object does not have the requested property, check which
509 // exception we need to throw. 506 // exception we need to throw.
510 if (attr == ABSENT) { 507 return IsContextual(object)
511 if (IsContextual(object)) { 508 ? ReferenceError("not_defined", name)
512 return ReferenceError("not_defined", name); 509 : TypeError("undefined_method", object, name);
513 }
514 return TypeError("undefined_method", object, name);
515 }
516 } 510 }
517 511
518 ASSERT(!result->IsTheHole()); 512 ASSERT(!result->IsTheHole());
519 513
520 HandleScope scope(isolate());
521 // Wrap result in a handle because ReceiverToObjectIfRequired may allocate
522 // new object and cause GC.
523 Handle<Object> result_handle(result);
524 // Make receiver an object if the callee requires it. Strict mode or builtin 514 // Make receiver an object if the callee requires it. Strict mode or builtin
525 // functions do not wrap the receiver, non-strict functions and objects 515 // functions do not wrap the receiver, non-strict functions and objects
526 // called as functions do. 516 // called as functions do.
527 ReceiverToObjectIfRequired(result_handle, object); 517 ReceiverToObjectIfRequired(result, object);
528 518
529 if (result_handle->IsJSFunction()) { 519 if (result->IsJSFunction()) {
520 Handle<JSFunction> function = Handle<JSFunction>::cast(result);
530 #ifdef ENABLE_DEBUGGER_SUPPORT 521 #ifdef ENABLE_DEBUGGER_SUPPORT
531 // Handle stepping into a function if step into is active. 522 // Handle stepping into a function if step into is active.
532 Debug* debug = isolate()->debug(); 523 Debug* debug = isolate()->debug();
533 if (debug->StepInActive()) { 524 if (debug->StepInActive()) {
534 // Protect the result in a handle as the debugger can allocate and might 525 // Protect the result in a handle as the debugger can allocate and might
535 // cause GC. 526 // cause GC.
536 Handle<JSFunction> function(JSFunction::cast(*result_handle), isolate());
537 debug->HandleStepIn(function, object, fp(), false); 527 debug->HandleStepIn(function, object, fp(), false);
538 return *function;
539 } 528 }
540 #endif 529 #endif
541 530 return *function;
542 return *result_handle;
543 } 531 }
544 532
545 // Try to find a suitable function delegate for the object at hand. 533 // Try to find a suitable function delegate for the object at hand.
546 result_handle = Handle<Object>(TryCallAsFunction(*result_handle)); 534 result = TryCallAsFunction(result);
547 if (result_handle->IsJSFunction()) return *result_handle; 535 if (result->IsJSFunction()) return *result;
548 536
549 return TypeError("property_not_function", object, name); 537 return TypeError("property_not_function", object, name);
550 } 538 }
551 539
552 540
553 bool CallICBase::TryUpdateExtraICState(LookupResult* lookup, 541 bool CallICBase::TryUpdateExtraICState(LookupResult* lookup,
554 Handle<Object> object, 542 Handle<Object> object,
555 Code::ExtraICState* extra_ic_state) { 543 Code::ExtraICState* extra_ic_state) {
556 ASSERT(kind_ == Code::CALL_IC); 544 ASSERT(kind_ == Code::CALL_IC);
557 if (lookup->type() != CONSTANT_FUNCTION) return false; 545 if (lookup->type() != CONSTANT_FUNCTION) return false;
(...skipping 29 matching lines...) Expand all
587 } 575 }
588 } 576 }
589 break; 577 break;
590 default: 578 default:
591 return false; 579 return false;
592 } 580 }
593 return false; 581 return false;
594 } 582 }
595 583
596 584
597 MaybeObject* CallICBase::ComputeMonomorphicStub( 585 Handle<Code> CallICBase::ComputeMonomorphicStub(LookupResult* lookup,
598 LookupResult* lookup, 586 State state,
599 State state, 587 Code::ExtraICState extra_state,
600 Code::ExtraICState extra_ic_state, 588 Handle<Object> object,
601 Handle<Object> object, 589 Handle<String> name) {
602 Handle<String> name) {
603 int argc = target()->arguments_count(); 590 int argc = target()->arguments_count();
604 MaybeObject* maybe_code = NULL; 591 Handle<JSObject> holder(lookup->holder());
605 switch (lookup->type()) { 592 switch (lookup->type()) {
606 case FIELD: { 593 case FIELD: {
607 int index = lookup->GetFieldIndex(); 594 int index = lookup->GetFieldIndex();
608 maybe_code = isolate()->stub_cache()->ComputeCallField(argc, 595 return isolate()->stub_cache()->ComputeCallField(
609 kind_, 596 argc, kind_, extra_state, name, object, holder, index);
610 extra_ic_state,
611 *name,
612 *object,
613 lookup->holder(),
614 index);
615 break;
616 } 597 }
617 case CONSTANT_FUNCTION: { 598 case CONSTANT_FUNCTION: {
618 // Get the constant function and compute the code stub for this 599 // Get the constant function and compute the code stub for this
619 // call; used for rewriting to monomorphic state and making sure 600 // call; used for rewriting to monomorphic state and making sure
620 // that the code stub is in the stub cache. 601 // that the code stub is in the stub cache.
621 JSFunction* function = lookup->GetConstantFunction(); 602 Handle<JSFunction> function(lookup->GetConstantFunction());
622 maybe_code = 603 return isolate()->stub_cache()->ComputeCallConstant(
623 isolate()->stub_cache()->ComputeCallConstant(argc, 604 argc, kind_, extra_state, name, object, holder, function);
624 kind_,
625 extra_ic_state,
626 *name,
627 *object,
628 lookup->holder(),
629 function);
630 break;
631 } 605 }
632 case NORMAL: { 606 case NORMAL: {
633 if (!object->IsJSObject()) return NULL; 607 // If we return a null handle, the IC will not be patched.
608 if (!object->IsJSObject()) return Handle<Code>::null();
634 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 609 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
635 610
636 if (lookup->holder()->IsGlobalObject()) { 611 if (holder->IsGlobalObject()) {
637 GlobalObject* global = GlobalObject::cast(lookup->holder()); 612 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
638 JSGlobalPropertyCell* cell = 613 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup));
639 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); 614 if (!cell->value()->IsJSFunction()) return Handle<Code>::null();
640 if (!cell->value()->IsJSFunction()) return NULL; 615 Handle<JSFunction> function(JSFunction::cast(cell->value()));
641 JSFunction* function = JSFunction::cast(cell->value()); 616 return isolate()->stub_cache()->ComputeCallGlobal(
642 maybe_code = isolate()->stub_cache()->ComputeCallGlobal(argc, 617 argc, kind_, extra_state, name, receiver, global, cell, function);
643 kind_,
644 extra_ic_state,
645 *name,
646 *receiver,
647 global,
648 cell,
649 function);
650 } else { 618 } else {
651 // There is only one shared stub for calling normalized 619 // There is only one shared stub for calling normalized
652 // properties. It does not traverse the prototype chain, so the 620 // properties. It does not traverse the prototype chain, so the
653 // property must be found in the receiver for the stub to be 621 // property must be found in the receiver for the stub to be
654 // applicable. 622 // applicable.
655 if (lookup->holder() != *receiver) return NULL; 623 if (!holder.is_identical_to(receiver)) return Handle<Code>::null();
656 maybe_code = isolate()->stub_cache()->ComputeCallNormal(argc, 624 return isolate()->stub_cache()->ComputeCallNormal(
657 kind_, 625 argc, kind_, extra_state);
658 extra_ic_state,
659 *name,
660 *receiver);
661 } 626 }
662 break; 627 break;
663 } 628 }
664 case INTERCEPTOR: { 629 case INTERCEPTOR:
665 ASSERT(HasInterceptorGetter(lookup->holder())); 630 ASSERT(HasInterceptorGetter(*holder));
666 maybe_code = isolate()->stub_cache()->ComputeCallInterceptor( 631 return isolate()->stub_cache()->ComputeCallInterceptor(
667 argc, 632 argc, kind_, extra_state, name, object, holder);
668 kind_,
669 extra_ic_state,
670 *name,
671 *object,
672 lookup->holder());
673 break;
674 }
675 default: 633 default:
676 maybe_code = NULL; 634 return Handle<Code>::null();
677 break;
678 } 635 }
679 return maybe_code;
680 } 636 }
681 637
682 638
683 void CallICBase::UpdateCaches(LookupResult* lookup, 639 void CallICBase::UpdateCaches(LookupResult* lookup,
684 State state, 640 State state,
685 Code::ExtraICState extra_ic_state, 641 Code::ExtraICState extra_ic_state,
686 Handle<Object> object, 642 Handle<Object> object,
687 Handle<String> name) { 643 Handle<String> name) {
688 // Bail out if we didn't find a result. 644 // Bail out if we didn't find a result.
689 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; 645 if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
690 646
691 if (lookup->holder() != *object && 647 if (lookup->holder() != *object &&
692 HasNormalObjectsInPrototypeChain( 648 HasNormalObjectsInPrototypeChain(
693 isolate(), lookup, object->GetPrototype())) { 649 isolate(), lookup, object->GetPrototype())) {
694 // Suppress optimization for prototype chains with slow properties objects 650 // Suppress optimization for prototype chains with slow properties objects
695 // in the middle. 651 // in the middle.
696 return; 652 return;
697 } 653 }
698 654
699 // Compute the number of arguments. 655 // Compute the number of arguments.
700 int argc = target()->arguments_count(); 656 int argc = target()->arguments_count();
701 MaybeObject* maybe_code = NULL;
702 bool had_proto_failure = false; 657 bool had_proto_failure = false;
658 Handle<Code> code;
703 if (state == UNINITIALIZED) { 659 if (state == UNINITIALIZED) {
704 // This is the first time we execute this inline cache. 660 // This is the first time we execute this inline cache.
705 // Set the target to the pre monomorphic stub to delay 661 // Set the target to the pre monomorphic stub to delay
706 // setting the monomorphic state. 662 // setting the monomorphic state.
707 maybe_code = 663 code = isolate()->stub_cache()->ComputeCallPreMonomorphic(
708 isolate()->stub_cache()->ComputeCallPreMonomorphic(argc, 664 argc, kind_, extra_ic_state);
709 kind_,
710 extra_ic_state);
711 } else if (state == MONOMORPHIC) { 665 } else if (state == MONOMORPHIC) {
712 if (kind_ == Code::CALL_IC && 666 if (kind_ == Code::CALL_IC &&
713 TryUpdateExtraICState(lookup, object, &extra_ic_state)) { 667 TryUpdateExtraICState(lookup, object, &extra_ic_state)) {
714 maybe_code = ComputeMonomorphicStub(lookup, 668 code = ComputeMonomorphicStub(lookup, state, extra_ic_state,
715 state, 669 object, name);
716 extra_ic_state,
717 object,
718 name);
719 } else if (kind_ == Code::CALL_IC && 670 } else if (kind_ == Code::CALL_IC &&
720 TryRemoveInvalidPrototypeDependentStub(target(), 671 TryRemoveInvalidPrototypeDependentStub(target(),
721 *object, 672 *object,
722 *name)) { 673 *name)) {
723 had_proto_failure = true; 674 had_proto_failure = true;
724 maybe_code = ComputeMonomorphicStub(lookup, 675 code = ComputeMonomorphicStub(lookup, state, extra_ic_state,
725 state, 676 object, name);
726 extra_ic_state,
727 object,
728 name);
729 } else { 677 } else {
730 maybe_code = 678 code = isolate()->stub_cache()->ComputeCallMegamorphic(
731 isolate()->stub_cache()->ComputeCallMegamorphic(argc, 679 argc, kind_, extra_ic_state);
732 kind_,
733 extra_ic_state);
734 } 680 }
735 } else { 681 } else {
736 maybe_code = ComputeMonomorphicStub(lookup, 682 code = ComputeMonomorphicStub(lookup, state, extra_ic_state,
737 state, 683 object, name);
738 extra_ic_state,
739 object,
740 name);
741 } 684 }
742 685
743 // If we're unable to compute the stub (not enough memory left), we 686 // If there's no appropriate stub we simply avoid updating the caches.
744 // simply avoid updating the caches. 687 if (code.is_null()) return;
745 Object* code;
746 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
747 688
748 // Patch the call site depending on the state of the cache. 689 // Patch the call site depending on the state of the cache.
749 if (state == UNINITIALIZED || 690 if (state == UNINITIALIZED ||
750 state == PREMONOMORPHIC || 691 state == PREMONOMORPHIC ||
751 state == MONOMORPHIC || 692 state == MONOMORPHIC ||
752 state == MONOMORPHIC_PROTOTYPE_FAILURE) { 693 state == MONOMORPHIC_PROTOTYPE_FAILURE) {
753 set_target(Code::cast(code)); 694 set_target(*code);
754 } else if (state == MEGAMORPHIC) { 695 } else if (state == MEGAMORPHIC) {
755 // Cache code holding map should be consistent with 696 // Cache code holding map should be consistent with
756 // GenerateMonomorphicCacheProbe. It is not the map which holds the stub. 697 // GenerateMonomorphicCacheProbe. It is not the map which holds the stub.
757 Map* map = JSObject::cast(object->IsJSObject() ? *object : 698 Handle<JSObject> cache_object = object->IsJSObject()
758 object->GetPrototype())->map(); 699 ? Handle<JSObject>::cast(object)
759 700 : Handle<JSObject>(JSObject::cast(object->GetPrototype()));
760 // Update the stub cache. 701 // Update the stub cache.
761 isolate()->stub_cache()->Set(*name, map, Code::cast(code)); 702 isolate()->stub_cache()->Set(*name, cache_object->map(), *code);
762 } 703 }
763 704
764 USE(had_proto_failure);
765 #ifdef DEBUG
766 if (had_proto_failure) state = MONOMORPHIC_PROTOTYPE_FAILURE; 705 if (had_proto_failure) state = MONOMORPHIC_PROTOTYPE_FAILURE;
767 TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", 706 TRACE_IC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC",
768 name, state, target()); 707 name, state, target());
769 #endif
770 } 708 }
771 709
772 710
773 MaybeObject* KeyedCallIC::LoadFunction(State state, 711 MaybeObject* KeyedCallIC::LoadFunction(State state,
774 Handle<Object> object, 712 Handle<Object> object,
775 Handle<Object> key) { 713 Handle<Object> key) {
776 if (key->IsSymbol()) { 714 if (key->IsSymbol()) {
777 return CallICBase::LoadFunction(state, 715 return CallICBase::LoadFunction(state,
778 Code::kNoExtraICState, 716 Code::kNoExtraICState,
779 object, 717 object,
780 Handle<String>::cast(key)); 718 Handle<String>::cast(key));
781 } 719 }
782 720
783 if (object->IsUndefined() || object->IsNull()) { 721 if (object->IsUndefined() || object->IsNull()) {
784 return TypeError("non_object_property_call", object, key); 722 return TypeError("non_object_property_call", object, key);
785 } 723 }
786 724
787 if (FLAG_use_ic && state != MEGAMORPHIC && object->IsHeapObject()) { 725 if (FLAG_use_ic && state != MEGAMORPHIC && object->IsHeapObject()) {
788 int argc = target()->arguments_count(); 726 int argc = target()->arguments_count();
789 Heap* heap = Handle<HeapObject>::cast(object)->GetHeap(); 727 Handle<Map> map =
790 Map* map = heap->non_strict_arguments_elements_map(); 728 isolate()->factory()->non_strict_arguments_elements_map();
791 if (object->IsJSObject() && 729 if (object->IsJSObject() &&
792 Handle<JSObject>::cast(object)->elements()->map() == map) { 730 Handle<JSObject>::cast(object)->elements()->map() == *map) {
793 MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallArguments( 731 Handle<Code> code = isolate()->stub_cache()->ComputeCallArguments(
794 argc, Code::KEYED_CALL_IC); 732 argc, Code::KEYED_CALL_IC);
795 Object* code; 733 set_target(*code);
796 if (maybe_code->ToObject(&code)) { 734 TRACE_IC("KeyedCallIC", key, state, target());
797 set_target(Code::cast(code)); 735 } else if (!object->IsAccessCheckNeeded()) {
798 #ifdef DEBUG 736 Handle<Code> code = isolate()->stub_cache()->ComputeCallMegamorphic(
799 TraceIC("KeyedCallIC", key, state, target());
800 #endif
801 }
802 } else if (FLAG_use_ic && state != MEGAMORPHIC &&
803 !object->IsAccessCheckNeeded()) {
804 MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic(
805 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); 737 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState);
806 Object* code; 738 set_target(*code);
807 if (maybe_code->ToObject(&code)) { 739 TRACE_IC("KeyedCallIC", key, state, target());
808 set_target(Code::cast(code));
809 #ifdef DEBUG
810 TraceIC("KeyedCallIC", key, state, target());
811 #endif
812 }
813 } 740 }
814 } 741 }
815 742
816 HandleScope scope(isolate());
817 Handle<Object> result = GetProperty(object, key); 743 Handle<Object> result = GetProperty(object, key);
818 RETURN_IF_EMPTY_HANDLE(isolate(), result); 744 RETURN_IF_EMPTY_HANDLE(isolate(), result);
819 745
820 // Make receiver an object if the callee requires it. Strict mode or builtin 746 // Make receiver an object if the callee requires it. Strict mode or builtin
821 // functions do not wrap the receiver, non-strict functions and objects 747 // functions do not wrap the receiver, non-strict functions and objects
822 // called as functions do. 748 // called as functions do.
823 ReceiverToObjectIfRequired(result, object); 749 ReceiverToObjectIfRequired(result, object);
750 if (result->IsJSFunction()) return *result;
824 751
825 if (result->IsJSFunction()) return *result; 752 result = TryCallAsFunction(result);
826 result = Handle<Object>(TryCallAsFunction(*result));
827 if (result->IsJSFunction()) return *result; 753 if (result->IsJSFunction()) return *result;
828 754
829 return TypeError("property_not_function", object, key); 755 return TypeError("property_not_function", object, key);
830 } 756 }
831 757
832 758
833 MaybeObject* LoadIC::Load(State state, 759 MaybeObject* LoadIC::Load(State state,
834 Handle<Object> object, 760 Handle<Object> object,
835 Handle<String> name) { 761 Handle<String> name) {
836 // If the object is undefined or null it's illegal to try to get any 762 // If the object is undefined or null it's illegal to try to get any
837 // of its properties; throw a TypeError in that case. 763 // of its properties; throw a TypeError in that case.
838 if (object->IsUndefined() || object->IsNull()) { 764 if (object->IsUndefined() || object->IsNull()) {
839 return TypeError("non_object_property_load", object, name); 765 return TypeError("non_object_property_load", object, name);
840 } 766 }
841 767
842 if (FLAG_use_ic) { 768 if (FLAG_use_ic) {
843 // Use specialized code for getting the length of strings and 769 // Use specialized code for getting the length of strings and
844 // string wrapper objects. The length property of string wrapper 770 // string wrapper objects. The length property of string wrapper
845 // objects is read-only and therefore always returns the length of 771 // objects is read-only and therefore always returns the length of
846 // the underlying string value. See ECMA-262 15.5.5.1. 772 // the underlying string value. See ECMA-262 15.5.5.1.
847 if ((object->IsString() || object->IsStringWrapper()) && 773 if ((object->IsString() || object->IsStringWrapper()) &&
848 name->Equals(isolate()->heap()->length_symbol())) { 774 name->Equals(isolate()->heap()->length_symbol())) {
849 AssertNoAllocation no_allocation; 775 Handle<Code> stub;
850 Code* stub = NULL;
851 if (state == UNINITIALIZED) { 776 if (state == UNINITIALIZED) {
852 stub = pre_monomorphic_stub(); 777 stub = pre_monomorphic_stub();
853 } else if (state == PREMONOMORPHIC) { 778 } else if (state == PREMONOMORPHIC) {
854 if (object->IsString()) { 779 stub = object->IsString()
855 stub = isolate()->builtins()->builtin( 780 ? isolate()->builtins()->LoadIC_StringLength()
856 Builtins::kLoadIC_StringLength); 781 : isolate()->builtins()->LoadIC_StringWrapperLength();
857 } else {
858 stub = isolate()->builtins()->builtin(
859 Builtins::kLoadIC_StringWrapperLength);
860 }
861 } else if (state == MONOMORPHIC && object->IsStringWrapper()) { 782 } else if (state == MONOMORPHIC && object->IsStringWrapper()) {
862 stub = isolate()->builtins()->builtin( 783 stub = isolate()->builtins()->LoadIC_StringWrapperLength();
863 Builtins::kLoadIC_StringWrapperLength);
864 } else if (state != MEGAMORPHIC) { 784 } else if (state != MEGAMORPHIC) {
865 stub = megamorphic_stub(); 785 stub = megamorphic_stub();
866 } 786 }
867 if (stub != NULL) { 787 if (!stub.is_null()) {
868 set_target(stub); 788 set_target(*stub);
869 #ifdef DEBUG 789 #ifdef DEBUG
870 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n"); 790 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
871 #endif 791 #endif
872 } 792 }
873 // Get the string if we have a string wrapper object. 793 // Get the string if we have a string wrapper object.
874 if (object->IsJSValue()) { 794 Handle<Object> string = object->IsJSValue()
875 return Smi::FromInt( 795 ? Handle<Object>(Handle<JSValue>::cast(object)->value())
876 String::cast(Handle<JSValue>::cast(object)->value())->length()); 796 : object;
877 } 797 return Smi::FromInt(String::cast(*string)->length());
878 return Smi::FromInt(String::cast(*object)->length());
879 } 798 }
880 799
881 // Use specialized code for getting the length of arrays. 800 // Use specialized code for getting the length of arrays.
882 if (object->IsJSArray() && 801 if (object->IsJSArray() &&
883 name->Equals(isolate()->heap()->length_symbol())) { 802 name->Equals(isolate()->heap()->length_symbol())) {
884 AssertNoAllocation no_allocation; 803 Handle<Code> stub;
885 Code* stub = NULL;
886 if (state == UNINITIALIZED) { 804 if (state == UNINITIALIZED) {
887 stub = pre_monomorphic_stub(); 805 stub = pre_monomorphic_stub();
888 } else if (state == PREMONOMORPHIC) { 806 } else if (state == PREMONOMORPHIC) {
889 stub = isolate()->builtins()->builtin( 807 stub = isolate()->builtins()->LoadIC_ArrayLength();
890 Builtins::kLoadIC_ArrayLength);
891 } else if (state != MEGAMORPHIC) { 808 } else if (state != MEGAMORPHIC) {
892 stub = megamorphic_stub(); 809 stub = megamorphic_stub();
893 } 810 }
894 if (stub != NULL) { 811 if (!stub.is_null()) {
895 set_target(stub); 812 set_target(*stub);
896 #ifdef DEBUG 813 #ifdef DEBUG
897 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n"); 814 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n");
898 #endif 815 #endif
899 } 816 }
900 return JSArray::cast(*object)->length(); 817 return JSArray::cast(*object)->length();
901 } 818 }
902 819
903 // Use specialized code for getting prototype of functions. 820 // Use specialized code for getting prototype of functions.
904 if (object->IsJSFunction() && 821 if (object->IsJSFunction() &&
905 name->Equals(isolate()->heap()->prototype_symbol()) && 822 name->Equals(isolate()->heap()->prototype_symbol()) &&
906 JSFunction::cast(*object)->should_have_prototype()) { 823 Handle<JSFunction>::cast(object)->should_have_prototype()) {
907 { AssertNoAllocation no_allocation; 824 Handle<Code> stub;
908 Code* stub = NULL; 825 if (state == UNINITIALIZED) {
909 if (state == UNINITIALIZED) { 826 stub = pre_monomorphic_stub();
910 stub = pre_monomorphic_stub(); 827 } else if (state == PREMONOMORPHIC) {
911 } else if (state == PREMONOMORPHIC) { 828 stub = isolate()->builtins()->LoadIC_FunctionPrototype();
912 stub = isolate()->builtins()->builtin( 829 } else if (state != MEGAMORPHIC) {
913 Builtins::kLoadIC_FunctionPrototype); 830 stub = megamorphic_stub();
914 } else if (state != MEGAMORPHIC) { 831 }
915 stub = megamorphic_stub(); 832 if (!stub.is_null()) {
916 } 833 set_target(*stub);
917 if (stub != NULL) {
918 set_target(stub);
919 #ifdef DEBUG 834 #ifdef DEBUG
920 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); 835 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n");
921 #endif 836 #endif
922 }
923 } 837 }
924 return Accessors::FunctionGetPrototype(*object, 0); 838 return Accessors::FunctionGetPrototype(*object, 0);
925 } 839 }
926 } 840 }
927 841
928 // Check if the name is trivially convertible to an index and get 842 // Check if the name is trivially convertible to an index and get
929 // the element if so. 843 // the element if so.
930 uint32_t index; 844 uint32_t index;
931 if (name->AsArrayIndex(&index)) return object->GetElement(index); 845 if (name->AsArrayIndex(&index)) return object->GetElement(index);
932 846
933 // Named lookup in the object. 847 // Named lookup in the object.
934 LookupResult lookup; 848 LookupResult lookup(isolate());
935 LookupForRead(*object, *name, &lookup); 849 LookupForRead(object, name, &lookup);
936 850
937 // If we did not find a property, check if we need to throw an exception. 851 // If we did not find a property, check if we need to throw an exception.
938 if (!lookup.IsProperty()) { 852 if (!lookup.IsProperty()) {
939 if (IsContextual(object)) { 853 if (IsContextual(object)) {
940 return ReferenceError("not_defined", name); 854 return ReferenceError("not_defined", name);
941 } 855 }
942 LOG(isolate(), SuspectReadEvent(*name, *object)); 856 LOG(isolate(), SuspectReadEvent(*name, *object));
943 } 857 }
944 858
945 // Update inline cache and stub cache. 859 // Update inline cache and stub cache.
946 if (FLAG_use_ic) { 860 if (FLAG_use_ic) {
947 UpdateCaches(&lookup, state, object, name); 861 UpdateCaches(&lookup, state, object, name);
948 } 862 }
949 863
950 PropertyAttributes attr; 864 PropertyAttributes attr;
951 if (lookup.IsProperty() && 865 if (lookup.IsProperty() &&
952 (lookup.type() == INTERCEPTOR || lookup.type() == HANDLER)) { 866 (lookup.type() == INTERCEPTOR || lookup.type() == HANDLER)) {
953 // Get the property. 867 // Get the property.
954 Object* result; 868 Handle<Object> result =
955 { MaybeObject* maybe_result = 869 Object::GetProperty(object, object, &lookup, name, &attr);
956 object->GetProperty(*object, &lookup, *name, &attr); 870 RETURN_IF_EMPTY_HANDLE(isolate(), result);
957 if (!maybe_result->ToObject(&result)) return maybe_result;
958 }
959 // If the property is not present, check if we need to throw an 871 // If the property is not present, check if we need to throw an
960 // exception. 872 // exception.
961 if (attr == ABSENT && IsContextual(object)) { 873 if (attr == ABSENT && IsContextual(object)) {
962 return ReferenceError("not_defined", name); 874 return ReferenceError("not_defined", name);
963 } 875 }
964 return result; 876 return *result;
965 } 877 }
966 878
967 // Get the property. 879 // Get the property.
968 return object->GetProperty(*object, &lookup, *name, &attr); 880 return object->GetProperty(*object, &lookup, *name, &attr);
969 } 881 }
970 882
971 883
972 void LoadIC::UpdateCaches(LookupResult* lookup, 884 void LoadIC::UpdateCaches(LookupResult* lookup,
973 State state, 885 State state,
974 Handle<Object> object, 886 Handle<Object> object,
975 Handle<String> name) { 887 Handle<String> name) {
976 // Bail out if the result is not cacheable. 888 // Bail out if the result is not cacheable.
977 if (!lookup->IsCacheable()) return; 889 if (!lookup->IsCacheable()) return;
978 890
979 // Loading properties from values is not common, so don't try to 891 // Loading properties from values is not common, so don't try to
980 // deal with non-JS objects here. 892 // deal with non-JS objects here.
981 if (!object->IsJSObject()) return; 893 if (!object->IsJSObject()) return;
982 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 894 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
983 895
984 if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return; 896 if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return;
985 897
986 // Compute the code stub for this load. 898 // Compute the code stub for this load.
987 MaybeObject* maybe_code = NULL; 899 Handle<Code> code;
988 Object* code;
989 if (state == UNINITIALIZED) { 900 if (state == UNINITIALIZED) {
990 // This is the first time we execute this inline cache. 901 // This is the first time we execute this inline cache.
991 // Set the target to the pre monomorphic stub to delay 902 // Set the target to the pre monomorphic stub to delay
992 // setting the monomorphic state. 903 // setting the monomorphic state.
993 maybe_code = pre_monomorphic_stub(); 904 code = pre_monomorphic_stub();
994 } else if (!lookup->IsProperty()) { 905 } else if (!lookup->IsProperty()) {
995 // Nonexistent property. The result is undefined. 906 // Nonexistent property. The result is undefined.
996 maybe_code = isolate()->stub_cache()->ComputeLoadNonexistent(*name, 907 code = isolate()->stub_cache()->ComputeLoadNonexistent(name, receiver);
997 *receiver);
998 } else { 908 } else {
999 // Compute monomorphic stub. 909 // Compute monomorphic stub.
910 Handle<JSObject> holder(lookup->holder());
1000 switch (lookup->type()) { 911 switch (lookup->type()) {
1001 case FIELD: { 912 case FIELD:
1002 maybe_code = isolate()->stub_cache()->ComputeLoadField( 913 code = isolate()->stub_cache()->ComputeLoadField(
1003 *name, 914 name, receiver, holder, lookup->GetFieldIndex());
1004 *receiver, 915 break;
1005 lookup->holder(), 916 case CONSTANT_FUNCTION: {
1006 lookup->GetFieldIndex()); 917 Handle<Object> constant(lookup->GetConstantFunction());
918 code = isolate()->stub_cache()->ComputeLoadConstant(
919 name, receiver, holder, constant);
1007 break; 920 break;
1008 } 921 }
1009 case CONSTANT_FUNCTION: { 922 case NORMAL:
1010 Object* constant = lookup->GetConstantFunction(); 923 if (holder->IsGlobalObject()) {
1011 maybe_code = isolate()->stub_cache()->ComputeLoadConstant( 924 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
1012 *name, *receiver, lookup->holder(), constant); 925 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup));
1013 break; 926 code = isolate()->stub_cache()->ComputeLoadGlobal(
1014 } 927 name, receiver, global, cell, lookup->IsDontDelete());
1015 case NORMAL: {
1016 if (lookup->holder()->IsGlobalObject()) {
1017 GlobalObject* global = GlobalObject::cast(lookup->holder());
1018 JSGlobalPropertyCell* cell =
1019 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
1020 maybe_code = isolate()->stub_cache()->ComputeLoadGlobal(*name,
1021 *receiver,
1022 global,
1023 cell,
1024 lookup->IsDontDelete());
1025 } else { 928 } else {
1026 // There is only one shared stub for loading normalized 929 // There is only one shared stub for loading normalized
1027 // properties. It does not traverse the prototype chain, so the 930 // properties. It does not traverse the prototype chain, so the
1028 // property must be found in the receiver for the stub to be 931 // property must be found in the receiver for the stub to be
1029 // applicable. 932 // applicable.
1030 if (lookup->holder() != *receiver) return; 933 if (!holder.is_identical_to(receiver)) return;
1031 maybe_code = isolate()->stub_cache()->ComputeLoadNormal(); 934 code = isolate()->stub_cache()->ComputeLoadNormal();
1032 } 935 }
1033 break; 936 break;
1034 }
1035 case CALLBACKS: { 937 case CALLBACKS: {
1036 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; 938 Handle<Object> callback_object(lookup->GetCallbackObject());
1037 AccessorInfo* callback = 939 if (!callback_object->IsAccessorInfo()) return;
1038 AccessorInfo::cast(lookup->GetCallbackObject()); 940 Handle<AccessorInfo> callback =
941 Handle<AccessorInfo>::cast(callback_object);
1039 if (v8::ToCData<Address>(callback->getter()) == 0) return; 942 if (v8::ToCData<Address>(callback->getter()) == 0) return;
1040 maybe_code = isolate()->stub_cache()->ComputeLoadCallback( 943 code = isolate()->stub_cache()->ComputeLoadCallback(
1041 *name, *receiver, lookup->holder(), callback); 944 name, receiver, holder, callback);
1042 break; 945 break;
1043 } 946 }
1044 case INTERCEPTOR: { 947 case INTERCEPTOR:
1045 ASSERT(HasInterceptorGetter(lookup->holder())); 948 ASSERT(HasInterceptorGetter(*holder));
1046 maybe_code = isolate()->stub_cache()->ComputeLoadInterceptor( 949 code = isolate()->stub_cache()->ComputeLoadInterceptor(
1047 *name, *receiver, lookup->holder()); 950 name, receiver, holder);
1048 break; 951 break;
1049 }
1050 default: 952 default:
1051 return; 953 return;
1052 } 954 }
1053 } 955 }
1054 956
1055 // If we're unable to compute the stub (not enough memory left), we
1056 // simply avoid updating the caches.
1057 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
1058
1059 // Patch the call site depending on the state of the cache. 957 // Patch the call site depending on the state of the cache.
1060 if (state == UNINITIALIZED || state == PREMONOMORPHIC || 958 if (state == UNINITIALIZED ||
959 state == PREMONOMORPHIC ||
1061 state == MONOMORPHIC_PROTOTYPE_FAILURE) { 960 state == MONOMORPHIC_PROTOTYPE_FAILURE) {
1062 set_target(Code::cast(code)); 961 set_target(*code);
1063 } else if (state == MONOMORPHIC) { 962 } else if (state == MONOMORPHIC) {
1064 set_target(megamorphic_stub()); 963 set_target(*megamorphic_stub());
1065 } else if (state == MEGAMORPHIC) { 964 } else if (state == MEGAMORPHIC) {
1066 // Cache code holding map should be consistent with 965 // Cache code holding map should be consistent with
1067 // GenerateMonomorphicCacheProbe. 966 // GenerateMonomorphicCacheProbe.
1068 Map* map = JSObject::cast(object->IsJSObject() ? *object : 967 isolate()->stub_cache()->Set(*name, receiver->map(), *code);
1069 object->GetPrototype())->map();
1070
1071 isolate()->stub_cache()->Set(*name, map, Code::cast(code));
1072 } 968 }
1073 969
1074 #ifdef DEBUG 970 TRACE_IC("LoadIC", name, state, target());
1075 TraceIC("LoadIC", name, state, target());
1076 #endif
1077 } 971 }
1078 972
1079 973
1080 MaybeObject* KeyedLoadIC::GetElementStubWithoutMapCheck( 974 Handle<Code> KeyedLoadIC::GetElementStubWithoutMapCheck(
1081 bool is_js_array, 975 bool is_js_array,
1082 ElementsKind elements_kind) { 976 ElementsKind elements_kind) {
1083 return KeyedLoadElementStub(elements_kind).TryGetCode(); 977 return KeyedLoadElementStub(elements_kind).GetCode();
1084 } 978 }
1085 979
1086 980
1087 MaybeObject* KeyedLoadIC::ComputePolymorphicStub( 981 Handle<Code> KeyedLoadIC::ComputePolymorphicStub(
1088 MapList* receiver_maps, 982 MapHandleList* receiver_maps,
1089 StrictModeFlag strict_mode) { 983 StrictModeFlag strict_mode) {
1090 CodeList handler_ics(receiver_maps->length()); 984 CodeHandleList handler_ics(receiver_maps->length());
1091 for (int i = 0; i < receiver_maps->length(); ++i) { 985 for (int i = 0; i < receiver_maps->length(); ++i) {
1092 Map* receiver_map(receiver_maps->at(i)); 986 Handle<Map> receiver_map = receiver_maps->at(i);
1093 MaybeObject* maybe_cached_stub = ComputeMonomorphicStubWithoutMapCheck( 987 Handle<Code> cached_stub = ComputeMonomorphicStubWithoutMapCheck(
1094 receiver_map, strict_mode); 988 receiver_map, strict_mode);
1095 Code* cached_stub;
1096 if (!maybe_cached_stub->To(&cached_stub)) return maybe_cached_stub;
1097 handler_ics.Add(cached_stub); 989 handler_ics.Add(cached_stub);
1098 } 990 }
1099 Object* object; 991 KeyedLoadStubCompiler compiler(isolate());
1100 KeyedLoadStubCompiler compiler; 992 Handle<Code> code = compiler.CompileLoadPolymorphic(
1101 MaybeObject* maybe_code = compiler.CompileLoadPolymorphic(receiver_maps, 993 receiver_maps, &handler_ics);
1102 &handler_ics);
1103 if (!maybe_code->ToObject(&object)) return maybe_code;
1104 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment(); 994 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment();
1105 PROFILE(isolate(), CodeCreateEvent( 995 PROFILE(isolate(),
1106 Logger::KEYED_LOAD_MEGAMORPHIC_IC_TAG, 996 CodeCreateEvent(Logger::KEYED_LOAD_MEGAMORPHIC_IC_TAG, *code, 0));
1107 Code::cast(object), 0)); 997 return code;
1108 return object;
1109 } 998 }
1110 999
1111 1000
1112 MaybeObject* KeyedLoadIC::Load(State state, 1001 MaybeObject* KeyedLoadIC::Load(State state,
1113 Handle<Object> object, 1002 Handle<Object> object,
1114 Handle<Object> key, 1003 Handle<Object> key,
1115 bool force_generic_stub) { 1004 bool force_generic_stub) {
1116 // Check for values that can be converted into a symbol. 1005 // Check for values that can be converted into a symbol.
1117 // TODO(1295): Remove this code. 1006 // TODO(1295): Remove this code.
1118 HandleScope scope(isolate());
1119 if (key->IsHeapNumber() && 1007 if (key->IsHeapNumber() &&
1120 isnan(HeapNumber::cast(*key)->value())) { 1008 isnan(Handle<HeapNumber>::cast(key)->value())) {
1121 key = isolate()->factory()->nan_symbol(); 1009 key = isolate()->factory()->nan_symbol();
1122 } else if (key->IsUndefined()) { 1010 } else if (key->IsUndefined()) {
1123 key = isolate()->factory()->undefined_symbol(); 1011 key = isolate()->factory()->undefined_symbol();
1124 } 1012 }
1125 1013
1126 if (key->IsSymbol()) { 1014 if (key->IsSymbol()) {
1127 Handle<String> name = Handle<String>::cast(key); 1015 Handle<String> name = Handle<String>::cast(key);
1128 1016
1129 // If the object is undefined or null it's illegal to try to get any 1017 // If the object is undefined or null it's illegal to try to get any
1130 // of its properties; throw a TypeError in that case. 1018 // of its properties; throw a TypeError in that case.
1131 if (object->IsUndefined() || object->IsNull()) { 1019 if (object->IsUndefined() || object->IsNull()) {
1132 return TypeError("non_object_property_load", object, name); 1020 return TypeError("non_object_property_load", object, name);
1133 } 1021 }
1134 1022
1135 if (FLAG_use_ic) { 1023 if (FLAG_use_ic) {
1136 // TODO(1073): don't ignore the current stub state. 1024 // TODO(1073): don't ignore the current stub state.
1137 1025
1138 // Use specialized code for getting the length of strings. 1026 // Use specialized code for getting the length of strings.
1139 if (object->IsString() && 1027 if (object->IsString() &&
1140 name->Equals(isolate()->heap()->length_symbol())) { 1028 name->Equals(isolate()->heap()->length_symbol())) {
1141 Handle<String> string = Handle<String>::cast(object); 1029 Handle<String> string = Handle<String>::cast(object);
1142 Object* code = NULL; 1030 Handle<Code> code =
1143 { MaybeObject* maybe_code = 1031 isolate()->stub_cache()->ComputeKeyedLoadStringLength(name, string);
1144 isolate()->stub_cache()->ComputeKeyedLoadStringLength(*name, 1032 ASSERT(!code.is_null());
1145 *string); 1033 set_target(*code);
1146 if (!maybe_code->ToObject(&code)) return maybe_code; 1034 TRACE_IC("KeyedLoadIC", name, state, target());
1147 }
1148 set_target(Code::cast(code));
1149 #ifdef DEBUG
1150 TraceIC("KeyedLoadIC", name, state, target());
1151 #endif // DEBUG
1152 return Smi::FromInt(string->length()); 1035 return Smi::FromInt(string->length());
1153 } 1036 }
1154 1037
1155 // Use specialized code for getting the length of arrays. 1038 // Use specialized code for getting the length of arrays.
1156 if (object->IsJSArray() && 1039 if (object->IsJSArray() &&
1157 name->Equals(isolate()->heap()->length_symbol())) { 1040 name->Equals(isolate()->heap()->length_symbol())) {
1158 Handle<JSArray> array = Handle<JSArray>::cast(object); 1041 Handle<JSArray> array = Handle<JSArray>::cast(object);
1159 Object* code; 1042 Handle<Code> code =
1160 { MaybeObject* maybe_code = 1043 isolate()->stub_cache()->ComputeKeyedLoadArrayLength(name, array);
1161 isolate()->stub_cache()->ComputeKeyedLoadArrayLength(*name, 1044 ASSERT(!code.is_null());
1162 *array); 1045 set_target(*code);
1163 if (!maybe_code->ToObject(&code)) return maybe_code; 1046 TRACE_IC("KeyedLoadIC", name, state, target());
1164 } 1047 return array->length();
1165 set_target(Code::cast(code));
1166 #ifdef DEBUG
1167 TraceIC("KeyedLoadIC", name, state, target());
1168 #endif // DEBUG
1169 return JSArray::cast(*object)->length();
1170 } 1048 }
1171 1049
1172 // Use specialized code for getting prototype of functions. 1050 // Use specialized code for getting prototype of functions.
1173 if (object->IsJSFunction() && 1051 if (object->IsJSFunction() &&
1174 name->Equals(isolate()->heap()->prototype_symbol()) && 1052 name->Equals(isolate()->heap()->prototype_symbol()) &&
1175 JSFunction::cast(*object)->should_have_prototype()) { 1053 Handle<JSFunction>::cast(object)->should_have_prototype()) {
1176 Handle<JSFunction> function = Handle<JSFunction>::cast(object); 1054 Handle<JSFunction> function = Handle<JSFunction>::cast(object);
1177 Object* code; 1055 Handle<Code> code =
1178 { MaybeObject* maybe_code = 1056 isolate()->stub_cache()->ComputeKeyedLoadFunctionPrototype(
1179 isolate()->stub_cache()->ComputeKeyedLoadFunctionPrototype( 1057 name, function);
1180 *name, *function); 1058 ASSERT(!code.is_null());
1181 if (!maybe_code->ToObject(&code)) return maybe_code; 1059 set_target(*code);
1182 } 1060 TRACE_IC("KeyedLoadIC", name, state, target());
1183 set_target(Code::cast(code));
1184 #ifdef DEBUG
1185 TraceIC("KeyedLoadIC", name, state, target());
1186 #endif // DEBUG
1187 return Accessors::FunctionGetPrototype(*object, 0); 1061 return Accessors::FunctionGetPrototype(*object, 0);
1188 } 1062 }
1189 } 1063 }
1190 1064
1191 // Check if the name is trivially convertible to an index and get 1065 // Check if the name is trivially convertible to an index and get
1192 // the element or char if so. 1066 // the element or char if so.
1193 uint32_t index = 0; 1067 uint32_t index = 0;
1194 if (name->AsArrayIndex(&index)) { 1068 if (name->AsArrayIndex(&index)) {
1195 HandleScope scope(isolate());
1196 // Rewrite to the generic keyed load stub. 1069 // Rewrite to the generic keyed load stub.
1197 if (FLAG_use_ic) set_target(generic_stub()); 1070 if (FLAG_use_ic) set_target(*generic_stub());
1198 return Runtime::GetElementOrCharAt(isolate(), object, index); 1071 return Runtime::GetElementOrCharAt(isolate(), object, index);
1199 } 1072 }
1200 1073
1201 // Named lookup. 1074 // Named lookup.
1202 LookupResult lookup; 1075 LookupResult lookup(isolate());
1203 LookupForRead(*object, *name, &lookup); 1076 LookupForRead(object, name, &lookup);
1204 1077
1205 // If we did not find a property, check if we need to throw an exception. 1078 // If we did not find a property, check if we need to throw an exception.
1206 if (!lookup.IsProperty() && IsContextual(object)) { 1079 if (!lookup.IsProperty() && IsContextual(object)) {
1207 return ReferenceError("not_defined", name); 1080 return ReferenceError("not_defined", name);
1208 } 1081 }
1209 1082
1210 if (FLAG_use_ic) { 1083 if (FLAG_use_ic) {
1211 UpdateCaches(&lookup, state, object, name); 1084 UpdateCaches(&lookup, state, object, name);
1212 } 1085 }
1213 1086
1214 PropertyAttributes attr; 1087 PropertyAttributes attr;
1215 if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { 1088 if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) {
1216 // Get the property. 1089 // Get the property.
1217 Object* result; 1090 Handle<Object> result =
1218 { MaybeObject* maybe_result = 1091 Object::GetProperty(object, object, &lookup, name, &attr);
1219 object->GetProperty(*object, &lookup, *name, &attr); 1092 RETURN_IF_EMPTY_HANDLE(isolate(), result);
1220 if (!maybe_result->ToObject(&result)) return maybe_result;
1221 }
1222 // If the property is not present, check if we need to throw an 1093 // If the property is not present, check if we need to throw an
1223 // exception. 1094 // exception.
1224 if (attr == ABSENT && IsContextual(object)) { 1095 if (attr == ABSENT && IsContextual(object)) {
1225 return ReferenceError("not_defined", name); 1096 return ReferenceError("not_defined", name);
1226 } 1097 }
1227 return result; 1098 return *result;
1228 } 1099 }
1229 1100
1230 return object->GetProperty(*object, &lookup, *name, &attr); 1101 return object->GetProperty(*object, &lookup, *name, &attr);
1231 } 1102 }
1232 1103
1233 // Do not use ICs for objects that require access checks (including 1104 // Do not use ICs for objects that require access checks (including
1234 // the global object). 1105 // the global object).
1235 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); 1106 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
1236 1107
1237 if (use_ic) { 1108 if (use_ic) {
1238 Code* stub = generic_stub(); 1109 Handle<Code> stub = generic_stub();
1239 if (!force_generic_stub) { 1110 if (!force_generic_stub) {
1240 if (object->IsString() && key->IsNumber()) { 1111 if (object->IsString() && key->IsNumber()) {
1241 if (state == UNINITIALIZED) { 1112 if (state == UNINITIALIZED) {
1242 stub = string_stub(); 1113 stub = string_stub();
1243 } 1114 }
1244 } else if (object->IsJSObject()) { 1115 } else if (object->IsJSObject()) {
1245 JSObject* receiver = JSObject::cast(*object); 1116 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1246 Heap* heap = Handle<JSObject>::cast(object)->GetHeap(); 1117 if (receiver->elements()->map() ==
1247 Map* elements_map = Handle<JSObject>::cast(object)->elements()->map(); 1118 isolate()->heap()->non_strict_arguments_elements_map()) {
1248 if (elements_map == heap->non_strict_arguments_elements_map()) {
1249 stub = non_strict_arguments_stub(); 1119 stub = non_strict_arguments_stub();
1250 } else if (receiver->HasIndexedInterceptor()) { 1120 } else if (receiver->HasIndexedInterceptor()) {
1251 stub = indexed_interceptor_stub(); 1121 stub = indexed_interceptor_stub();
1252 } else if (key->IsSmi() && (target() != non_strict_arguments_stub())) { 1122 } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) {
1253 MaybeObject* maybe_stub = ComputeStub(receiver, 1123 stub = ComputeStub(receiver, LOAD, kNonStrictMode, stub);
1254 LOAD,
1255 kNonStrictMode,
1256 stub);
1257 stub = maybe_stub->IsFailure() ?
1258 NULL : Code::cast(maybe_stub->ToObjectUnchecked());
1259 } 1124 }
1260 } 1125 }
1261 } 1126 }
1262 if (stub != NULL) set_target(stub); 1127 if (!stub.is_null()) set_target(*stub);
1263 } 1128 }
1264 1129
1265 #ifdef DEBUG 1130 TRACE_IC("KeyedLoadIC", key, state, target());
1266 TraceIC("KeyedLoadIC", key, state, target());
1267 #endif // DEBUG
1268 1131
1269 // Get the property. 1132 // Get the property.
1270 return Runtime::GetObjectProperty(isolate(), object, key); 1133 return Runtime::GetObjectProperty(isolate(), object, key);
1271 } 1134 }
1272 1135
1273 1136
1274 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, 1137 void KeyedLoadIC::UpdateCaches(LookupResult* lookup,
1275 Handle<Object> object, Handle<String> name) { 1138 State state,
1139 Handle<Object> object,
1140 Handle<String> name) {
1276 // Bail out if we didn't find a result. 1141 // Bail out if we didn't find a result.
1277 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; 1142 if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
1278 1143
1279 if (!object->IsJSObject()) return; 1144 if (!object->IsJSObject()) return;
1280 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1145 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1281 1146
1282 if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return; 1147 if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return;
1283 1148
1284 // Compute the code stub for this load. 1149 // Compute the code stub for this load.
1285 MaybeObject* maybe_code = NULL; 1150 Handle<Code> code;
1286 Object* code;
1287 1151
1288 if (state == UNINITIALIZED) { 1152 if (state == UNINITIALIZED) {
1289 // This is the first time we execute this inline cache. 1153 // This is the first time we execute this inline cache.
1290 // Set the target to the pre monomorphic stub to delay 1154 // Set the target to the pre monomorphic stub to delay
1291 // setting the monomorphic state. 1155 // setting the monomorphic state.
1292 maybe_code = pre_monomorphic_stub(); 1156 code = pre_monomorphic_stub();
1293 } else { 1157 } else {
1294 // Compute a monomorphic stub. 1158 // Compute a monomorphic stub.
1159 Handle<JSObject> holder(lookup->holder());
1295 switch (lookup->type()) { 1160 switch (lookup->type()) {
1296 case FIELD: { 1161 case FIELD:
1297 maybe_code = isolate()->stub_cache()->ComputeKeyedLoadField( 1162 code = isolate()->stub_cache()->ComputeKeyedLoadField(
1298 *name, *receiver, lookup->holder(), lookup->GetFieldIndex()); 1163 name, receiver, holder, lookup->GetFieldIndex());
1299 break; 1164 break;
1300 }
1301 case CONSTANT_FUNCTION: { 1165 case CONSTANT_FUNCTION: {
1302 Object* constant = lookup->GetConstantFunction(); 1166 Handle<Object> constant(lookup->GetConstantFunction());
1303 maybe_code = isolate()->stub_cache()->ComputeKeyedLoadConstant( 1167 code = isolate()->stub_cache()->ComputeKeyedLoadConstant(
1304 *name, *receiver, lookup->holder(), constant); 1168 name, receiver, holder, constant);
1305 break; 1169 break;
1306 } 1170 }
1307 case CALLBACKS: { 1171 case CALLBACKS: {
1308 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; 1172 Handle<Object> callback_object(lookup->GetCallbackObject());
1309 AccessorInfo* callback = 1173 if (!callback_object->IsAccessorInfo()) return;
1310 AccessorInfo::cast(lookup->GetCallbackObject()); 1174 Handle<AccessorInfo> callback =
1175 Handle<AccessorInfo>::cast(callback_object);
1311 if (v8::ToCData<Address>(callback->getter()) == 0) return; 1176 if (v8::ToCData<Address>(callback->getter()) == 0) return;
1312 maybe_code = isolate()->stub_cache()->ComputeKeyedLoadCallback( 1177 code = isolate()->stub_cache()->ComputeKeyedLoadCallback(
1313 *name, *receiver, lookup->holder(), callback); 1178 name, receiver, holder, callback);
1314 break; 1179 break;
1315 } 1180 }
1316 case INTERCEPTOR: { 1181 case INTERCEPTOR:
1317 ASSERT(HasInterceptorGetter(lookup->holder())); 1182 ASSERT(HasInterceptorGetter(lookup->holder()));
1318 maybe_code = isolate()->stub_cache()->ComputeKeyedLoadInterceptor( 1183 code = isolate()->stub_cache()->ComputeKeyedLoadInterceptor(
1319 *name, *receiver, lookup->holder()); 1184 name, receiver, holder);
1320 break; 1185 break;
1321 } 1186 default:
1322 default: {
1323 // Always rewrite to the generic case so that we do not 1187 // Always rewrite to the generic case so that we do not
1324 // repeatedly try to rewrite. 1188 // repeatedly try to rewrite.
1325 maybe_code = generic_stub(); 1189 code = generic_stub();
1326 break; 1190 break;
1327 }
1328 } 1191 }
1329 } 1192 }
1330 1193
1331 // If we're unable to compute the stub (not enough memory left), we
1332 // simply avoid updating the caches.
1333 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
1334
1335 // Patch the call site depending on the state of the cache. Make 1194 // Patch the call site depending on the state of the cache. Make
1336 // sure to always rewrite from monomorphic to megamorphic. 1195 // sure to always rewrite from monomorphic to megamorphic.
1337 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE); 1196 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE);
1338 if (state == UNINITIALIZED || state == PREMONOMORPHIC) { 1197 if (state == UNINITIALIZED || state == PREMONOMORPHIC) {
1339 set_target(Code::cast(code)); 1198 set_target(*code);
1340 } else if (state == MONOMORPHIC) { 1199 } else if (state == MONOMORPHIC) {
1341 set_target(megamorphic_stub()); 1200 set_target(*megamorphic_stub());
1342 } 1201 }
1343 1202
1344 #ifdef DEBUG 1203 TRACE_IC("KeyedLoadIC", name, state, target());
1345 TraceIC("KeyedLoadIC", name, state, target());
1346 #endif
1347 } 1204 }
1348 1205
1349 1206
1350 static bool StoreICableLookup(LookupResult* lookup) { 1207 static bool StoreICableLookup(LookupResult* lookup) {
1351 // Bail out if we didn't find a result. 1208 // Bail out if we didn't find a result.
1352 if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return false; 1209 if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return false;
1353 1210
1354 // If the property is read-only, we leave the IC in its current 1211 // If the property is read-only, we leave the IC in its current
1355 // state. 1212 // state.
1356 if (lookup->IsReadOnly()) return false; 1213 if (lookup->IsReadOnly()) return false;
1357 1214
1358 return true; 1215 return true;
1359 } 1216 }
1360 1217
1361 1218
1362 static bool LookupForWrite(JSObject* receiver, 1219 static bool LookupForWrite(Handle<JSObject> receiver,
1363 String* name, 1220 Handle<String> name,
1364 LookupResult* lookup) { 1221 LookupResult* lookup) {
1365 receiver->LocalLookup(name, lookup); 1222 receiver->LocalLookup(*name, lookup);
1366 if (!StoreICableLookup(lookup)) { 1223 if (!StoreICableLookup(lookup)) {
1367 return false; 1224 return false;
1368 } 1225 }
1369 1226
1370 if (lookup->type() == INTERCEPTOR && 1227 if (lookup->type() == INTERCEPTOR &&
1371 receiver->GetNamedInterceptor()->setter()->IsUndefined()) { 1228 receiver->GetNamedInterceptor()->setter()->IsUndefined()) {
1372 receiver->LocalLookupRealNamedProperty(name, lookup); 1229 receiver->LocalLookupRealNamedProperty(*name, lookup);
1373 return StoreICableLookup(lookup); 1230 return StoreICableLookup(lookup);
1374 } 1231 }
1375 1232
1376 return true; 1233 return true;
1377 } 1234 }
1378 1235
1379 1236
1380 MaybeObject* StoreIC::Store(State state, 1237 MaybeObject* StoreIC::Store(State state,
1381 StrictModeFlag strict_mode, 1238 StrictModeFlag strict_mode,
1382 Handle<Object> object, 1239 Handle<Object> object,
(...skipping 11 matching lines...) Expand all
1394 if (object->IsUndefined() || object->IsNull()) { 1251 if (object->IsUndefined() || object->IsNull()) {
1395 return TypeError("non_object_property_store", object, name); 1252 return TypeError("non_object_property_store", object, name);
1396 } 1253 }
1397 1254
1398 // The length property of string values is read-only. Throw in strict mode. 1255 // The length property of string values is read-only. Throw in strict mode.
1399 if (strict_mode == kStrictMode && object->IsString() && 1256 if (strict_mode == kStrictMode && object->IsString() &&
1400 name->Equals(isolate()->heap()->length_symbol())) { 1257 name->Equals(isolate()->heap()->length_symbol())) {
1401 return TypeError("strict_read_only_property", object, name); 1258 return TypeError("strict_read_only_property", object, name);
1402 } 1259 }
1403 // Ignore other stores where the receiver is not a JSObject. 1260 // Ignore other stores where the receiver is not a JSObject.
1261 // TODO(1475): Must check prototype chains of object wrappers.
1404 return *value; 1262 return *value;
1405 } 1263 }
1406 1264
1407 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1265 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1408 1266
1409 // Check if the given name is an array index. 1267 // Check if the given name is an array index.
1410 uint32_t index; 1268 uint32_t index;
1411 if (name->AsArrayIndex(&index)) { 1269 if (name->AsArrayIndex(&index)) {
1412 HandleScope scope(isolate());
1413 Handle<Object> result = SetElement(receiver, index, value, strict_mode); 1270 Handle<Object> result = SetElement(receiver, index, value, strict_mode);
1414 if (result.is_null()) return Failure::Exception(); 1271 RETURN_IF_EMPTY_HANDLE(isolate(), result);
1415 return *value; 1272 return *value;
1416 } 1273 }
1417 1274
1418 // Use specialized code for setting the length of arrays. 1275 // Use specialized code for setting the length of arrays.
1419 if (receiver->IsJSArray() 1276 if (receiver->IsJSArray()
1420 && name->Equals(isolate()->heap()->length_symbol()) 1277 && name->Equals(isolate()->heap()->length_symbol())
1421 && JSArray::cast(*receiver)->AllowsSetElementsLength()) { 1278 && Handle<JSArray>::cast(receiver)->AllowsSetElementsLength()) {
1422 #ifdef DEBUG 1279 #ifdef DEBUG
1423 if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n"); 1280 if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n");
1424 #endif 1281 #endif
1425 Builtins::Name target = (strict_mode == kStrictMode) 1282 Handle<Code> stub = (strict_mode == kStrictMode)
1426 ? Builtins::kStoreIC_ArrayLength_Strict 1283 ? isolate()->builtins()->StoreIC_ArrayLength_Strict()
1427 : Builtins::kStoreIC_ArrayLength; 1284 : isolate()->builtins()->StoreIC_ArrayLength();
1428 set_target(isolate()->builtins()->builtin(target)); 1285 set_target(*stub);
1429 return receiver->SetProperty(*name, *value, NONE, strict_mode); 1286 return receiver->SetProperty(*name, *value, NONE, strict_mode);
1430 } 1287 }
1431 1288
1432 // Lookup the property locally in the receiver. 1289 // Lookup the property locally in the receiver.
1433 if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) { 1290 if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) {
1434 LookupResult lookup; 1291 LookupResult lookup(isolate());
1435 1292
1436 if (LookupForWrite(*receiver, *name, &lookup)) { 1293 if (LookupForWrite(receiver, name, &lookup)) {
1437 // Generate a stub for this store. 1294 // Generate a stub for this store.
1438 UpdateCaches(&lookup, state, strict_mode, receiver, name, value); 1295 UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
1439 } else { 1296 } else {
1440 // Strict mode doesn't allow setting non-existent global property 1297 // Strict mode doesn't allow setting non-existent global property
1441 // or an assignment to a read only property. 1298 // or an assignment to a read only property.
1442 if (strict_mode == kStrictMode) { 1299 if (strict_mode == kStrictMode) {
1443 if (lookup.IsFound() && lookup.IsReadOnly()) { 1300 if (lookup.IsFound() && lookup.IsReadOnly()) {
1444 return TypeError("strict_read_only_property", object, name); 1301 return TypeError("strict_read_only_property", object, name);
1445 } else if (IsContextual(object)) { 1302 } else if (IsContextual(object)) {
1446 return ReferenceError("not_defined", name); 1303 return ReferenceError("not_defined", name);
1447 } 1304 }
1448 } 1305 }
1449 } 1306 }
1450 } 1307 }
1451 1308
1452 if (receiver->IsJSGlobalProxy()) { 1309 if (receiver->IsJSGlobalProxy()) {
1310 // TODO(ulan): find out why we patch this site even with --no-use-ic
1453 // Generate a generic stub that goes to the runtime when we see a global 1311 // Generate a generic stub that goes to the runtime when we see a global
1454 // proxy as receiver. 1312 // proxy as receiver.
1455 Code* stub = (strict_mode == kStrictMode) 1313 Handle<Code> stub = (strict_mode == kStrictMode)
1456 ? global_proxy_stub_strict() 1314 ? global_proxy_stub_strict()
1457 : global_proxy_stub(); 1315 : global_proxy_stub();
1458 if (target() != stub) { 1316 if (target() != *stub) {
1459 set_target(stub); 1317 set_target(*stub);
1460 #ifdef DEBUG 1318 TRACE_IC("StoreIC", name, state, target());
1461 TraceIC("StoreIC", name, state, target());
1462 #endif
1463 } 1319 }
1464 } 1320 }
1465 1321
1466 // Set the property. 1322 // Set the property.
1467 return receiver->SetProperty(*name, *value, NONE, strict_mode); 1323 return receiver->SetProperty(*name, *value, NONE, strict_mode);
1468 } 1324 }
1469 1325
1470 1326
1471 void StoreIC::UpdateCaches(LookupResult* lookup, 1327 void StoreIC::UpdateCaches(LookupResult* lookup,
1472 State state, 1328 State state,
1473 StrictModeFlag strict_mode, 1329 StrictModeFlag strict_mode,
1474 Handle<JSObject> receiver, 1330 Handle<JSObject> receiver,
1475 Handle<String> name, 1331 Handle<String> name,
1476 Handle<Object> value) { 1332 Handle<Object> value) {
1477 // Skip JSGlobalProxy. 1333 // Skip JSGlobalProxy.
1478 ASSERT(!receiver->IsJSGlobalProxy()); 1334 ASSERT(!receiver->IsJSGlobalProxy());
1479 1335
1480 ASSERT(StoreICableLookup(lookup)); 1336 ASSERT(StoreICableLookup(lookup));
1481 1337
1482 // If the property has a non-field type allowing map transitions 1338 // If the property has a non-field type allowing map transitions
1483 // where there is extra room in the object, we leave the IC in its 1339 // where there is extra room in the object, we leave the IC in its
1484 // current state. 1340 // current state.
1485 PropertyType type = lookup->type(); 1341 PropertyType type = lookup->type();
1486 1342
1487 // Compute the code stub for this store; used for rewriting to 1343 // Compute the code stub for this store; used for rewriting to
1488 // monomorphic state and making sure that the code stub is in the 1344 // monomorphic state and making sure that the code stub is in the
1489 // stub cache. 1345 // stub cache.
1490 MaybeObject* maybe_code = NULL; 1346 Handle<Code> code;
1491 Object* code = NULL;
1492 switch (type) { 1347 switch (type) {
1493 case FIELD: { 1348 case FIELD:
1494 maybe_code = isolate()->stub_cache()->ComputeStoreField( 1349 code = isolate()->stub_cache()->ComputeStoreField(name,
1495 *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode); 1350 receiver,
1351 lookup->GetFieldIndex(),
1352 Handle<Map>::null(),
1353 strict_mode);
1496 break; 1354 break;
1497 }
1498 case MAP_TRANSITION: { 1355 case MAP_TRANSITION: {
1499 if (lookup->GetAttributes() != NONE) return; 1356 if (lookup->GetAttributes() != NONE) return;
1500 HandleScope scope(isolate());
1501 ASSERT(type == MAP_TRANSITION); 1357 ASSERT(type == MAP_TRANSITION);
1502 Handle<Map> transition(lookup->GetTransitionMap()); 1358 Handle<Map> transition(lookup->GetTransitionMap());
1503 int index = transition->PropertyIndexFor(*name); 1359 int index = transition->PropertyIndexFor(*name);
1504 maybe_code = isolate()->stub_cache()->ComputeStoreField( 1360 code = isolate()->stub_cache()->ComputeStoreField(
1505 *name, *receiver, index, *transition, strict_mode); 1361 name, receiver, index, transition, strict_mode);
1506 break; 1362 break;
1507 } 1363 }
1508 case NORMAL: { 1364 case NORMAL:
1509 if (receiver->IsGlobalObject()) { 1365 if (receiver->IsGlobalObject()) {
1510 // The stub generated for the global object picks the value directly 1366 // The stub generated for the global object picks the value directly
1511 // from the property cell. So the property must be directly on the 1367 // from the property cell. So the property must be directly on the
1512 // global object. 1368 // global object.
1513 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); 1369 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
1514 JSGlobalPropertyCell* cell = 1370 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup));
1515 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); 1371 code = isolate()->stub_cache()->ComputeStoreGlobal(
1516 maybe_code = isolate()->stub_cache()->ComputeStoreGlobal( 1372 name, global, cell, strict_mode);
1517 *name, *global, cell, strict_mode);
1518 } else { 1373 } else {
1519 if (lookup->holder() != *receiver) return; 1374 if (lookup->holder() != *receiver) return;
1520 maybe_code = isolate()->stub_cache()->ComputeStoreNormal(strict_mode); 1375 code = isolate()->stub_cache()->ComputeStoreNormal(strict_mode);
1521 } 1376 }
1522 break; 1377 break;
1523 }
1524 case CALLBACKS: { 1378 case CALLBACKS: {
1525 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; 1379 Handle<Object> callback_object(lookup->GetCallbackObject());
1526 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); 1380 if (!callback_object->IsAccessorInfo()) return;
1381 Handle<AccessorInfo> callback =
1382 Handle<AccessorInfo>::cast(callback_object);
1527 if (v8::ToCData<Address>(callback->setter()) == 0) return; 1383 if (v8::ToCData<Address>(callback->setter()) == 0) return;
1528 maybe_code = isolate()->stub_cache()->ComputeStoreCallback( 1384 code = isolate()->stub_cache()->ComputeStoreCallback(
1529 *name, *receiver, callback, strict_mode); 1385 name, receiver, callback, strict_mode);
1530 break; 1386 break;
1531 } 1387 }
1532 case INTERCEPTOR: { 1388 case INTERCEPTOR:
1533 ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined()); 1389 ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined());
1534 maybe_code = isolate()->stub_cache()->ComputeStoreInterceptor( 1390 code = isolate()->stub_cache()->ComputeStoreInterceptor(
1535 *name, *receiver, strict_mode); 1391 name, receiver, strict_mode);
1536 break; 1392 break;
1537 }
1538 default: 1393 default:
1539 return; 1394 return;
1540 } 1395 }
1541 1396
1542 // If we're unable to compute the stub (not enough memory left), we
1543 // simply avoid updating the caches.
1544 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
1545
1546 // Patch the call site depending on the state of the cache. 1397 // Patch the call site depending on the state of the cache.
1547 if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) { 1398 if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) {
1548 set_target(Code::cast(code)); 1399 set_target(*code);
1549 } else if (state == MONOMORPHIC) { 1400 } else if (state == MONOMORPHIC) {
1550 // Only move to megamorphic if the target changes. 1401 // Only move to megamorphic if the target changes.
1551 if (target() != Code::cast(code)) { 1402 if (target() != *code) {
1552 set_target((strict_mode == kStrictMode) 1403 set_target((strict_mode == kStrictMode)
1553 ? megamorphic_stub_strict() 1404 ? megamorphic_stub_strict()
1554 : megamorphic_stub()); 1405 : megamorphic_stub());
1555 } 1406 }
1556 } else if (state == MEGAMORPHIC) { 1407 } else if (state == MEGAMORPHIC) {
1557 // Update the stub cache. 1408 // Update the stub cache.
1558 isolate()->stub_cache()->Set(*name, 1409 isolate()->stub_cache()->Set(*name, receiver->map(), *code);
1559 receiver->map(),
1560 Code::cast(code));
1561 } 1410 }
1562 1411
1563 #ifdef DEBUG 1412 TRACE_IC("StoreIC", name, state, target());
1564 TraceIC("StoreIC", name, state, target());
1565 #endif
1566 } 1413 }
1567 1414
1568 1415
1569 static bool AddOneReceiverMapIfMissing(MapList* receiver_maps, 1416 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps,
1570 Map* new_receiver_map) { 1417 Handle<Map> new_receiver_map) {
1418 ASSERT(!new_receiver_map.is_null());
1571 for (int current = 0; current < receiver_maps->length(); ++current) { 1419 for (int current = 0; current < receiver_maps->length(); ++current) {
1572 if (receiver_maps->at(current) == new_receiver_map) { 1420 if (!receiver_maps->at(current).is_null() &&
1421 receiver_maps->at(current).is_identical_to(new_receiver_map)) {
1573 return false; 1422 return false;
1574 } 1423 }
1575 } 1424 }
1576 receiver_maps->Add(new_receiver_map); 1425 receiver_maps->Add(new_receiver_map);
1577 return true; 1426 return true;
1578 } 1427 }
1579 1428
1580 1429
1581 void KeyedIC::GetReceiverMapsForStub(Code* stub, MapList* result) { 1430 void KeyedIC::GetReceiverMapsForStub(Handle<Code> stub,
1431 MapHandleList* result) {
1582 ASSERT(stub->is_inline_cache_stub()); 1432 ASSERT(stub->is_inline_cache_stub());
1583 if (stub == string_stub()) { 1433 if (!string_stub().is_null() && stub.is_identical_to(string_stub())) {
1584 return result->Add(isolate()->heap()->string_map()); 1434 return result->Add(isolate()->factory()->string_map());
1585 } else if (stub->is_keyed_load_stub() || stub->is_keyed_store_stub()) { 1435 } else if (stub->is_keyed_load_stub() || stub->is_keyed_store_stub()) {
1586 if (stub->ic_state() == MONOMORPHIC) { 1436 if (stub->ic_state() == MONOMORPHIC) {
1587 result->Add(Map::cast(stub->FindFirstMap())); 1437 result->Add(Handle<Map>(stub->FindFirstMap()));
1588 } else { 1438 } else {
1589 ASSERT(stub->ic_state() == MEGAMORPHIC); 1439 ASSERT(stub->ic_state() == MEGAMORPHIC);
1590 AssertNoAllocation no_allocation; 1440 AssertNoAllocation no_allocation;
1591 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); 1441 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
1592 for (RelocIterator it(stub, mask); !it.done(); it.next()) { 1442 for (RelocIterator it(*stub, mask); !it.done(); it.next()) {
1593 RelocInfo* info = it.rinfo(); 1443 RelocInfo* info = it.rinfo();
1594 Object* object = info->target_object(); 1444 Handle<Object> object(info->target_object());
1595 ASSERT(object->IsMap()); 1445 ASSERT(object->IsMap());
1596 result->Add(Map::cast(object)); 1446 AddOneReceiverMapIfMissing(result, Handle<Map>::cast(object));
1597 } 1447 }
1598 } 1448 }
1599 } 1449 }
1600 } 1450 }
1601 1451
1602 1452
1603 MaybeObject* KeyedIC::ComputeStub(JSObject* receiver, 1453 Handle<Code> KeyedIC::ComputeStub(Handle<JSObject> receiver,
1604 StubKind stub_kind, 1454 StubKind stub_kind,
1605 StrictModeFlag strict_mode, 1455 StrictModeFlag strict_mode,
1606 Code* generic_stub) { 1456 Handle<Code> generic_stub) {
1607 State ic_state = target()->ic_state(); 1457 State ic_state = target()->ic_state();
1608 if ((ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) && 1458 if ((ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) &&
1609 !IsTransitionStubKind(stub_kind)) { 1459 !IsTransitionStubKind(stub_kind)) {
1610 Code* monomorphic_stub; 1460 return ComputeMonomorphicStub(
1611 MaybeObject* maybe_stub = ComputeMonomorphicStub(receiver, 1461 receiver, stub_kind, strict_mode, generic_stub);
1612 stub_kind,
1613 strict_mode,
1614 generic_stub);
1615 if (!maybe_stub->To(&monomorphic_stub)) return maybe_stub;
1616
1617 return monomorphic_stub;
1618 } 1462 }
1619 ASSERT(target() != generic_stub); 1463 ASSERT(target() != *generic_stub);
1620 1464
1621 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS 1465 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS
1622 // via megamorphic stubs, since they don't have a map in their relocation info 1466 // via megamorphic stubs, since they don't have a map in their relocation info
1623 // and so the stubs can't be harvested for the object needed for a map check. 1467 // and so the stubs can't be harvested for the object needed for a map check.
1624 if (target()->type() != NORMAL) { 1468 if (target()->type() != NORMAL) {
1625 return generic_stub; 1469 return generic_stub;
1626 } 1470 }
1627 1471
1628 // Determine the list of receiver maps that this call site has seen, 1472 // Determine the list of receiver maps that this call site has seen,
1629 // adding the map that was just encountered. 1473 // adding the map that was just encountered.
1630 MapList target_receiver_maps; 1474 MapHandleList target_receiver_maps;
1475 Handle<Map> receiver_map(receiver->map());
1631 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) { 1476 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) {
1632 target_receiver_maps.Add(receiver->map()); 1477 target_receiver_maps.Add(receiver_map);
1633 } else { 1478 } else {
1634 GetReceiverMapsForStub(target(), &target_receiver_maps); 1479 GetReceiverMapsForStub(Handle<Code>(target()), &target_receiver_maps);
1635 } 1480 }
1636 bool map_added = 1481 bool map_added =
1637 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver->map()); 1482 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map);
1638 if (IsTransitionStubKind(stub_kind)) { 1483 if (IsTransitionStubKind(stub_kind)) {
1639 MaybeObject* maybe_map = ComputeTransitionedMap(receiver, stub_kind); 1484 Handle<Map> new_map = ComputeTransitionedMap(receiver, stub_kind);
1640 Map* new_map = NULL;
1641 if (!maybe_map->To(&new_map)) return maybe_map;
1642 map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps, new_map); 1485 map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps, new_map);
1643 } 1486 }
1644 if (!map_added) { 1487 if (!map_added) {
1645 // If the miss wasn't due to an unseen map, a polymorphic stub 1488 // If the miss wasn't due to an unseen map, a polymorphic stub
1646 // won't help, use the generic stub. 1489 // won't help, use the generic stub.
1647 return generic_stub; 1490 return generic_stub;
1648 } 1491 }
1649 1492
1650 // If the maximum number of receiver maps has been exceeded, use the generic 1493 // If the maximum number of receiver maps has been exceeded, use the generic
1651 // version of the IC. 1494 // version of the IC.
1652 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { 1495 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) {
1653 return generic_stub; 1496 return generic_stub;
1654 } 1497 }
1655 1498
1656 PolymorphicCodeCache* cache = isolate()->heap()->polymorphic_code_cache(); 1499 Handle<PolymorphicCodeCache> cache =
1657 Code::Flags flags = Code::ComputeFlags(this->kind(), 1500 isolate()->factory()->polymorphic_code_cache();
1658 MEGAMORPHIC, 1501 Code::Flags flags = Code::ComputeFlags(kind(), MEGAMORPHIC, strict_mode);
1659 strict_mode); 1502 Handle<Object> probe = cache->Lookup(&target_receiver_maps, flags);
1660 Object* maybe_cached_stub = cache->Lookup(&target_receiver_maps, flags); 1503 if (probe->IsCode()) return Handle<Code>::cast(probe);
1661 // If there is a cached stub, use it. 1504
1662 if (!maybe_cached_stub->IsUndefined()) { 1505 Handle<Code> stub =
1663 ASSERT(maybe_cached_stub->IsCode());
1664 return Code::cast(maybe_cached_stub);
1665 }
1666 MaybeObject* maybe_stub =
1667 ComputePolymorphicStub(&target_receiver_maps, strict_mode); 1506 ComputePolymorphicStub(&target_receiver_maps, strict_mode);
1668 Code* stub; 1507 PolymorphicCodeCache::Update(cache, &target_receiver_maps, flags, stub);
1669 if (!maybe_stub->To(&stub)) return maybe_stub;
1670 MaybeObject* maybe_update = cache->Update(&target_receiver_maps, flags, stub);
1671 if (maybe_update->IsFailure()) return maybe_update;
1672 return stub; 1508 return stub;
1673 } 1509 }
1674 1510
1675 1511
1676 MaybeObject* KeyedIC::ComputeMonomorphicStubWithoutMapCheck( 1512 Handle<Code> KeyedIC::ComputeMonomorphicStubWithoutMapCheck(
1677 Map* receiver_map, 1513 Handle<Map> receiver_map,
1678 StrictModeFlag strict_mode) { 1514 StrictModeFlag strict_mode) {
1679 if ((receiver_map->instance_type() & kNotStringTag) == 0) { 1515 if ((receiver_map->instance_type() & kNotStringTag) == 0) {
1680 ASSERT(string_stub() != NULL); 1516 ASSERT(!string_stub().is_null());
1681 return string_stub(); 1517 return string_stub();
1682 } else { 1518 } else {
1683 ASSERT(receiver_map->has_dictionary_elements() || 1519 ASSERT(receiver_map->has_dictionary_elements() ||
1684 receiver_map->has_fast_elements() || 1520 receiver_map->has_fast_elements() ||
1685 receiver_map->has_fast_smi_only_elements() || 1521 receiver_map->has_fast_smi_only_elements() ||
1686 receiver_map->has_fast_double_elements() || 1522 receiver_map->has_fast_double_elements() ||
1687 receiver_map->has_external_array_elements()); 1523 receiver_map->has_external_array_elements());
1688 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; 1524 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
1689 return GetElementStubWithoutMapCheck(is_js_array, 1525 return GetElementStubWithoutMapCheck(is_js_array,
1690 receiver_map->elements_kind()); 1526 receiver_map->elements_kind());
1691 } 1527 }
1692 } 1528 }
1693 1529
1694 1530
1695 MaybeObject* KeyedIC::ComputeMonomorphicStub(JSObject* receiver, 1531 Handle<Code> KeyedIC::ComputeMonomorphicStub(Handle<JSObject> receiver,
1696 StubKind stub_kind, 1532 StubKind stub_kind,
1697 StrictModeFlag strict_mode, 1533 StrictModeFlag strict_mode,
1698 Code* generic_stub) { 1534 Handle<Code> generic_stub) {
1699 Code* result = NULL;
1700 if (receiver->HasFastElements() || 1535 if (receiver->HasFastElements() ||
1701 receiver->HasFastSmiOnlyElements() || 1536 receiver->HasFastSmiOnlyElements() ||
1702 receiver->HasExternalArrayElements() || 1537 receiver->HasExternalArrayElements() ||
1703 receiver->HasFastDoubleElements() || 1538 receiver->HasFastDoubleElements() ||
1704 receiver->HasDictionaryElements()) { 1539 receiver->HasDictionaryElements()) {
1705 MaybeObject* maybe_stub = 1540 return isolate()->stub_cache()->ComputeKeyedLoadOrStoreElement(
1706 isolate()->stub_cache()->ComputeKeyedLoadOrStoreElement( 1541 receiver, stub_kind, strict_mode);
1707 receiver, stub_kind, strict_mode);
1708 if (!maybe_stub->To(&result)) return maybe_stub;
1709 } else { 1542 } else {
1710 result = generic_stub; 1543 return generic_stub;
1711 }
1712 return result;
1713 }
1714
1715
1716 MaybeObject* KeyedIC::ComputeTransitionedMap(JSObject* receiver,
1717 StubKind stub_kind) {
1718 switch (stub_kind) {
1719 case KeyedIC::STORE_TRANSITION_SMI_TO_OBJECT:
1720 case KeyedIC::STORE_TRANSITION_DOUBLE_TO_OBJECT:
1721 return receiver->GetElementsTransitionMap(FAST_ELEMENTS);
1722 case KeyedIC::STORE_TRANSITION_SMI_TO_DOUBLE:
1723 return receiver->GetElementsTransitionMap(FAST_DOUBLE_ELEMENTS);
1724 default:
1725 UNREACHABLE();
1726 return NULL;
1727 } 1544 }
1728 } 1545 }
1729 1546
1730 1547
1731 MaybeObject* KeyedStoreIC::GetElementStubWithoutMapCheck( 1548 Handle<Map> KeyedIC::ComputeTransitionedMap(Handle<JSObject> receiver,
1732 bool is_js_array, 1549 StubKind stub_kind) {
1733 ElementsKind elements_kind) { 1550 switch (stub_kind) {
1734 return KeyedStoreElementStub(is_js_array, elements_kind).TryGetCode(); 1551 case KeyedIC::STORE_TRANSITION_SMI_TO_OBJECT:
1552 case KeyedIC::STORE_TRANSITION_DOUBLE_TO_OBJECT:
1553 return JSObject::GetElementsTransitionMap(receiver, FAST_ELEMENTS);
1554 break;
1555 case KeyedIC::STORE_TRANSITION_SMI_TO_DOUBLE:
1556 return JSObject::GetElementsTransitionMap(receiver, FAST_DOUBLE_ELEMENTS);
1557 break;
1558 default:
1559 UNREACHABLE();
1560 return Handle<Map>::null();
1561 }
1735 } 1562 }
1736 1563
1737 1564
1738 // If |map| is contained in |maps_list|, returns |map|; otherwise returns NULL. 1565 Handle<Code> KeyedStoreIC::GetElementStubWithoutMapCheck(
1739 Map* GetMapIfPresent(Map* map, MapList* maps_list) { 1566 bool is_js_array,
1740 for (int i = 0; i < maps_list->length(); ++i) { 1567 ElementsKind elements_kind) {
1741 if (maps_list->at(i) == map) return map; 1568 return KeyedStoreElementStub(is_js_array, elements_kind).GetCode();
1742 }
1743 return NULL;
1744 } 1569 }
1745 1570
1746 1571
1747 // Returns the most generic transitioned map for |map| that's found in 1572 Handle<Code> KeyedStoreIC::ComputePolymorphicStub(MapHandleList* receiver_maps,
1748 // |maps_list|, or NULL if no transitioned map for |map| is found at all. 1573 StrictModeFlag strict_mode) {
1749 Map* GetTransitionedMap(Map* map, MapList* maps_list) { 1574 // Collect MONOMORPHIC stubs for all target_receiver_maps.
1750 ElementsKind elements_kind = map->elements_kind(); 1575 CodeHandleList handler_ics(receiver_maps->length());
1751 if (elements_kind == FAST_ELEMENTS) { 1576 MapHandleList transitioned_maps(receiver_maps->length());
1752 return NULL; 1577 for (int i = 0; i < receiver_maps->length(); ++i) {
1578 Handle<Map> receiver_map(receiver_maps->at(i));
1579 Handle<Code> cached_stub;
1580 Handle<Map> transitioned_map =
1581 receiver_map->FindTransitionedMap(receiver_maps);
1582 if (!transitioned_map.is_null()) {
1583 cached_stub = ElementsTransitionAndStoreStub(
1584 receiver_map->elements_kind(), // original elements_kind
1585 transitioned_map->elements_kind(),
1586 receiver_map->instance_type() == JS_ARRAY_TYPE, // is_js_array
1587 strict_mode).GetCode();
1588 } else {
1589 cached_stub = ComputeMonomorphicStubWithoutMapCheck(receiver_map,
1590 strict_mode);
1591 }
1592 ASSERT(!cached_stub.is_null());
1593 handler_ics.Add(cached_stub);
1594 transitioned_maps.Add(transitioned_map);
1753 } 1595 }
1754 if (elements_kind == FAST_DOUBLE_ELEMENTS) { 1596 KeyedStoreStubCompiler compiler(isolate(), strict_mode);
1755 bool dummy = true; 1597 Handle<Code> code = compiler.CompileStorePolymorphic(
1756 Map* fast_map = map->LookupElementsTransitionMap(FAST_ELEMENTS, &dummy); 1598 receiver_maps, &handler_ics, &transitioned_maps);
1757 if (fast_map == NULL) return NULL; 1599 isolate()->counters()->keyed_store_polymorphic_stubs()->Increment();
1758 return GetMapIfPresent(fast_map, maps_list); 1600 PROFILE(isolate(),
1759 } 1601 CodeCreateEvent(Logger::KEYED_STORE_MEGAMORPHIC_IC_TAG, *code, 0));
1760 if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { 1602 return code;
1761 bool dummy = true;
1762 Map* double_map = map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS,
1763 &dummy);
1764 // In the current implementation, if the DOUBLE map doesn't exist, the
1765 // FAST map can't exist either.
1766 if (double_map == NULL) return NULL;
1767 Map* fast_map = map->LookupElementsTransitionMap(FAST_ELEMENTS, &dummy);
1768 if (fast_map == NULL) {
1769 return GetMapIfPresent(double_map, maps_list);
1770 }
1771 // Both double_map and fast_map are non-NULL. Return fast_map if it's in
1772 // maps_list, double_map otherwise.
1773 Map* fast_map_present = GetMapIfPresent(fast_map, maps_list);
1774 if (fast_map_present != NULL) return fast_map_present;
1775 return GetMapIfPresent(double_map, maps_list);
1776 }
1777 return NULL;
1778 } 1603 }
1779 1604
1780 1605
1781 MaybeObject* KeyedStoreIC::ComputePolymorphicStub(
1782 MapList* receiver_maps,
1783 StrictModeFlag strict_mode) {
1784 // TODO(yangguo): <remove>
1785 Code* generic_stub = (strict_mode == kStrictMode)
1786 ? isolate()->builtins()->builtin(Builtins::kKeyedStoreIC_Generic_Strict)
1787 : isolate()->builtins()->builtin(Builtins::kKeyedStoreIC_Generic);
1788 // </remove>
1789
1790 // Collect MONOMORPHIC stubs for all target_receiver_maps.
1791 CodeList handler_ics(receiver_maps->length());
1792 MapList transitioned_maps(receiver_maps->length());
1793 for (int i = 0; i < receiver_maps->length(); ++i) {
1794 Map* receiver_map(receiver_maps->at(i));
1795 MaybeObject* maybe_cached_stub = NULL;
1796 Map* transitioned_map = GetTransitionedMap(receiver_map, receiver_maps);
1797 if (transitioned_map != NULL) {
1798 // TODO(yangguo): Enable this code!
1799 // maybe_cached_stub = FastElementsConversionStub(
1800 // receiver_map->elements_kind(), // original elements_kind
1801 // transitioned_map->elements_kind(),
1802 // receiver_map->instance_type() == JS_ARRAY_TYPE, // is_js_array
1803 // strict_mode_).TryGetCode();
1804 // TODO(yangguo): <remove>
1805 maybe_cached_stub = generic_stub;
1806 // </remove>
1807 } else {
1808 maybe_cached_stub = ComputeMonomorphicStubWithoutMapCheck(
1809 receiver_map, strict_mode);
1810 }
1811 Code* cached_stub;
1812 if (!maybe_cached_stub->To(&cached_stub)) return maybe_cached_stub;
1813 handler_ics.Add(cached_stub);
1814 transitioned_maps.Add(transitioned_map);
1815 }
1816 Object* object;
1817 KeyedStoreStubCompiler compiler(strict_mode);
1818 MaybeObject* maybe_code = compiler.CompileStorePolymorphic(
1819 receiver_maps, &handler_ics, &transitioned_maps);
1820 if (!maybe_code->ToObject(&object)) return maybe_code;
1821 isolate()->counters()->keyed_store_polymorphic_stubs()->Increment();
1822 PROFILE(isolate(), CodeCreateEvent(
1823 Logger::KEYED_STORE_MEGAMORPHIC_IC_TAG,
1824 Code::cast(object), 0));
1825 return object;
1826 }
1827
1828
1829 MaybeObject* KeyedStoreIC::Store(State state, 1606 MaybeObject* KeyedStoreIC::Store(State state,
1830 StrictModeFlag strict_mode, 1607 StrictModeFlag strict_mode,
1831 Handle<Object> object, 1608 Handle<Object> object,
1832 Handle<Object> key, 1609 Handle<Object> key,
1833 Handle<Object> value, 1610 Handle<Object> value,
1834 bool force_generic) { 1611 bool force_generic) {
1835 if (key->IsSymbol()) { 1612 if (key->IsSymbol()) {
1836 Handle<String> name = Handle<String>::cast(key); 1613 Handle<String> name = Handle<String>::cast(key);
1837 1614
1615 // Handle proxies.
1616 if (object->IsJSProxy()) {
1617 return JSProxy::cast(*object)->SetProperty(
1618 *name, *value, NONE, strict_mode);
1619 }
1620
1838 // If the object is undefined or null it's illegal to try to set any 1621 // If the object is undefined or null it's illegal to try to set any
1839 // properties on it; throw a TypeError in that case. 1622 // properties on it; throw a TypeError in that case.
1840 if (object->IsUndefined() || object->IsNull()) { 1623 if (object->IsUndefined() || object->IsNull()) {
1841 return TypeError("non_object_property_store", object, name); 1624 return TypeError("non_object_property_store", object, name);
1842 } 1625 }
1843 1626
1844 // Ignore stores where the receiver is not a JSObject. 1627 // Ignore stores where the receiver is not a JSObject.
1845 if (!object->IsJSObject()) return *value; 1628 if (!object->IsJSObject()) return *value;
1846 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1629 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1847 1630
1848 // Check if the given name is an array index. 1631 // Check if the given name is an array index.
1849 uint32_t index; 1632 uint32_t index;
1850 if (name->AsArrayIndex(&index)) { 1633 if (name->AsArrayIndex(&index)) {
1851 HandleScope scope(isolate());
1852 Handle<Object> result = SetElement(receiver, index, value, strict_mode); 1634 Handle<Object> result = SetElement(receiver, index, value, strict_mode);
1853 if (result.is_null()) return Failure::Exception(); 1635 RETURN_IF_EMPTY_HANDLE(isolate(), result);
1854 return *value; 1636 return *value;
1855 } 1637 }
1856 1638
1857 // Lookup the property locally in the receiver. 1639 // Lookup the property locally in the receiver.
1858 LookupResult lookup; 1640 LookupResult lookup(isolate());
1859 receiver->LocalLookup(*name, &lookup); 1641 receiver->LocalLookup(*name, &lookup);
1860 1642
1861 // Update inline cache and stub cache. 1643 // Update inline cache and stub cache.
1862 if (FLAG_use_ic) { 1644 if (FLAG_use_ic) {
1863 UpdateCaches(&lookup, state, strict_mode, receiver, name, value); 1645 UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
1864 } 1646 }
1865 1647
1866 // Set the property. 1648 // Set the property.
1867 return receiver->SetProperty(*name, *value, NONE, strict_mode); 1649 return receiver->SetProperty(*name, *value, NONE, strict_mode);
1868 } 1650 }
1869 1651
1870 // Do not use ICs for objects that require access checks (including 1652 // Do not use ICs for objects that require access checks (including
1871 // the global object). 1653 // the global object).
1872 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); 1654 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
1873 ASSERT(!(use_ic && object->IsJSGlobalProxy())); 1655 ASSERT(!(use_ic && object->IsJSGlobalProxy()));
1874 1656
1875 if (use_ic) { 1657 if (use_ic) {
1876 Code* stub = (strict_mode == kStrictMode) 1658 Handle<Code> stub = (strict_mode == kStrictMode)
1877 ? generic_stub_strict() 1659 ? generic_stub_strict()
1878 : generic_stub(); 1660 : generic_stub();
1879 if (object->IsJSObject()) { 1661 if (object->IsJSObject()) {
1880 JSObject* receiver = JSObject::cast(*object); 1662 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1881 Heap* heap = Handle<JSObject>::cast(object)->GetHeap(); 1663 if (receiver->elements()->map() ==
1882 Map* elements_map = Handle<JSObject>::cast(object)->elements()->map(); 1664 isolate()->heap()->non_strict_arguments_elements_map()) {
1883 if (elements_map == heap->non_strict_arguments_elements_map()) {
1884 stub = non_strict_arguments_stub(); 1665 stub = non_strict_arguments_stub();
1885 } else if (!force_generic) { 1666 } else if (!force_generic) {
1886 if (key->IsSmi() && (target() != non_strict_arguments_stub())) { 1667 if (key->IsSmi() && (target() != *non_strict_arguments_stub())) {
1887 StubKind stub_kind = STORE_NO_TRANSITION; 1668 StubKind stub_kind = STORE_NO_TRANSITION;
1888 if (receiver->GetElementsKind() == FAST_SMI_ONLY_ELEMENTS) { 1669 if (receiver->GetElementsKind() == FAST_SMI_ONLY_ELEMENTS) {
1889 if (value->IsHeapNumber()) { 1670 if (value->IsHeapNumber()) {
1890 stub_kind = STORE_TRANSITION_SMI_TO_DOUBLE; 1671 stub_kind = STORE_TRANSITION_SMI_TO_DOUBLE;
1891 } else if (value->IsHeapObject()) { 1672 } else if (value->IsHeapObject()) {
1892 stub_kind = STORE_TRANSITION_SMI_TO_OBJECT; 1673 stub_kind = STORE_TRANSITION_SMI_TO_OBJECT;
1893 } 1674 }
1894 } else if (receiver->GetElementsKind() == FAST_DOUBLE_ELEMENTS) { 1675 } else if (receiver->GetElementsKind() == FAST_DOUBLE_ELEMENTS) {
1895 if (!value->IsSmi() && !value->IsHeapNumber()) { 1676 if (!value->IsSmi() && !value->IsHeapNumber()) {
1896 stub_kind = STORE_TRANSITION_DOUBLE_TO_OBJECT; 1677 stub_kind = STORE_TRANSITION_DOUBLE_TO_OBJECT;
1897 } 1678 }
1898 } 1679 }
1899 HandleScope scope(isolate()); 1680 stub = ComputeStub(receiver, stub_kind, strict_mode, stub);
1900 MaybeObject* maybe_stub = ComputeStub(receiver,
1901 stub_kind,
1902 strict_mode,
1903 stub);
1904 stub = maybe_stub->IsFailure() ?
1905 NULL : Code::cast(maybe_stub->ToObjectUnchecked());
1906 } 1681 }
1907 } 1682 }
1908 } 1683 }
1909 if (stub != NULL) set_target(stub); 1684 if (!stub.is_null()) set_target(*stub);
1910 } 1685 }
1911 1686
1912 #ifdef DEBUG 1687 TRACE_IC("KeyedStoreIC", key, state, target());
1913 TraceIC("KeyedStoreIC", key, state, target());
1914 #endif
1915 1688
1916 // Set the property. 1689 // Set the property.
1917 return Runtime::SetObjectProperty( 1690 return Runtime::SetObjectProperty(
1918 isolate(), object , key, value, NONE, strict_mode); 1691 isolate(), object , key, value, NONE, strict_mode);
1919 } 1692 }
1920 1693
1921 1694
1922 void KeyedStoreIC::UpdateCaches(LookupResult* lookup, 1695 void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
1923 State state, 1696 State state,
1924 StrictModeFlag strict_mode, 1697 StrictModeFlag strict_mode,
(...skipping 11 matching lines...) Expand all
1936 if (lookup->IsReadOnly()) return; 1709 if (lookup->IsReadOnly()) return;
1937 1710
1938 // If the property has a non-field type allowing map transitions 1711 // If the property has a non-field type allowing map transitions
1939 // where there is extra room in the object, we leave the IC in its 1712 // where there is extra room in the object, we leave the IC in its
1940 // current state. 1713 // current state.
1941 PropertyType type = lookup->type(); 1714 PropertyType type = lookup->type();
1942 1715
1943 // Compute the code stub for this store; used for rewriting to 1716 // Compute the code stub for this store; used for rewriting to
1944 // monomorphic state and making sure that the code stub is in the 1717 // monomorphic state and making sure that the code stub is in the
1945 // stub cache. 1718 // stub cache.
1946 MaybeObject* maybe_code = NULL; 1719 Handle<Code> code;
1947 Object* code = NULL;
1948 1720
1949 switch (type) { 1721 switch (type) {
1950 case FIELD: { 1722 case FIELD:
1951 maybe_code = isolate()->stub_cache()->ComputeKeyedStoreField( 1723 code = isolate()->stub_cache()->ComputeKeyedStoreField(
1952 *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode); 1724 name, receiver, lookup->GetFieldIndex(),
1725 Handle<Map>::null(), strict_mode);
1953 break; 1726 break;
1954 } 1727 case MAP_TRANSITION:
1955 case MAP_TRANSITION: {
1956 if (lookup->GetAttributes() == NONE) { 1728 if (lookup->GetAttributes() == NONE) {
1957 HandleScope scope(isolate());
1958 ASSERT(type == MAP_TRANSITION); 1729 ASSERT(type == MAP_TRANSITION);
1959 Handle<Map> transition(lookup->GetTransitionMap()); 1730 Handle<Map> transition(lookup->GetTransitionMap());
1960 int index = transition->PropertyIndexFor(*name); 1731 int index = transition->PropertyIndexFor(*name);
1961 maybe_code = isolate()->stub_cache()->ComputeKeyedStoreField( 1732 code = isolate()->stub_cache()->ComputeKeyedStoreField(
1962 *name, *receiver, index, *transition, strict_mode); 1733 name, receiver, index, transition, strict_mode);
1963 break; 1734 break;
1964 } 1735 }
1965 // fall through. 1736 // fall through.
1966 } 1737 default:
1967 default: {
1968 // Always rewrite to the generic case so that we do not 1738 // Always rewrite to the generic case so that we do not
1969 // repeatedly try to rewrite. 1739 // repeatedly try to rewrite.
1970 maybe_code = (strict_mode == kStrictMode) 1740 code = (strict_mode == kStrictMode)
1971 ? generic_stub_strict() 1741 ? generic_stub_strict()
1972 : generic_stub(); 1742 : generic_stub();
1973 break; 1743 break;
1974 }
1975 } 1744 }
1976 1745
1977 // If we're unable to compute the stub (not enough memory left), we 1746 ASSERT(!code.is_null());
1978 // simply avoid updating the caches.
1979 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
1980 1747
1981 // Patch the call site depending on the state of the cache. Make 1748 // Patch the call site depending on the state of the cache. Make
1982 // sure to always rewrite from monomorphic to megamorphic. 1749 // sure to always rewrite from monomorphic to megamorphic.
1983 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE); 1750 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE);
1984 if (state == UNINITIALIZED || state == PREMONOMORPHIC) { 1751 if (state == UNINITIALIZED || state == PREMONOMORPHIC) {
1985 set_target(Code::cast(code)); 1752 set_target(*code);
1986 } else if (state == MONOMORPHIC) { 1753 } else if (state == MONOMORPHIC) {
1987 set_target((strict_mode == kStrictMode) 1754 set_target((strict_mode == kStrictMode)
1988 ? megamorphic_stub_strict() 1755 ? *megamorphic_stub_strict()
1989 : megamorphic_stub()); 1756 : *megamorphic_stub());
1990 } 1757 }
1991 1758
1992 #ifdef DEBUG 1759 TRACE_IC("KeyedStoreIC", name, state, target());
1993 TraceIC("KeyedStoreIC", name, state, target());
1994 #endif
1995 } 1760 }
1996 1761
1997 1762
1763 #undef TRACE_IC
1764
1765
1998 // ---------------------------------------------------------------------------- 1766 // ----------------------------------------------------------------------------
1999 // Static IC stub generators. 1767 // Static IC stub generators.
2000 // 1768 //
2001 1769
2002 static JSFunction* CompileFunction(Isolate* isolate,
2003 JSFunction* function) {
2004 // Compile now with optimization.
2005 HandleScope scope(isolate);
2006 Handle<JSFunction> function_handle(function, isolate);
2007 CompileLazy(function_handle, CLEAR_EXCEPTION);
2008 return *function_handle;
2009 }
2010
2011
2012 // Used from ic-<arch>.cc. 1770 // Used from ic-<arch>.cc.
2013 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) { 1771 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) {
2014 NoHandleAllocation na; 1772 HandleScope scope(isolate);
2015 ASSERT(args.length() == 2); 1773 ASSERT(args.length() == 2);
2016 CallIC ic(isolate); 1774 CallIC ic(isolate);
2017 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 1775 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2018 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); 1776 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2019 MaybeObject* maybe_result = ic.LoadFunction(state, 1777 MaybeObject* maybe_result = ic.LoadFunction(state,
2020 extra_ic_state, 1778 extra_ic_state,
2021 args.at<Object>(0), 1779 args.at<Object>(0),
2022 args.at<String>(1)); 1780 args.at<String>(1));
2023 Object* result; 1781 // Result could be a function or a failure.
2024 if (!maybe_result->ToObject(&result)) return maybe_result; 1782 JSFunction* raw_function = NULL;
1783 if (!maybe_result->To(&raw_function)) return maybe_result;
2025 1784
2026 // The first time the inline cache is updated may be the first time the 1785 // The first time the inline cache is updated may be the first time the
2027 // function it references gets called. If the function was lazily compiled 1786 // function it references gets called. If the function is lazily compiled
2028 // then the first call will trigger a compilation. We check for this case 1787 // then the first call will trigger a compilation. We check for this case
2029 // and we do the compilation immediately, instead of waiting for the stub 1788 // and we do the compilation immediately, instead of waiting for the stub
2030 // currently attached to the JSFunction object to trigger compilation. We 1789 // currently attached to the JSFunction object to trigger compilation.
2031 // do this in the case where we know that the inline cache is inside a loop, 1790 if (raw_function->is_compiled()) return raw_function;
2032 // because then we know that we want to optimize the function. 1791
2033 if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { 1792 Handle<JSFunction> function(raw_function);
2034 return result; 1793 JSFunction::CompileLazy(function, CLEAR_EXCEPTION);
2035 } 1794 return *function;
2036 return CompileFunction(isolate, JSFunction::cast(result));
2037 } 1795 }
2038 1796
2039 1797
2040 // Used from ic-<arch>.cc. 1798 // Used from ic-<arch>.cc.
2041 RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) { 1799 RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) {
2042 NoHandleAllocation na; 1800 HandleScope scope(isolate);
2043 ASSERT(args.length() == 2); 1801 ASSERT(args.length() == 2);
2044 KeyedCallIC ic(isolate); 1802 KeyedCallIC ic(isolate);
2045 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 1803 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2046 Object* result; 1804 MaybeObject* maybe_result =
2047 { MaybeObject* maybe_result =
2048 ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1)); 1805 ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1));
2049 if (!maybe_result->ToObject(&result)) return maybe_result; 1806 // Result could be a function or a failure.
2050 } 1807 JSFunction* raw_function = NULL;
1808 if (!maybe_result->To(&raw_function)) return maybe_result;
2051 1809
2052 if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { 1810 if (raw_function->is_compiled()) return raw_function;
2053 return result; 1811
2054 } 1812 Handle<JSFunction> function(raw_function);
2055 return CompileFunction(isolate, JSFunction::cast(result)); 1813 JSFunction::CompileLazy(function, CLEAR_EXCEPTION);
1814 return *function;
2056 } 1815 }
2057 1816
2058 1817
2059 // Used from ic-<arch>.cc. 1818 // Used from ic-<arch>.cc.
2060 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { 1819 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) {
2061 NoHandleAllocation na; 1820 HandleScope scope(isolate);
2062 ASSERT(args.length() == 2); 1821 ASSERT(args.length() == 2);
2063 LoadIC ic(isolate); 1822 LoadIC ic(isolate);
2064 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 1823 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2065 return ic.Load(state, args.at<Object>(0), args.at<String>(1)); 1824 return ic.Load(state, args.at<Object>(0), args.at<String>(1));
2066 } 1825 }
2067 1826
2068 1827
2069 // Used from ic-<arch>.cc 1828 // Used from ic-<arch>.cc
2070 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) { 1829 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) {
2071 NoHandleAllocation na; 1830 HandleScope scope(isolate);
2072 ASSERT(args.length() == 2); 1831 ASSERT(args.length() == 2);
2073 KeyedLoadIC ic(isolate); 1832 KeyedLoadIC ic(isolate);
2074 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 1833 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2075 return ic.Load(state, args.at<Object>(0), args.at<Object>(1), false); 1834 return ic.Load(state, args.at<Object>(0), args.at<Object>(1), false);
2076 } 1835 }
2077 1836
2078 1837
2079 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) { 1838 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) {
2080 NoHandleAllocation na; 1839 HandleScope scope(isolate);
2081 ASSERT(args.length() == 2); 1840 ASSERT(args.length() == 2);
2082 KeyedLoadIC ic(isolate); 1841 KeyedLoadIC ic(isolate);
2083 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 1842 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2084 return ic.Load(state, args.at<Object>(0), args.at<Object>(1), true); 1843 return ic.Load(state, args.at<Object>(0), args.at<Object>(1), true);
2085 } 1844 }
2086 1845
2087 1846
2088 // Used from ic-<arch>.cc. 1847 // Used from ic-<arch>.cc.
2089 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) { 1848 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) {
2090 NoHandleAllocation na; 1849 HandleScope scope;
2091 ASSERT(args.length() == 3); 1850 ASSERT(args.length() == 3);
2092 StoreIC ic(isolate); 1851 StoreIC ic(isolate);
2093 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 1852 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2094 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); 1853 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2095 return ic.Store(state, 1854 return ic.Store(state,
2096 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode), 1855 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
2097 args.at<Object>(0), 1856 args.at<Object>(0),
2098 args.at<String>(1), 1857 args.at<String>(1),
2099 args.at<Object>(2)); 1858 args.at<Object>(2));
2100 } 1859 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
2149 object->set_properties(new_storage); 1908 object->set_properties(new_storage);
2150 object->set_map(transition); 1909 object->set_map(transition);
2151 1910
2152 // Return the stored value. 1911 // Return the stored value.
2153 return value; 1912 return value;
2154 } 1913 }
2155 1914
2156 1915
2157 // Used from ic-<arch>.cc. 1916 // Used from ic-<arch>.cc.
2158 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) { 1917 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) {
2159 NoHandleAllocation na; 1918 HandleScope scope(isolate);
2160 ASSERT(args.length() == 3); 1919 ASSERT(args.length() == 3);
2161 KeyedStoreIC ic(isolate); 1920 KeyedStoreIC ic(isolate);
2162 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 1921 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2163 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); 1922 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2164 return ic.Store(state, 1923 return ic.Store(state,
2165 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode), 1924 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
2166 args.at<Object>(0), 1925 args.at<Object>(0),
2167 args.at<Object>(1), 1926 args.at<Object>(1),
2168 args.at<Object>(2), 1927 args.at<Object>(2),
2169 false); 1928 false);
(...skipping 13 matching lines...) Expand all
2183 return Runtime::SetObjectProperty(isolate, 1942 return Runtime::SetObjectProperty(isolate,
2184 object, 1943 object,
2185 key, 1944 key,
2186 value, 1945 value,
2187 NONE, 1946 NONE,
2188 strict_mode); 1947 strict_mode);
2189 } 1948 }
2190 1949
2191 1950
2192 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) { 1951 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) {
2193 NoHandleAllocation na; 1952 HandleScope scope(isolate);
2194 ASSERT(args.length() == 3); 1953 ASSERT(args.length() == 3);
2195 KeyedStoreIC ic(isolate); 1954 KeyedStoreIC ic(isolate);
2196 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 1955 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2197 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); 1956 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2198 return ic.Store(state, 1957 return ic.Store(state,
2199 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode), 1958 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
2200 args.at<Object>(0), 1959 args.at<Object>(0),
2201 args.at<Object>(1), 1960 args.at<Object>(1),
2202 args.at<Object>(2), 1961 args.at<Object>(2),
2203 true); 1962 true);
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after
2618 #undef ADDR 2377 #undef ADDR
2619 }; 2378 };
2620 2379
2621 2380
2622 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2381 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2623 return IC_utilities[id]; 2382 return IC_utilities[id];
2624 } 2383 }
2625 2384
2626 2385
2627 } } // namespace v8::internal 2386 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/incremental-marking.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698