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

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

Issue 143633007: A64: Synchronize with r18764. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/macro-assembler-ia32.cc ('k') | src/ic.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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 __ CallExternalReference( 411 __ CallExternalReference(
412 ExternalReference(IC_Utility(id), masm->isolate()), 412 ExternalReference(IC_Utility(id), masm->isolate()),
413 StubCache::kInterceptorArgsLength); 413 StubCache::kInterceptorArgsLength);
414 } 414 }
415 415
416 416
417 // Number of pointers to be reserved on stack for fast API call. 417 // Number of pointers to be reserved on stack for fast API call.
418 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength; 418 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength;
419 419
420 420
421 // Reserves space for the extra arguments to API function in the
422 // caller's frame.
423 //
424 // These arguments are set by CheckPrototypes and GenerateFastApiCall.
425 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
426 // ----------- S t a t e -------------
427 // -- esp[0] : return address
428 // -- esp[4] : last argument in the internal frame of the caller
429 // -----------------------------------
430 __ pop(scratch);
431 for (int i = 0; i < kFastApiCallArguments; i++) {
432 __ push(Immediate(Smi::FromInt(0)));
433 }
434 __ push(scratch);
435 }
436
437
438 // Undoes the effects of ReserveSpaceForFastApiCall.
439 static void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
440 // ----------- S t a t e -------------
441 // -- esp[0] : return address.
442 // -- esp[4] : last fast api call extra argument.
443 // -- ...
444 // -- esp[kFastApiCallArguments * 4] : first fast api call extra argument.
445 // -- esp[kFastApiCallArguments * 4 + 4] : last argument in the internal
446 // frame.
447 // -----------------------------------
448 __ pop(scratch);
449 __ add(esp, Immediate(kPointerSize * kFastApiCallArguments));
450 __ push(scratch);
451 }
452
453
454 static void GenerateFastApiCallBody(MacroAssembler* masm, 421 static void GenerateFastApiCallBody(MacroAssembler* masm,
455 const CallOptimization& optimization, 422 const CallOptimization& optimization,
456 int argc, 423 int argc,
424 Register holder,
425 Register scratch1,
426 Register scratch2,
427 Register scratch3,
457 bool restore_context); 428 bool restore_context);
458 429
459
460 // Generates call to API function. 430 // Generates call to API function.
461 static void GenerateFastApiCall(MacroAssembler* masm, 431 static void GenerateFastApiCall(MacroAssembler* masm,
462 const CallOptimization& optimization, 432 const CallOptimization& optimization,
463 int argc) { 433 int argc,
464 typedef FunctionCallbackArguments FCA; 434 Handle<Map> map_to_holder,
465 // Save calling context. 435 CallOptimization::HolderLookup holder_lookup) {
466 __ mov(Operand(esp, (1 + FCA::kContextSaveIndex) * kPointerSize), esi); 436 Counters* counters = masm->isolate()->counters();
437 __ IncrementCounter(counters->call_const_fast_api(), 1);
467 438
468 // Get the function and setup the context. 439 // Move holder to a register
469 Handle<JSFunction> function = optimization.constant_function(); 440 Register holder_reg = eax;
470 __ LoadHeapObject(edi, function); 441 switch (holder_lookup) {
471 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 442 case CallOptimization::kHolderIsReceiver:
472 443 {
473 // Construct the FunctionCallbackInfo. 444 ASSERT(map_to_holder.is_null());
474 __ mov(Operand(esp, (1 + FCA::kCalleeIndex) * kPointerSize), edi); 445 __ mov(holder_reg, Operand(esp, (argc + 1)* kPointerSize));
475 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 446 }
476 Handle<Object> call_data(api_call_info->data(), masm->isolate()); 447 break;
477 if (masm->isolate()->heap()->InNewSpace(*call_data)) { 448 case CallOptimization::kHolderIsPrototypeOfMap:
478 __ mov(ecx, api_call_info); 449 {
479 __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset)); 450 Handle<JSObject> holder(JSObject::cast(map_to_holder->prototype()));
480 __ mov(Operand(esp, (1 + FCA::kDataIndex) * kPointerSize), ebx); 451 if (!masm->isolate()->heap()->InNewSpace(*holder)) {
481 } else { 452 __ mov(holder_reg, holder);
482 __ mov(Operand(esp, (1 + FCA::kDataIndex) * kPointerSize), 453 } else {
483 Immediate(call_data)); 454 __ mov(holder_reg, map_to_holder);
455 __ mov(holder_reg, FieldOperand(holder_reg, Map::kPrototypeOffset));
456 }
457 }
458 break;
459 case CallOptimization::kHolderNotFound:
460 UNREACHABLE();
484 } 461 }
485 __ mov(Operand(esp, (1 + FCA::kIsolateIndex) * kPointerSize), 462 GenerateFastApiCallBody(masm,
486 Immediate(reinterpret_cast<int>(masm->isolate()))); 463 optimization,
487 __ mov(Operand(esp, (1 + FCA::kReturnValueOffset) * kPointerSize), 464 argc,
488 masm->isolate()->factory()->undefined_value()); 465 holder_reg,
489 __ mov(Operand(esp, (1 + FCA::kReturnValueDefaultValueIndex) * kPointerSize), 466 ebx,
490 masm->isolate()->factory()->undefined_value()); 467 ecx,
491 468 edx,
492 // Prepare arguments. 469 false);
493 STATIC_ASSERT(kFastApiCallArguments == 7);
494 __ lea(eax, Operand(esp, 1 * kPointerSize));
495
496 GenerateFastApiCallBody(masm, optimization, argc, false);
497 } 470 }
498 471
499 472
500 // Generate call to api function. 473 // Generate call to api function.
501 // This function uses push() to generate smaller, faster code than 474 // This function uses push() to generate smaller, faster code than
502 // the version above. It is an optimization that should will be removed 475 // the version above. It is an optimization that should will be removed
503 // when api call ICs are generated in hydrogen. 476 // when api call ICs are generated in hydrogen.
504 static void GenerateFastApiCall(MacroAssembler* masm, 477 static void GenerateFastApiCall(MacroAssembler* masm,
505 const CallOptimization& optimization, 478 const CallOptimization& optimization,
506 Register receiver, 479 Register receiver,
507 Register scratch1, 480 Register scratch1,
508 Register scratch2, 481 Register scratch2,
509 Register scratch3, 482 Register scratch3,
510 int argc, 483 int argc,
511 Register* values) { 484 Register* values) {
512 ASSERT(optimization.is_simple_api_call());
513
514 // Copy return value. 485 // Copy return value.
515 __ pop(scratch1); 486 __ pop(scratch1);
516
517 // receiver 487 // receiver
518 __ push(receiver); 488 __ push(receiver);
519
520 // Write the arguments to stack frame. 489 // Write the arguments to stack frame.
521 for (int i = 0; i < argc; i++) { 490 for (int i = 0; i < argc; i++) {
522 Register arg = values[argc-1-i]; 491 Register arg = values[argc-1-i];
523 ASSERT(!receiver.is(arg)); 492 ASSERT(!receiver.is(arg));
524 ASSERT(!scratch1.is(arg)); 493 ASSERT(!scratch1.is(arg));
525 ASSERT(!scratch2.is(arg)); 494 ASSERT(!scratch2.is(arg));
526 ASSERT(!scratch3.is(arg)); 495 ASSERT(!scratch3.is(arg));
527 __ push(arg); 496 __ push(arg);
528 } 497 }
498 __ push(scratch1);
499 // Stack now matches JSFunction abi.
500 GenerateFastApiCallBody(masm,
501 optimization,
502 argc,
503 receiver,
504 scratch1,
505 scratch2,
506 scratch3,
507 true);
508 }
509
510
511 static void GenerateFastApiCallBody(MacroAssembler* masm,
512 const CallOptimization& optimization,
513 int argc,
514 Register holder,
515 Register scratch1,
516 Register scratch2,
517 Register scratch3,
518 bool restore_context) {
519 // ----------- S t a t e -------------
520 // -- esp[0] : return address
521 // -- esp[4] : last argument
522 // -- ...
523 // -- esp[argc * 4] : first argument
524 // -- esp[(argc + 1) * 4] : receiver
525 ASSERT(optimization.is_simple_api_call());
529 526
530 typedef FunctionCallbackArguments FCA; 527 typedef FunctionCallbackArguments FCA;
531 528
532 STATIC_ASSERT(FCA::kHolderIndex == 0); 529 STATIC_ASSERT(FCA::kHolderIndex == 0);
533 STATIC_ASSERT(FCA::kIsolateIndex == 1); 530 STATIC_ASSERT(FCA::kIsolateIndex == 1);
534 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); 531 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
535 STATIC_ASSERT(FCA::kReturnValueOffset == 3); 532 STATIC_ASSERT(FCA::kReturnValueOffset == 3);
536 STATIC_ASSERT(FCA::kDataIndex == 4); 533 STATIC_ASSERT(FCA::kDataIndex == 4);
537 STATIC_ASSERT(FCA::kCalleeIndex == 5); 534 STATIC_ASSERT(FCA::kCalleeIndex == 5);
538 STATIC_ASSERT(FCA::kContextSaveIndex == 6); 535 STATIC_ASSERT(FCA::kContextSaveIndex == 6);
539 STATIC_ASSERT(FCA::kArgsLength == 7); 536 STATIC_ASSERT(FCA::kArgsLength == 7);
540 537
538 __ pop(scratch1);
539
540 ASSERT(!holder.is(esi));
541 // context save 541 // context save
542 __ push(esi); 542 __ push(esi);
543 543
544 // Get the function and setup the context. 544 // Get the function and setup the context.
545 Handle<JSFunction> function = optimization.constant_function(); 545 Handle<JSFunction> function = optimization.constant_function();
546 __ LoadHeapObject(scratch2, function); 546 __ LoadHeapObject(scratch2, function);
547 __ mov(esi, FieldOperand(scratch2, JSFunction::kContextOffset)); 547 __ mov(esi, FieldOperand(scratch2, JSFunction::kContextOffset));
548 // callee 548 // callee
549 __ push(scratch2); 549 __ push(scratch2);
550 550
551 Isolate* isolate = masm->isolate(); 551 Isolate* isolate = masm->isolate();
552 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 552 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
553 Handle<Object> call_data(api_call_info->data(), isolate); 553 Handle<Object> call_data(api_call_info->data(), isolate);
554 // Push data from ExecutableAccessorInfo. 554 // Push data from ExecutableAccessorInfo.
555 if (isolate->heap()->InNewSpace(*call_data)) { 555 if (isolate->heap()->InNewSpace(*call_data)) {
556 __ mov(scratch2, api_call_info); 556 __ mov(scratch2, api_call_info);
557 __ mov(scratch3, FieldOperand(scratch2, CallHandlerInfo::kDataOffset)); 557 __ mov(scratch3, FieldOperand(scratch2, CallHandlerInfo::kDataOffset));
558 __ push(scratch3); 558 __ push(scratch3);
559 } else { 559 } else {
560 __ push(Immediate(call_data)); 560 __ push(Immediate(call_data));
561 } 561 }
562 // return value 562 // return value
563 __ push(Immediate(isolate->factory()->undefined_value())); 563 __ push(Immediate(isolate->factory()->undefined_value()));
564 // return value default 564 // return value default
565 __ push(Immediate(isolate->factory()->undefined_value())); 565 __ push(Immediate(isolate->factory()->undefined_value()));
566 // isolate 566 // isolate
567 __ push(Immediate(reinterpret_cast<int>(isolate))); 567 __ push(Immediate(reinterpret_cast<int>(isolate)));
568 // holder 568 // holder
569 __ push(receiver); 569 __ push(holder);
570 570
571 // store receiver address for GenerateFastApiCallBody 571 // store receiver address for GenerateFastApiCallBody
572 ASSERT(!scratch1.is(eax)); 572 ASSERT(!scratch1.is(eax));
573 __ mov(eax, esp); 573 __ mov(eax, esp);
574 574
575 // return address 575 // return address
576 __ push(scratch1); 576 __ push(scratch1);
577 577
578 GenerateFastApiCallBody(masm, optimization, argc, true);
579 }
580
581
582 static void GenerateFastApiCallBody(MacroAssembler* masm,
583 const CallOptimization& optimization,
584 int argc,
585 bool restore_context) {
586 // ----------- S t a t e -------------
587 // -- esp[0] : return address
588 // -- esp[4] - esp[28] : FunctionCallbackInfo, incl.
589 // : object passing the type check
590 // (set by CheckPrototypes)
591 // -- esp[32] : last argument
592 // -- ...
593 // -- esp[(argc + 7) * 4] : first argument
594 // -- esp[(argc + 8) * 4] : receiver
595 //
596 // -- eax : receiver address
597 // -----------------------------------
598 typedef FunctionCallbackArguments FCA;
599
600 // API function gets reference to the v8::Arguments. If CPU profiler 578 // API function gets reference to the v8::Arguments. If CPU profiler
601 // is enabled wrapper function will be called and we need to pass 579 // is enabled wrapper function will be called and we need to pass
602 // address of the callback as additional parameter, always allocate 580 // address of the callback as additional parameter, always allocate
603 // space for it. 581 // space for it.
604 const int kApiArgc = 1 + 1; 582 const int kApiArgc = 1 + 1;
605 583
606 // Allocate the v8::Arguments structure in the arguments' space since 584 // Allocate the v8::Arguments structure in the arguments' space since
607 // it's not controlled by GC. 585 // it's not controlled by GC.
608 const int kApiStackSpace = 4; 586 const int kApiStackSpace = 4;
609 587
610 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
611
612 // Function address is a foreign pointer outside V8's heap. 588 // Function address is a foreign pointer outside V8's heap.
613 Address function_address = v8::ToCData<Address>(api_call_info->callback()); 589 Address function_address = v8::ToCData<Address>(api_call_info->callback());
614 __ PrepareCallApiFunction(kApiArgc + kApiStackSpace); 590 __ PrepareCallApiFunction(kApiArgc + kApiStackSpace);
615 591
616 // FunctionCallbackInfo::implicit_args_. 592 // FunctionCallbackInfo::implicit_args_.
617 __ mov(ApiParameterOperand(2), eax); 593 __ mov(ApiParameterOperand(2), eax);
618 __ add(eax, Immediate((argc + kFastApiCallArguments - 1) * kPointerSize)); 594 __ add(eax, Immediate((argc + kFastApiCallArguments - 1) * kPointerSize));
619 // FunctionCallbackInfo::values_. 595 // FunctionCallbackInfo::values_.
620 __ mov(ApiParameterOperand(3), eax); 596 __ mov(ApiParameterOperand(3), eax);
621 // FunctionCallbackInfo::length_. 597 // FunctionCallbackInfo::length_.
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
686 Register scratch2, 662 Register scratch2,
687 Register scratch3, 663 Register scratch3,
688 Handle<JSObject> interceptor_holder, 664 Handle<JSObject> interceptor_holder,
689 LookupResult* lookup, 665 LookupResult* lookup,
690 Handle<Name> name, 666 Handle<Name> name,
691 const CallOptimization& optimization, 667 const CallOptimization& optimization,
692 Label* miss_label) { 668 Label* miss_label) {
693 ASSERT(optimization.is_constant_call()); 669 ASSERT(optimization.is_constant_call());
694 ASSERT(!lookup->holder()->IsGlobalObject()); 670 ASSERT(!lookup->holder()->IsGlobalObject());
695 671
696 int depth1 = kInvalidProtoDepth;
697 int depth2 = kInvalidProtoDepth;
698 bool can_do_fast_api_call = false;
699 if (optimization.is_simple_api_call() &&
700 !lookup->holder()->IsGlobalObject()) {
701 depth1 = optimization.GetPrototypeDepthOfExpectedType(
702 object, interceptor_holder);
703 if (depth1 == kInvalidProtoDepth) {
704 depth2 = optimization.GetPrototypeDepthOfExpectedType(
705 interceptor_holder, Handle<JSObject>(lookup->holder()));
706 }
707 can_do_fast_api_call =
708 depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth;
709 }
710
711 Counters* counters = masm->isolate()->counters(); 672 Counters* counters = masm->isolate()->counters();
712 __ IncrementCounter(counters->call_const_interceptor(), 1); 673 __ IncrementCounter(counters->call_const_interceptor(), 1);
713 674
714 if (can_do_fast_api_call) {
715 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1);
716 ReserveSpaceForFastApiCall(masm, scratch1);
717 }
718
719 // Check that the maps from receiver to interceptor's holder 675 // Check that the maps from receiver to interceptor's holder
720 // haven't changed and thus we can invoke interceptor. 676 // haven't changed and thus we can invoke interceptor.
721 Label miss_cleanup;
722 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
723 Register holder = 677 Register holder =
724 stub_compiler_->CheckPrototypes( 678 stub_compiler_->CheckPrototypes(
725 IC::CurrentTypeOf(object, masm->isolate()), receiver, 679 IC::CurrentTypeOf(object, masm->isolate()), receiver,
726 interceptor_holder, scratch1, scratch2, scratch3, 680 interceptor_holder, scratch1, scratch2, scratch3,
727 name, depth1, miss); 681 name, miss_label);
728 682
729 // Invoke an interceptor and if it provides a value, 683 // Invoke an interceptor and if it provides a value,
730 // branch to |regular_invoke|. 684 // branch to |regular_invoke|.
731 Label regular_invoke; 685 Label regular_invoke;
732 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, 686 LoadWithInterceptor(masm, receiver, holder, interceptor_holder,
733 &regular_invoke); 687 &regular_invoke);
734 688
735 // Interceptor returned nothing for this property. Try to use cached 689 // Interceptor returned nothing for this property. Try to use cached
736 // constant function. 690 // constant function.
737 691
738 // Check that the maps from interceptor's holder to constant function's 692 // Check that the maps from interceptor's holder to constant function's
739 // holder haven't changed and thus we can use cached constant function. 693 // holder haven't changed and thus we can use cached constant function.
740 if (*interceptor_holder != lookup->holder()) { 694 if (*interceptor_holder != lookup->holder()) {
741 stub_compiler_->CheckPrototypes( 695 stub_compiler_->CheckPrototypes(
742 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder, 696 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder,
743 handle(lookup->holder()), scratch1, scratch2, scratch3, 697 handle(lookup->holder()), scratch1, scratch2, scratch3,
744 name, depth2, miss); 698 name, miss_label);
745 } else { 699 }
746 // CheckPrototypes has a side effect of fetching a 'holder' 700
747 // for API (object which is instanceof for the signature). It's 701 Handle<Map> lookup_map;
748 // safe to omit it here, as if present, it should be fetched 702 CallOptimization::HolderLookup holder_lookup =
749 // by the previous CheckPrototypes. 703 CallOptimization::kHolderNotFound;
750 ASSERT(depth2 == kInvalidProtoDepth); 704 if (optimization.is_simple_api_call() &&
705 !lookup->holder()->IsGlobalObject()) {
706 lookup_map = optimization.LookupHolderOfExpectedType(
707 object, object, interceptor_holder, &holder_lookup);
708 if (holder_lookup == CallOptimization::kHolderNotFound) {
709 lookup_map =
710 optimization.LookupHolderOfExpectedType(
711 object,
712 interceptor_holder,
713 Handle<JSObject>(lookup->holder()),
714 &holder_lookup);
715 }
751 } 716 }
752 717
753 // Invoke function. 718 // Invoke function.
754 if (can_do_fast_api_call) { 719 if (holder_lookup != CallOptimization::kHolderNotFound) {
755 GenerateFastApiCall(masm, optimization, arguments_.immediate()); 720 int argc = arguments_.immediate();
721 GenerateFastApiCall(masm,
722 optimization,
723 argc,
724 lookup_map,
725 holder_lookup);
756 } else { 726 } else {
757 Handle<JSFunction> fun = optimization.constant_function(); 727 Handle<JSFunction> fun = optimization.constant_function();
758 stub_compiler_->GenerateJumpFunction(object, fun); 728 stub_compiler_->GenerateJumpFunction(object, fun);
759 } 729 }
760 730
761 // Deferred code for fast API call case---clean preallocated space.
762 if (can_do_fast_api_call) {
763 __ bind(&miss_cleanup);
764 FreeSpaceForFastApiCall(masm, scratch1);
765 __ jmp(miss_label);
766 }
767
768 // Invoke a regular function. 731 // Invoke a regular function.
769 __ bind(&regular_invoke); 732 __ bind(&regular_invoke);
770 if (can_do_fast_api_call) {
771 FreeSpaceForFastApiCall(masm, scratch1);
772 }
773 } 733 }
774 734
775 void CompileRegular(MacroAssembler* masm, 735 void CompileRegular(MacroAssembler* masm,
776 Handle<JSObject> object, 736 Handle<JSObject> object,
777 Register receiver, 737 Register receiver,
778 Register scratch1, 738 Register scratch1,
779 Register scratch2, 739 Register scratch2,
780 Register scratch3, 740 Register scratch3,
781 Handle<Name> name, 741 Handle<Name> name,
782 Handle<JSObject> interceptor_holder, 742 Handle<JSObject> interceptor_holder,
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after
1176 1136
1177 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { 1137 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) {
1178 __ jmp(code, RelocInfo::CODE_TARGET); 1138 __ jmp(code, RelocInfo::CODE_TARGET);
1179 } 1139 }
1180 1140
1181 1141
1182 #undef __ 1142 #undef __
1183 #define __ ACCESS_MASM(masm()) 1143 #define __ ACCESS_MASM(masm())
1184 1144
1185 1145
1186 Register StubCompiler::CheckPrototypes(Handle<Type> type, 1146 Register StubCompiler::CheckPrototypes(Handle<HeapType> type,
1187 Register object_reg, 1147 Register object_reg,
1188 Handle<JSObject> holder, 1148 Handle<JSObject> holder,
1189 Register holder_reg, 1149 Register holder_reg,
1190 Register scratch1, 1150 Register scratch1,
1191 Register scratch2, 1151 Register scratch2,
1192 Handle<Name> name, 1152 Handle<Name> name,
1193 int save_at_depth,
1194 Label* miss, 1153 Label* miss,
1195 PrototypeCheckType check) { 1154 PrototypeCheckType check) {
1196 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); 1155 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate()));
1197 // Make sure that the type feedback oracle harvests the receiver map. 1156 // Make sure that the type feedback oracle harvests the receiver map.
1198 // TODO(svenpanne) Remove this hack when all ICs are reworked. 1157 // TODO(svenpanne) Remove this hack when all ICs are reworked.
1199 __ mov(scratch1, receiver_map); 1158 __ mov(scratch1, receiver_map);
1200 1159
1201 // Make sure there's no overlap between holder and object registers. 1160 // Make sure there's no overlap between holder and object registers.
1202 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 1161 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
1203 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) 1162 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
1204 && !scratch2.is(scratch1)); 1163 && !scratch2.is(scratch1));
1205 1164
1206 // Keep track of the current object in register reg. 1165 // Keep track of the current object in register reg.
1207 Register reg = object_reg; 1166 Register reg = object_reg;
1208 int depth = 0; 1167 int depth = 0;
1209 1168
1210 const int kHolderIndex = FunctionCallbackArguments::kHolderIndex + 1;
1211 if (save_at_depth == depth) {
1212 __ mov(Operand(esp, kHolderIndex * kPointerSize), reg);
1213 }
1214
1215 Handle<JSObject> current = Handle<JSObject>::null(); 1169 Handle<JSObject> current = Handle<JSObject>::null();
1216 if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant()); 1170 if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant());
1217 Handle<JSObject> prototype = Handle<JSObject>::null(); 1171 Handle<JSObject> prototype = Handle<JSObject>::null();
1218 Handle<Map> current_map = receiver_map; 1172 Handle<Map> current_map = receiver_map;
1219 Handle<Map> holder_map(holder->map()); 1173 Handle<Map> holder_map(holder->map());
1220 // Traverse the prototype chain and check the maps in the prototype chain for 1174 // Traverse the prototype chain and check the maps in the prototype chain for
1221 // fast and global objects or do negative lookup for normal objects. 1175 // fast and global objects or do negative lookup for normal objects.
1222 while (!current_map.is_identical_to(holder_map)) { 1176 while (!current_map.is_identical_to(holder_map)) {
1223 ++depth; 1177 ++depth;
1224 1178
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1272 if (in_new_space) { 1226 if (in_new_space) {
1273 // The prototype is in new space; we cannot store a reference to it 1227 // The prototype is in new space; we cannot store a reference to it
1274 // in the code. Load it from the map. 1228 // in the code. Load it from the map.
1275 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); 1229 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
1276 } else { 1230 } else {
1277 // The prototype is in old space; load it directly. 1231 // The prototype is in old space; load it directly.
1278 __ mov(reg, prototype); 1232 __ mov(reg, prototype);
1279 } 1233 }
1280 } 1234 }
1281 1235
1282 if (save_at_depth == depth) {
1283 __ mov(Operand(esp, kHolderIndex * kPointerSize), reg);
1284 }
1285
1286 // Go to the next object in the prototype chain. 1236 // Go to the next object in the prototype chain.
1287 current = prototype; 1237 current = prototype;
1288 current_map = handle(current->map()); 1238 current_map = handle(current->map());
1289 } 1239 }
1290 1240
1291 // Log the check depth. 1241 // Log the check depth.
1292 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); 1242 LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
1293 1243
1294 if (depth != 0 || check == CHECK_ALL_MAPS) { 1244 if (depth != 0 || check == CHECK_ALL_MAPS) {
1295 // Check the holder map. 1245 // Check the holder map.
(...skipping 28 matching lines...) Expand all
1324 Label success; 1274 Label success;
1325 __ jmp(&success); 1275 __ jmp(&success);
1326 GenerateRestoreName(masm(), miss, name); 1276 GenerateRestoreName(masm(), miss, name);
1327 TailCallBuiltin(masm(), MissBuiltin(kind())); 1277 TailCallBuiltin(masm(), MissBuiltin(kind()));
1328 __ bind(&success); 1278 __ bind(&success);
1329 } 1279 }
1330 } 1280 }
1331 1281
1332 1282
1333 Register LoadStubCompiler::CallbackHandlerFrontend( 1283 Register LoadStubCompiler::CallbackHandlerFrontend(
1334 Handle<Type> type, 1284 Handle<HeapType> type,
1335 Register object_reg, 1285 Register object_reg,
1336 Handle<JSObject> holder, 1286 Handle<JSObject> holder,
1337 Handle<Name> name, 1287 Handle<Name> name,
1338 Handle<Object> callback) { 1288 Handle<Object> callback) {
1339 Label miss; 1289 Label miss;
1340 1290
1341 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss); 1291 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss);
1342 1292
1343 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { 1293 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) {
1344 ASSERT(!reg.is(scratch2())); 1294 ASSERT(!reg.is(scratch2()));
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
1659 index.translate(holder), Representation::Tagged()); 1609 index.translate(holder), Representation::Tagged());
1660 GenerateJumpFunction(object, edi, &miss); 1610 GenerateJumpFunction(object, edi, &miss);
1661 1611
1662 HandlerFrontendFooter(&miss); 1612 HandlerFrontendFooter(&miss);
1663 1613
1664 // Return the generated code. 1614 // Return the generated code.
1665 return GetCode(Code::FAST, name); 1615 return GetCode(Code::FAST, name);
1666 } 1616 }
1667 1617
1668 1618
1669 Handle<Code> CallStubCompiler::CompileArrayCodeCall(
1670 Handle<Object> object,
1671 Handle<JSObject> holder,
1672 Handle<Cell> cell,
1673 Handle<JSFunction> function,
1674 Handle<String> name,
1675 Code::StubType type) {
1676 Label miss;
1677
1678 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
1679 if (!cell.is_null()) {
1680 ASSERT(cell->value() == *function);
1681 GenerateLoadFunctionFromCell(cell, function, &miss);
1682 }
1683
1684 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite();
1685 site->SetElementsKind(GetInitialFastElementsKind());
1686 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site);
1687 const int argc = arguments().immediate();
1688 __ mov(eax, Immediate(argc));
1689 __ mov(ebx, site_feedback_cell);
1690 __ mov(edi, function);
1691
1692 ArrayConstructorStub stub(isolate());
1693 __ TailCallStub(&stub);
1694
1695 HandlerFrontendFooter(&miss);
1696
1697 // Return the generated code.
1698 return GetCode(type, name);
1699 }
1700
1701
1702 Handle<Code> CallStubCompiler::CompileArrayPushCall(
1703 Handle<Object> object,
1704 Handle<JSObject> holder,
1705 Handle<Cell> cell,
1706 Handle<JSFunction> function,
1707 Handle<String> name,
1708 Code::StubType type) {
1709 // If object is not an array or is observed or sealed, bail out to regular
1710 // call.
1711 if (!object->IsJSArray() ||
1712 !cell.is_null() ||
1713 Handle<JSArray>::cast(object)->map()->is_observed() ||
1714 !Handle<JSArray>::cast(object)->map()->is_extensible()) {
1715 return Handle<Code>::null();
1716 }
1717
1718 Label miss;
1719
1720 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
1721
1722 const int argc = arguments().immediate();
1723 if (argc == 0) {
1724 // Noop, return the length.
1725 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
1726 __ ret((argc + 1) * kPointerSize);
1727 } else {
1728 Label call_builtin;
1729
1730 if (argc == 1) { // Otherwise fall through to call builtin.
1731 Label attempt_to_grow_elements, with_write_barrier, check_double;
1732
1733 // Get the elements array of the object.
1734 __ mov(edi, FieldOperand(edx, JSArray::kElementsOffset));
1735
1736 // Check that the elements are in fast mode and writable.
1737 __ cmp(FieldOperand(edi, HeapObject::kMapOffset),
1738 Immediate(factory()->fixed_array_map()));
1739 __ j(not_equal, &check_double);
1740
1741 // Get the array's length into eax and calculate new length.
1742 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
1743 STATIC_ASSERT(kSmiTagSize == 1);
1744 STATIC_ASSERT(kSmiTag == 0);
1745 __ add(eax, Immediate(Smi::FromInt(argc)));
1746
1747 // Get the elements' length into ecx.
1748 __ mov(ecx, FieldOperand(edi, FixedArray::kLengthOffset));
1749
1750 // Check if we could survive without allocation.
1751 __ cmp(eax, ecx);
1752 __ j(greater, &attempt_to_grow_elements);
1753
1754 // Check if value is a smi.
1755 __ mov(ecx, Operand(esp, argc * kPointerSize));
1756 __ JumpIfNotSmi(ecx, &with_write_barrier);
1757
1758 // Save new length.
1759 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
1760
1761 // Store the value.
1762 __ mov(FieldOperand(edi,
1763 eax,
1764 times_half_pointer_size,
1765 FixedArray::kHeaderSize - argc * kPointerSize),
1766 ecx);
1767
1768 __ ret((argc + 1) * kPointerSize);
1769
1770 __ bind(&check_double);
1771
1772
1773 // Check that the elements are in double mode.
1774 __ cmp(FieldOperand(edi, HeapObject::kMapOffset),
1775 Immediate(factory()->fixed_double_array_map()));
1776 __ j(not_equal, &call_builtin);
1777
1778 // Get the array's length into eax and calculate new length.
1779 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
1780 STATIC_ASSERT(kSmiTagSize == 1);
1781 STATIC_ASSERT(kSmiTag == 0);
1782 __ add(eax, Immediate(Smi::FromInt(argc)));
1783
1784 // Get the elements' length into ecx.
1785 __ mov(ecx, FieldOperand(edi, FixedArray::kLengthOffset));
1786
1787 // Check if we could survive without allocation.
1788 __ cmp(eax, ecx);
1789 __ j(greater, &call_builtin);
1790
1791 __ mov(ecx, Operand(esp, argc * kPointerSize));
1792 __ StoreNumberToDoubleElements(
1793 ecx, edi, eax, ecx, xmm0, &call_builtin, true, argc * kDoubleSize);
1794
1795 // Save new length.
1796 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
1797 __ ret((argc + 1) * kPointerSize);
1798
1799 __ bind(&with_write_barrier);
1800
1801 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
1802
1803 if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) {
1804 Label fast_object, not_fast_object;
1805 __ CheckFastObjectElements(ebx, &not_fast_object, Label::kNear);
1806 __ jmp(&fast_object);
1807 // In case of fast smi-only, convert to fast object, otherwise bail out.
1808 __ bind(&not_fast_object);
1809 __ CheckFastSmiElements(ebx, &call_builtin);
1810 __ cmp(FieldOperand(ecx, HeapObject::kMapOffset),
1811 Immediate(factory()->heap_number_map()));
1812 __ j(equal, &call_builtin);
1813 // edi: elements array
1814 // edx: receiver
1815 // ebx: map
1816 Label try_holey_map;
1817 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
1818 FAST_ELEMENTS,
1819 ebx,
1820 edi,
1821 &try_holey_map);
1822
1823 ElementsTransitionGenerator::
1824 GenerateMapChangeElementsTransition(masm(),
1825 DONT_TRACK_ALLOCATION_SITE,
1826 NULL);
1827 // Restore edi.
1828 __ mov(edi, FieldOperand(edx, JSArray::kElementsOffset));
1829 __ jmp(&fast_object);
1830
1831 __ bind(&try_holey_map);
1832 __ LoadTransitionedArrayMapConditional(FAST_HOLEY_SMI_ELEMENTS,
1833 FAST_HOLEY_ELEMENTS,
1834 ebx,
1835 edi,
1836 &call_builtin);
1837 ElementsTransitionGenerator::
1838 GenerateMapChangeElementsTransition(masm(),
1839 DONT_TRACK_ALLOCATION_SITE,
1840 NULL);
1841 // Restore edi.
1842 __ mov(edi, FieldOperand(edx, JSArray::kElementsOffset));
1843 __ bind(&fast_object);
1844 } else {
1845 __ CheckFastObjectElements(ebx, &call_builtin);
1846 }
1847
1848 // Save new length.
1849 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
1850
1851 // Store the value.
1852 __ lea(edx, FieldOperand(edi,
1853 eax, times_half_pointer_size,
1854 FixedArray::kHeaderSize - argc * kPointerSize));
1855 __ mov(Operand(edx, 0), ecx);
1856
1857 __ RecordWrite(edi, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
1858 OMIT_SMI_CHECK);
1859
1860 __ ret((argc + 1) * kPointerSize);
1861
1862 __ bind(&attempt_to_grow_elements);
1863 if (!FLAG_inline_new) {
1864 __ jmp(&call_builtin);
1865 }
1866
1867 __ mov(ebx, Operand(esp, argc * kPointerSize));
1868 // Growing elements that are SMI-only requires special handling in case
1869 // the new element is non-Smi. For now, delegate to the builtin.
1870 Label no_fast_elements_check;
1871 __ JumpIfSmi(ebx, &no_fast_elements_check);
1872 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
1873 __ CheckFastObjectElements(ecx, &call_builtin, Label::kFar);
1874 __ bind(&no_fast_elements_check);
1875
1876 // We could be lucky and the elements array could be at the top of
1877 // new-space. In this case we can just grow it in place by moving the
1878 // allocation pointer up.
1879
1880 ExternalReference new_space_allocation_top =
1881 ExternalReference::new_space_allocation_top_address(isolate());
1882 ExternalReference new_space_allocation_limit =
1883 ExternalReference::new_space_allocation_limit_address(isolate());
1884
1885 const int kAllocationDelta = 4;
1886 // Load top.
1887 __ mov(ecx, Operand::StaticVariable(new_space_allocation_top));
1888
1889 // Check if it's the end of elements.
1890 __ lea(edx, FieldOperand(edi,
1891 eax, times_half_pointer_size,
1892 FixedArray::kHeaderSize - argc * kPointerSize));
1893 __ cmp(edx, ecx);
1894 __ j(not_equal, &call_builtin);
1895 __ add(ecx, Immediate(kAllocationDelta * kPointerSize));
1896 __ cmp(ecx, Operand::StaticVariable(new_space_allocation_limit));
1897 __ j(above, &call_builtin);
1898
1899 // We fit and could grow elements.
1900 __ mov(Operand::StaticVariable(new_space_allocation_top), ecx);
1901
1902 // Push the argument...
1903 __ mov(Operand(edx, 0), ebx);
1904 // ... and fill the rest with holes.
1905 for (int i = 1; i < kAllocationDelta; i++) {
1906 __ mov(Operand(edx, i * kPointerSize),
1907 Immediate(factory()->the_hole_value()));
1908 }
1909
1910 // We know the elements array is in new space so we don't need the
1911 // remembered set, but we just pushed a value onto it so we may have to
1912 // tell the incremental marker to rescan the object that we just grew. We
1913 // don't need to worry about the holes because they are in old space and
1914 // already marked black.
1915 __ RecordWrite(edi, edx, ebx, kDontSaveFPRegs, OMIT_REMEMBERED_SET);
1916
1917 // Restore receiver to edx as finish sequence assumes it's here.
1918 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1919
1920 // Increment element's and array's sizes.
1921 __ add(FieldOperand(edi, FixedArray::kLengthOffset),
1922 Immediate(Smi::FromInt(kAllocationDelta)));
1923
1924 // NOTE: This only happen in new-space, where we don't
1925 // care about the black-byte-count on pages. Otherwise we should
1926 // update that too if the object is black.
1927
1928 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
1929
1930 __ ret((argc + 1) * kPointerSize);
1931 }
1932
1933 __ bind(&call_builtin);
1934 __ TailCallExternalReference(
1935 ExternalReference(Builtins::c_ArrayPush, isolate()),
1936 argc + 1,
1937 1);
1938 }
1939
1940 HandlerFrontendFooter(&miss);
1941
1942 // Return the generated code.
1943 return GetCode(type, name);
1944 }
1945
1946
1947 Handle<Code> CallStubCompiler::CompileArrayPopCall(
1948 Handle<Object> object,
1949 Handle<JSObject> holder,
1950 Handle<Cell> cell,
1951 Handle<JSFunction> function,
1952 Handle<String> name,
1953 Code::StubType type) {
1954 // If object is not an array or is observed or sealed, bail out to regular
1955 // call.
1956 if (!object->IsJSArray() ||
1957 !cell.is_null() ||
1958 Handle<JSArray>::cast(object)->map()->is_observed() ||
1959 !Handle<JSArray>::cast(object)->map()->is_extensible()) {
1960 return Handle<Code>::null();
1961 }
1962
1963 Label miss, return_undefined, call_builtin;
1964
1965 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
1966
1967 // Get the elements array of the object.
1968 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset));
1969
1970 // Check that the elements are in fast mode and writable.
1971 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
1972 Immediate(factory()->fixed_array_map()));
1973 __ j(not_equal, &call_builtin);
1974
1975 // Get the array's length into ecx and calculate new length.
1976 __ mov(ecx, FieldOperand(edx, JSArray::kLengthOffset));
1977 __ sub(ecx, Immediate(Smi::FromInt(1)));
1978 __ j(negative, &return_undefined);
1979
1980 // Get the last element.
1981 STATIC_ASSERT(kSmiTagSize == 1);
1982 STATIC_ASSERT(kSmiTag == 0);
1983 __ mov(eax, FieldOperand(ebx,
1984 ecx, times_half_pointer_size,
1985 FixedArray::kHeaderSize));
1986 __ cmp(eax, Immediate(factory()->the_hole_value()));
1987 __ j(equal, &call_builtin);
1988
1989 // Set the array's length.
1990 __ mov(FieldOperand(edx, JSArray::kLengthOffset), ecx);
1991
1992 // Fill with the hole.
1993 __ mov(FieldOperand(ebx,
1994 ecx, times_half_pointer_size,
1995 FixedArray::kHeaderSize),
1996 Immediate(factory()->the_hole_value()));
1997 const int argc = arguments().immediate();
1998 __ ret((argc + 1) * kPointerSize);
1999
2000 __ bind(&return_undefined);
2001 __ mov(eax, Immediate(factory()->undefined_value()));
2002 __ ret((argc + 1) * kPointerSize);
2003
2004 __ bind(&call_builtin);
2005 __ TailCallExternalReference(
2006 ExternalReference(Builtins::c_ArrayPop, isolate()),
2007 argc + 1,
2008 1);
2009
2010 HandlerFrontendFooter(&miss);
2011
2012 // Return the generated code.
2013 return GetCode(type, name);
2014 }
2015
2016
2017 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
2018 Handle<Object> object,
2019 Handle<JSObject> holder,
2020 Handle<Cell> cell,
2021 Handle<JSFunction> function,
2022 Handle<String> name,
2023 Code::StubType type) {
2024 // If object is not a string, bail out to regular call.
2025 if (!object->IsString() || !cell.is_null()) {
2026 return Handle<Code>::null();
2027 }
2028
2029 const int argc = arguments().immediate();
2030
2031 Label miss;
2032 Label name_miss;
2033 Label index_out_of_range;
2034 Label* index_out_of_range_label = &index_out_of_range;
2035
2036 if (kind_ == Code::CALL_IC &&
2037 (CallICBase::StringStubState::decode(extra_state()) ==
2038 DEFAULT_STRING_STUB)) {
2039 index_out_of_range_label = &miss;
2040 }
2041
2042 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
2043
2044 Register receiver = ebx;
2045 Register index = edi;
2046 Register result = eax;
2047 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize));
2048 if (argc > 0) {
2049 __ mov(index, Operand(esp, (argc - 0) * kPointerSize));
2050 } else {
2051 __ Set(index, Immediate(factory()->undefined_value()));
2052 }
2053
2054 StringCharCodeAtGenerator generator(receiver,
2055 index,
2056 result,
2057 &miss, // When not a string.
2058 &miss, // When not a number.
2059 index_out_of_range_label,
2060 STRING_INDEX_IS_NUMBER);
2061 generator.GenerateFast(masm());
2062 __ ret((argc + 1) * kPointerSize);
2063
2064 StubRuntimeCallHelper call_helper;
2065 generator.GenerateSlow(masm(), call_helper);
2066
2067 if (index_out_of_range.is_linked()) {
2068 __ bind(&index_out_of_range);
2069 __ Set(eax, Immediate(factory()->nan_value()));
2070 __ ret((argc + 1) * kPointerSize);
2071 }
2072
2073 __ bind(&miss);
2074 // Restore function name in ecx.
2075 __ Set(ecx, Immediate(name));
2076 HandlerFrontendFooter(&name_miss);
2077
2078 // Return the generated code.
2079 return GetCode(type, name);
2080 }
2081
2082
2083 Handle<Code> CallStubCompiler::CompileStringCharAtCall(
2084 Handle<Object> object,
2085 Handle<JSObject> holder,
2086 Handle<Cell> cell,
2087 Handle<JSFunction> function,
2088 Handle<String> name,
2089 Code::StubType type) {
2090 // If object is not a string, bail out to regular call.
2091 if (!object->IsString() || !cell.is_null()) {
2092 return Handle<Code>::null();
2093 }
2094
2095 const int argc = arguments().immediate();
2096
2097 Label miss;
2098 Label name_miss;
2099 Label index_out_of_range;
2100 Label* index_out_of_range_label = &index_out_of_range;
2101
2102 if (kind_ == Code::CALL_IC &&
2103 (CallICBase::StringStubState::decode(extra_state()) ==
2104 DEFAULT_STRING_STUB)) {
2105 index_out_of_range_label = &miss;
2106 }
2107
2108 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
2109
2110 Register receiver = eax;
2111 Register index = edi;
2112 Register scratch = edx;
2113 Register result = eax;
2114 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize));
2115 if (argc > 0) {
2116 __ mov(index, Operand(esp, (argc - 0) * kPointerSize));
2117 } else {
2118 __ Set(index, Immediate(factory()->undefined_value()));
2119 }
2120
2121 StringCharAtGenerator generator(receiver,
2122 index,
2123 scratch,
2124 result,
2125 &miss, // When not a string.
2126 &miss, // When not a number.
2127 index_out_of_range_label,
2128 STRING_INDEX_IS_NUMBER);
2129 generator.GenerateFast(masm());
2130 __ ret((argc + 1) * kPointerSize);
2131
2132 StubRuntimeCallHelper call_helper;
2133 generator.GenerateSlow(masm(), call_helper);
2134
2135 if (index_out_of_range.is_linked()) {
2136 __ bind(&index_out_of_range);
2137 __ Set(eax, Immediate(factory()->empty_string()));
2138 __ ret((argc + 1) * kPointerSize);
2139 }
2140
2141 __ bind(&miss);
2142 // Restore function name in ecx.
2143 __ Set(ecx, Immediate(name));
2144 HandlerFrontendFooter(&name_miss);
2145
2146 // Return the generated code.
2147 return GetCode(type, name);
2148 }
2149
2150
2151 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
2152 Handle<Object> object,
2153 Handle<JSObject> holder,
2154 Handle<Cell> cell,
2155 Handle<JSFunction> function,
2156 Handle<String> name,
2157 Code::StubType type) {
2158 const int argc = arguments().immediate();
2159
2160 // If the object is not a JSObject or we got an unexpected number of
2161 // arguments, bail out to the regular call.
2162 if (!object->IsJSObject() || argc != 1) {
2163 return Handle<Code>::null();
2164 }
2165
2166 Label miss;
2167
2168 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
2169 if (!cell.is_null()) {
2170 ASSERT(cell->value() == *function);
2171 GenerateLoadFunctionFromCell(cell, function, &miss);
2172 }
2173
2174 // Load the char code argument.
2175 Register code = ebx;
2176 __ mov(code, Operand(esp, 1 * kPointerSize));
2177
2178 // Check the code is a smi.
2179 Label slow;
2180 STATIC_ASSERT(kSmiTag == 0);
2181 __ JumpIfNotSmi(code, &slow);
2182
2183 // Convert the smi code to uint16.
2184 __ and_(code, Immediate(Smi::FromInt(0xffff)));
2185
2186 StringCharFromCodeGenerator generator(code, eax);
2187 generator.GenerateFast(masm());
2188 __ ret(2 * kPointerSize);
2189
2190 StubRuntimeCallHelper call_helper;
2191 generator.GenerateSlow(masm(), call_helper);
2192
2193 __ bind(&slow);
2194 // We do not have to patch the receiver because the function makes no use of
2195 // it.
2196 GenerateJumpFunctionIgnoreReceiver(function);
2197
2198 HandlerFrontendFooter(&miss);
2199
2200 // Return the generated code.
2201 return GetCode(type, name);
2202 }
2203
2204
2205 Handle<Code> CallStubCompiler::CompileMathFloorCall(
2206 Handle<Object> object,
2207 Handle<JSObject> holder,
2208 Handle<Cell> cell,
2209 Handle<JSFunction> function,
2210 Handle<String> name,
2211 Code::StubType type) {
2212 if (!CpuFeatures::IsSupported(SSE2)) {
2213 return Handle<Code>::null();
2214 }
2215
2216 CpuFeatureScope use_sse2(masm(), SSE2);
2217
2218 const int argc = arguments().immediate();
2219
2220 // If the object is not a JSObject or we got an unexpected number of
2221 // arguments, bail out to the regular call.
2222 if (!object->IsJSObject() || argc != 1) {
2223 return Handle<Code>::null();
2224 }
2225
2226 Label miss;
2227
2228 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
2229 if (!cell.is_null()) {
2230 ASSERT(cell->value() == *function);
2231 GenerateLoadFunctionFromCell(cell, function, &miss);
2232 }
2233
2234 // Load the (only) argument into eax.
2235 __ mov(eax, Operand(esp, 1 * kPointerSize));
2236
2237 // Check if the argument is a smi.
2238 Label smi;
2239 STATIC_ASSERT(kSmiTag == 0);
2240 __ JumpIfSmi(eax, &smi);
2241
2242 // Check if the argument is a heap number and load its value into xmm0.
2243 Label slow;
2244 __ CheckMap(eax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK);
2245 __ movsd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset));
2246
2247 // Check if the argument is strictly positive. Note this also
2248 // discards NaN.
2249 __ xorpd(xmm1, xmm1);
2250 __ ucomisd(xmm0, xmm1);
2251 __ j(below_equal, &slow);
2252
2253 // Do a truncating conversion.
2254 __ cvttsd2si(eax, Operand(xmm0));
2255
2256 // Check if the result fits into a smi. Note this also checks for
2257 // 0x80000000 which signals a failed conversion.
2258 Label wont_fit_into_smi;
2259 __ test(eax, Immediate(0xc0000000));
2260 __ j(not_zero, &wont_fit_into_smi);
2261
2262 // Smi tag and return.
2263 __ SmiTag(eax);
2264 __ bind(&smi);
2265 __ ret(2 * kPointerSize);
2266
2267 // Check if the argument is < 2^kMantissaBits.
2268 Label already_round;
2269 __ bind(&wont_fit_into_smi);
2270 __ LoadPowerOf2(xmm1, ebx, HeapNumber::kMantissaBits);
2271 __ ucomisd(xmm0, xmm1);
2272 __ j(above_equal, &already_round);
2273
2274 // Save a copy of the argument.
2275 __ movaps(xmm2, xmm0);
2276
2277 // Compute (argument + 2^kMantissaBits) - 2^kMantissaBits.
2278 __ addsd(xmm0, xmm1);
2279 __ subsd(xmm0, xmm1);
2280
2281 // Compare the argument and the tentative result to get the right mask:
2282 // if xmm2 < xmm0:
2283 // xmm2 = 1...1
2284 // else:
2285 // xmm2 = 0...0
2286 __ cmpltsd(xmm2, xmm0);
2287
2288 // Subtract 1 if the argument was less than the tentative result.
2289 __ LoadPowerOf2(xmm1, ebx, 0);
2290 __ andpd(xmm1, xmm2);
2291 __ subsd(xmm0, xmm1);
2292
2293 // Return a new heap number.
2294 __ AllocateHeapNumber(eax, ebx, edx, &slow);
2295 __ movsd(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
2296 __ ret(2 * kPointerSize);
2297
2298 // Return the argument (when it's an already round heap number).
2299 __ bind(&already_round);
2300 __ mov(eax, Operand(esp, 1 * kPointerSize));
2301 __ ret(2 * kPointerSize);
2302
2303 __ bind(&slow);
2304 // We do not have to patch the receiver because the function makes no use of
2305 // it.
2306 GenerateJumpFunctionIgnoreReceiver(function);
2307
2308 HandlerFrontendFooter(&miss);
2309
2310 // Return the generated code.
2311 return GetCode(type, name);
2312 }
2313
2314
2315 Handle<Code> CallStubCompiler::CompileMathAbsCall(
2316 Handle<Object> object,
2317 Handle<JSObject> holder,
2318 Handle<Cell> cell,
2319 Handle<JSFunction> function,
2320 Handle<String> name,
2321 Code::StubType type) {
2322 const int argc = arguments().immediate();
2323
2324 // If the object is not a JSObject or we got an unexpected number of
2325 // arguments, bail out to the regular call.
2326 if (!object->IsJSObject() || argc != 1) {
2327 return Handle<Code>::null();
2328 }
2329
2330 Label miss;
2331
2332 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
2333 if (!cell.is_null()) {
2334 ASSERT(cell->value() == *function);
2335 GenerateLoadFunctionFromCell(cell, function, &miss);
2336 }
2337
2338 // Load the (only) argument into eax.
2339 __ mov(eax, Operand(esp, 1 * kPointerSize));
2340
2341 // Check if the argument is a smi.
2342 Label not_smi;
2343 STATIC_ASSERT(kSmiTag == 0);
2344 __ JumpIfNotSmi(eax, &not_smi);
2345
2346 // Branchless abs implementation, refer to below:
2347 // http://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs
2348 // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0
2349 // otherwise.
2350 __ mov(ebx, eax);
2351 __ sar(ebx, kBitsPerInt - 1);
2352
2353 // Do bitwise not or do nothing depending on ebx.
2354 __ xor_(eax, ebx);
2355
2356 // Add 1 or do nothing depending on ebx.
2357 __ sub(eax, ebx);
2358
2359 // If the result is still negative, go to the slow case.
2360 // This only happens for the most negative smi.
2361 Label slow;
2362 __ j(negative, &slow);
2363
2364 // Smi case done.
2365 __ ret(2 * kPointerSize);
2366
2367 // Check if the argument is a heap number and load its exponent and
2368 // sign into ebx.
2369 __ bind(&not_smi);
2370 __ CheckMap(eax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK);
2371 __ mov(ebx, FieldOperand(eax, HeapNumber::kExponentOffset));
2372
2373 // Check the sign of the argument. If the argument is positive,
2374 // just return it.
2375 Label negative_sign;
2376 __ test(ebx, Immediate(HeapNumber::kSignMask));
2377 __ j(not_zero, &negative_sign);
2378 __ ret(2 * kPointerSize);
2379
2380 // If the argument is negative, clear the sign, and return a new
2381 // number.
2382 __ bind(&negative_sign);
2383 __ and_(ebx, ~HeapNumber::kSignMask);
2384 __ mov(ecx, FieldOperand(eax, HeapNumber::kMantissaOffset));
2385 __ AllocateHeapNumber(eax, edi, edx, &slow);
2386 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ebx);
2387 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx);
2388 __ ret(2 * kPointerSize);
2389
2390 __ bind(&slow);
2391 // We do not have to patch the receiver because the function makes no use of
2392 // it.
2393 GenerateJumpFunctionIgnoreReceiver(function);
2394
2395 HandlerFrontendFooter(&miss);
2396
2397 // Return the generated code.
2398 return GetCode(type, name);
2399 }
2400
2401
2402 Handle<Code> CallStubCompiler::CompileFastApiCall( 1619 Handle<Code> CallStubCompiler::CompileFastApiCall(
2403 const CallOptimization& optimization, 1620 const CallOptimization& optimization,
2404 Handle<Object> object, 1621 Handle<Object> object,
2405 Handle<JSObject> holder, 1622 Handle<JSObject> holder,
2406 Handle<Cell> cell, 1623 Handle<Cell> cell,
2407 Handle<JSFunction> function, 1624 Handle<JSFunction> function,
2408 Handle<String> name) { 1625 Handle<String> name) {
2409 ASSERT(optimization.is_simple_api_call()); 1626 ASSERT(optimization.is_simple_api_call());
2410 // Bail out if object is a global object as we don't want to 1627 // Bail out if object is a global object as we don't want to
2411 // repatch it to global receiver. 1628 // repatch it to global receiver.
2412 if (object->IsGlobalObject()) return Handle<Code>::null(); 1629 if (object->IsGlobalObject()) return Handle<Code>::null();
2413 if (!cell.is_null()) return Handle<Code>::null(); 1630 if (!cell.is_null()) return Handle<Code>::null();
2414 if (!object->IsJSObject()) return Handle<Code>::null(); 1631 if (!object->IsJSObject()) return Handle<Code>::null();
2415 int depth = optimization.GetPrototypeDepthOfExpectedType( 1632 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
2416 Handle<JSObject>::cast(object), holder); 1633 CallOptimization::HolderLookup holder_lookup =
2417 if (depth == kInvalidProtoDepth) return Handle<Code>::null(); 1634 CallOptimization::kHolderNotFound;
1635 Handle<Map> lookup_map = optimization.LookupHolderOfExpectedType(
1636 receiver, receiver, holder, &holder_lookup);
1637 if (holder_lookup == CallOptimization::kHolderNotFound) {
1638 return Handle<Code>::null();
1639 }
2418 1640
2419 Label miss, miss_before_stack_reserved; 1641 Label miss;
2420 1642 GenerateNameCheck(name, &miss);
2421 GenerateNameCheck(name, &miss_before_stack_reserved);
2422 1643
2423 // Get the receiver from the stack. 1644 // Get the receiver from the stack.
2424 const int argc = arguments().immediate(); 1645 const int argc = arguments().immediate();
2425 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1646 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
2426 1647
2427 // Check that the receiver isn't a smi. 1648 // Check that the receiver isn't a smi.
2428 __ JumpIfSmi(edx, &miss_before_stack_reserved); 1649 __ JumpIfSmi(edx, &miss);
2429 1650
2430 Counters* counters = isolate()->counters(); 1651 Counters* counters = isolate()->counters();
2431 __ IncrementCounter(counters->call_const(), 1); 1652 __ IncrementCounter(counters->call_const(), 1);
2432 __ IncrementCounter(counters->call_const_fast_api(), 1);
2433
2434 // Allocate space for v8::Arguments implicit values. Must be initialized
2435 // before calling any runtime function.
2436 __ sub(esp, Immediate(kFastApiCallArguments * kPointerSize));
2437 1653
2438 // Check that the maps haven't changed and find a Holder as a side effect. 1654 // Check that the maps haven't changed and find a Holder as a side effect.
2439 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, 1655 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder,
2440 ebx, eax, edi, name, depth, &miss); 1656 ebx, eax, edi, name, &miss);
2441 1657
2442 // Move the return address on top of the stack. 1658 GenerateFastApiCall(masm(), optimization, argc, lookup_map, holder_lookup);
2443 __ mov(eax, Operand(esp, kFastApiCallArguments * kPointerSize));
2444 __ mov(Operand(esp, 0 * kPointerSize), eax);
2445 1659
2446 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains 1660 HandlerFrontendFooter(&miss);
2447 // duplicate of return address and will be overwritten.
2448 GenerateFastApiCall(masm(), optimization, argc);
2449
2450 __ bind(&miss);
2451 __ add(esp, Immediate(kFastApiCallArguments * kPointerSize));
2452
2453 HandlerFrontendFooter(&miss_before_stack_reserved);
2454 1661
2455 // Return the generated code. 1662 // Return the generated code.
2456 return GetCode(function); 1663 return GetCode(function);
2457 } 1664 }
2458 1665
2459 1666
2460 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { 1667 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
2461 Label success; 1668 Label success;
2462 // Check that the object is a boolean. 1669 // Check that the object is a boolean.
2463 __ cmp(object, factory()->true_value()); 1670 __ cmp(object, factory()->true_value());
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
2631 // Return the generated code. 1838 // Return the generated code.
2632 return GetCode(Code::NORMAL, name); 1839 return GetCode(Code::NORMAL, name);
2633 } 1840 }
2634 1841
2635 1842
2636 Handle<Code> StoreStubCompiler::CompileStoreCallback( 1843 Handle<Code> StoreStubCompiler::CompileStoreCallback(
2637 Handle<JSObject> object, 1844 Handle<JSObject> object,
2638 Handle<JSObject> holder, 1845 Handle<JSObject> holder,
2639 Handle<Name> name, 1846 Handle<Name> name,
2640 Handle<ExecutableAccessorInfo> callback) { 1847 Handle<ExecutableAccessorInfo> callback) {
2641 HandlerFrontend(IC::CurrentTypeOf(object, isolate()), 1848 Register holder_reg = HandlerFrontend(
2642 receiver(), holder, name); 1849 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name);
2643 1850
2644 __ pop(scratch1()); // remove the return address 1851 __ pop(scratch1()); // remove the return address
2645 __ push(receiver()); 1852 __ push(receiver());
1853 __ push(holder_reg);
2646 __ Push(callback); 1854 __ Push(callback);
2647 __ Push(name); 1855 __ Push(name);
2648 __ push(value()); 1856 __ push(value());
2649 __ push(scratch1()); // restore return address 1857 __ push(scratch1()); // restore return address
2650 1858
2651 // Do tail-call to the runtime system. 1859 // Do tail-call to the runtime system.
2652 ExternalReference store_callback_property = 1860 ExternalReference store_callback_property =
2653 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); 1861 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate());
2654 __ TailCallExternalReference(store_callback_property, 4, 1); 1862 __ TailCallExternalReference(store_callback_property, 5, 1);
2655 1863
2656 // Return the generated code. 1864 // Return the generated code.
2657 return GetCode(kind(), Code::FAST, name); 1865 return GetCode(kind(), Code::FAST, name);
2658 } 1866 }
2659 1867
2660 1868
2661 Handle<Code> StoreStubCompiler::CompileStoreCallback( 1869 Handle<Code> StoreStubCompiler::CompileStoreCallback(
2662 Handle<JSObject> object, 1870 Handle<JSObject> object,
2663 Handle<JSObject> holder, 1871 Handle<JSObject> holder,
2664 Handle<Name> name, 1872 Handle<Name> name,
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
2763 } 1971 }
2764 __ bind(&miss); 1972 __ bind(&miss);
2765 TailCallBuiltin(masm(), MissBuiltin(kind())); 1973 TailCallBuiltin(masm(), MissBuiltin(kind()));
2766 1974
2767 // Return the generated code. 1975 // Return the generated code.
2768 return GetICCode( 1976 return GetICCode(
2769 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); 1977 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC);
2770 } 1978 }
2771 1979
2772 1980
2773 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<Type> type, 1981 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<HeapType> type,
2774 Handle<JSObject> last, 1982 Handle<JSObject> last,
2775 Handle<Name> name) { 1983 Handle<Name> name) {
2776 NonexistentHandlerFrontend(type, last, name); 1984 NonexistentHandlerFrontend(type, last, name);
2777 1985
2778 // Return undefined if maps of the full prototype chain are still the 1986 // Return undefined if maps of the full prototype chain are still the
2779 // same and no global property with this name contains a value. 1987 // same and no global property with this name contains a value.
2780 __ mov(eax, isolate()->factory()->undefined_value()); 1988 __ mov(eax, isolate()->factory()->undefined_value());
2781 __ ret(0); 1989 __ ret(0);
2782 1990
2783 // Return the generated code. 1991 // Return the generated code.
(...skipping 22 matching lines...) Expand all
2806 } 2014 }
2807 2015
2808 2016
2809 Register* KeyedStoreStubCompiler::registers() { 2017 Register* KeyedStoreStubCompiler::registers() {
2810 // receiver, name, value, scratch1, scratch2, scratch3. 2018 // receiver, name, value, scratch1, scratch2, scratch3.
2811 static Register registers[] = { edx, ecx, eax, ebx, edi, no_reg }; 2019 static Register registers[] = { edx, ecx, eax, ebx, edi, no_reg };
2812 return registers; 2020 return registers;
2813 } 2021 }
2814 2022
2815 2023
2816 void KeyedLoadStubCompiler::GenerateNameCheck(Handle<Name> name,
2817 Register name_reg,
2818 Label* miss) {
2819 __ cmp(name_reg, Immediate(name));
2820 __ j(not_equal, miss);
2821 }
2822
2823
2824 void KeyedStoreStubCompiler::GenerateNameCheck(Handle<Name> name,
2825 Register name_reg,
2826 Label* miss) {
2827 __ cmp(name_reg, Immediate(name));
2828 __ j(not_equal, miss);
2829 }
2830
2831
2832 #undef __ 2024 #undef __
2833 #define __ ACCESS_MASM(masm) 2025 #define __ ACCESS_MASM(masm)
2834 2026
2835 2027
2836 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, 2028 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm,
2837 Register receiver, 2029 Register receiver,
2838 Handle<JSFunction> getter) { 2030 Handle<JSFunction> getter) {
2839 { 2031 {
2840 FrameScope scope(masm, StackFrame::INTERNAL); 2032 FrameScope scope(masm, StackFrame::INTERNAL);
2841 2033
(...skipping 15 matching lines...) Expand all
2857 } 2049 }
2858 __ ret(0); 2050 __ ret(0);
2859 } 2051 }
2860 2052
2861 2053
2862 #undef __ 2054 #undef __
2863 #define __ ACCESS_MASM(masm()) 2055 #define __ ACCESS_MASM(masm())
2864 2056
2865 2057
2866 Handle<Code> LoadStubCompiler::CompileLoadGlobal( 2058 Handle<Code> LoadStubCompiler::CompileLoadGlobal(
2867 Handle<Type> type, 2059 Handle<HeapType> type,
2868 Handle<GlobalObject> global, 2060 Handle<GlobalObject> global,
2869 Handle<PropertyCell> cell, 2061 Handle<PropertyCell> cell,
2870 Handle<Name> name, 2062 Handle<Name> name,
2871 bool is_dont_delete) { 2063 bool is_dont_delete) {
2872 Label miss; 2064 Label miss;
2873 2065
2874 HandlerFrontendHeader(type, receiver(), global, name, &miss); 2066 HandlerFrontendHeader(type, receiver(), global, name, &miss);
2875 // Get the value from the cell. 2067 // Get the value from the cell.
2876 if (Serializer::enabled()) { 2068 if (Serializer::enabled()) {
2877 __ mov(eax, Immediate(cell)); 2069 __ mov(eax, Immediate(cell));
(...skipping 24 matching lines...) Expand all
2902 2094
2903 2095
2904 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( 2096 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC(
2905 TypeHandleList* types, 2097 TypeHandleList* types,
2906 CodeHandleList* handlers, 2098 CodeHandleList* handlers,
2907 Handle<Name> name, 2099 Handle<Name> name,
2908 Code::StubType type, 2100 Code::StubType type,
2909 IcCheckType check) { 2101 IcCheckType check) {
2910 Label miss; 2102 Label miss;
2911 2103
2912 if (check == PROPERTY) { 2104 if (check == PROPERTY &&
2913 GenerateNameCheck(name, this->name(), &miss); 2105 (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) {
2106 __ cmp(this->name(), Immediate(name));
2107 __ j(not_equal, &miss);
2914 } 2108 }
2915 2109
2916 Label number_case; 2110 Label number_case;
2917 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; 2111 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss;
2918 __ JumpIfSmi(receiver(), smi_target); 2112 __ JumpIfSmi(receiver(), smi_target);
2919 2113
2920 Register map_reg = scratch1(); 2114 Register map_reg = scratch1();
2921 __ mov(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); 2115 __ mov(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset));
2922 int receiver_count = types->length(); 2116 int receiver_count = types->length();
2923 int number_of_handled_maps = 0; 2117 int number_of_handled_maps = 0;
2924 for (int current = 0; current < receiver_count; ++current) { 2118 for (int current = 0; current < receiver_count; ++current) {
2925 Handle<Type> type = types->at(current); 2119 Handle<HeapType> type = types->at(current);
2926 Handle<Map> map = IC::TypeToMap(*type, isolate()); 2120 Handle<Map> map = IC::TypeToMap(*type, isolate());
2927 if (!map->is_deprecated()) { 2121 if (!map->is_deprecated()) {
2928 number_of_handled_maps++; 2122 number_of_handled_maps++;
2929 __ cmp(map_reg, map); 2123 __ cmp(map_reg, map);
2930 if (type->Is(Type::Number())) { 2124 if (type->Is(HeapType::Number())) {
2931 ASSERT(!number_case.is_unused()); 2125 ASSERT(!number_case.is_unused());
2932 __ bind(&number_case); 2126 __ bind(&number_case);
2933 } 2127 }
2934 __ j(equal, handlers->at(current)); 2128 __ j(equal, handlers->at(current));
2935 } 2129 }
2936 } 2130 }
2937 ASSERT(number_of_handled_maps != 0); 2131 ASSERT(number_of_handled_maps != 0);
2938 2132
2939 __ bind(&miss); 2133 __ bind(&miss);
2940 TailCallBuiltin(masm(), MissBuiltin(kind())); 2134 TailCallBuiltin(masm(), MissBuiltin(kind()));
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
2992 // ----------------------------------- 2186 // -----------------------------------
2993 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); 2187 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
2994 } 2188 }
2995 2189
2996 2190
2997 #undef __ 2191 #undef __
2998 2192
2999 } } // namespace v8::internal 2193 } } // namespace v8::internal
3000 2194
3001 #endif // V8_TARGET_ARCH_IA32 2195 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/macro-assembler-ia32.cc ('k') | src/ic.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698