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

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

Issue 185653004: Experimental parser: merge to r19637 (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 6 years, 9 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/x64/macro-assembler-x64.cc ('k') | src/zone-allocator.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 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 __ movp(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); 238 __ movp(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
239 } 239 }
240 240
241 241
242 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( 242 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
243 MacroAssembler* masm, 243 MacroAssembler* masm,
244 int index, 244 int index,
245 Register prototype, 245 Register prototype,
246 Label* miss) { 246 Label* miss) {
247 Isolate* isolate = masm->isolate(); 247 Isolate* isolate = masm->isolate();
248 // Check we're still in the same context.
249 __ Move(prototype, isolate->global_object());
250 __ cmpq(Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)),
251 prototype);
252 __ j(not_equal, miss);
253 // Get the global function with the given index. 248 // Get the global function with the given index.
254 Handle<JSFunction> function( 249 Handle<JSFunction> function(
255 JSFunction::cast(isolate->native_context()->get(index))); 250 JSFunction::cast(isolate->native_context()->get(index)));
251
252 // Check we're still in the same context.
253 Register scratch = prototype;
254 const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX);
255 __ movp(scratch, Operand(rsi, offset));
256 __ movp(scratch, FieldOperand(scratch, GlobalObject::kNativeContextOffset));
257 __ Cmp(Operand(scratch, Context::SlotOffset(index)), function);
258 __ j(not_equal, miss);
259
256 // Load its initial map. The global functions all have initial maps. 260 // Load its initial map. The global functions all have initial maps.
257 __ Move(prototype, Handle<Map>(function->initial_map())); 261 __ Move(prototype, Handle<Map>(function->initial_map()));
258 // Load the prototype from the initial map. 262 // Load the prototype from the initial map.
259 __ movp(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); 263 __ movp(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
260 } 264 }
261 265
262 266
263 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, 267 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
264 Register receiver, 268 Register receiver,
265 Register scratch, 269 Register scratch,
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 Register name, 385 Register name,
382 Handle<JSObject> holder_obj, 386 Handle<JSObject> holder_obj,
383 IC::UtilityId id) { 387 IC::UtilityId id) {
384 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); 388 PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
385 __ CallExternalReference( 389 __ CallExternalReference(
386 ExternalReference(IC_Utility(id), masm->isolate()), 390 ExternalReference(IC_Utility(id), masm->isolate()),
387 StubCache::kInterceptorArgsLength); 391 StubCache::kInterceptorArgsLength);
388 } 392 }
389 393
390 394
391 // Number of pointers to be reserved on stack for fast API call.
392 static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength;
393
394
395 // Reserves space for the extra arguments to API function in the
396 // caller's frame.
397 //
398 // These arguments are set by CheckPrototypes and GenerateFastApiCall.
399 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
400 // ----------- S t a t e -------------
401 // -- rsp[0] : return address
402 // -- rsp[8] : last argument in the internal frame of the caller
403 // -----------------------------------
404 __ movq(scratch, StackOperandForReturnAddress(0));
405 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
406 __ movq(StackOperandForReturnAddress(0), scratch);
407 __ Move(scratch, Smi::FromInt(0));
408 StackArgumentsAccessor args(rsp, kFastApiCallArguments,
409 ARGUMENTS_DONT_CONTAIN_RECEIVER);
410 for (int i = 0; i < kFastApiCallArguments; i++) {
411 __ movp(args.GetArgumentOperand(i), scratch);
412 }
413 }
414
415
416 // Undoes the effects of ReserveSpaceForFastApiCall.
417 static void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
418 // ----------- S t a t e -------------
419 // -- rsp[0] : return address.
420 // -- rsp[8] : last fast api call extra argument.
421 // -- ...
422 // -- rsp[kFastApiCallArguments * 8] : first fast api call extra
423 // argument.
424 // -- rsp[kFastApiCallArguments * 8 + 8] : last argument in the internal
425 // frame.
426 // -----------------------------------
427 __ movq(scratch, StackOperandForReturnAddress(0));
428 __ movq(StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize),
429 scratch);
430 __ addq(rsp, Immediate(kPointerSize * kFastApiCallArguments));
431 }
432
433
434 static void GenerateFastApiCallBody(MacroAssembler* masm,
435 const CallOptimization& optimization,
436 int argc,
437 bool restore_context);
438
439
440 // Generates call to API function.
441 static void GenerateFastApiCall(MacroAssembler* masm,
442 const CallOptimization& optimization,
443 int argc) {
444 typedef FunctionCallbackArguments FCA;
445 StackArgumentsAccessor args(rsp, argc + kFastApiCallArguments);
446
447 // Save calling context.
448 int offset = argc + kFastApiCallArguments;
449 __ movp(args.GetArgumentOperand(offset - FCA::kContextSaveIndex), rsi);
450
451 // Get the function and setup the context.
452 Handle<JSFunction> function = optimization.constant_function();
453 __ Move(rdi, function);
454 __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
455 // Construct the FunctionCallbackInfo on the stack.
456 __ movp(args.GetArgumentOperand(offset - FCA::kCalleeIndex), rdi);
457 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
458 Handle<Object> call_data(api_call_info->data(), masm->isolate());
459 if (masm->isolate()->heap()->InNewSpace(*call_data)) {
460 __ Move(rcx, api_call_info);
461 __ movp(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset));
462 __ movp(args.GetArgumentOperand(offset - FCA::kDataIndex), rbx);
463 } else {
464 __ Move(args.GetArgumentOperand(offset - FCA::kDataIndex), call_data);
465 }
466 __ Move(kScratchRegister,
467 ExternalReference::isolate_address(masm->isolate()));
468 __ movp(args.GetArgumentOperand(offset - FCA::kIsolateIndex),
469 kScratchRegister);
470 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex);
471 __ movp(args.GetArgumentOperand(offset - FCA::kReturnValueDefaultValueIndex),
472 kScratchRegister);
473 __ movp(args.GetArgumentOperand(offset - FCA::kReturnValueOffset),
474 kScratchRegister);
475
476 // Prepare arguments.
477 STATIC_ASSERT(kFastApiCallArguments == 7);
478 __ lea(rax, args.GetArgumentOperand(offset - FCA::kHolderIndex));
479
480 GenerateFastApiCallBody(masm, optimization, argc, false);
481 }
482
483
484 // Generate call to api function. 395 // Generate call to api function.
485 // This function uses push() to generate smaller, faster code than 396 void StubCompiler::GenerateFastApiCall(MacroAssembler* masm,
486 // the version above. It is an optimization that should will be removed 397 const CallOptimization& optimization,
487 // when api call ICs are generated in hydrogen. 398 Handle<Map> receiver_map,
488 static void GenerateFastApiCall(MacroAssembler* masm, 399 Register receiver,
489 const CallOptimization& optimization, 400 Register scratch_in,
490 Register receiver, 401 bool is_store,
491 Register scratch1, 402 int argc,
492 Register scratch2, 403 Register* values) {
493 Register scratch3,
494 int argc,
495 Register* values) {
496 ASSERT(optimization.is_simple_api_call()); 404 ASSERT(optimization.is_simple_api_call());
497 405
498 __ PopReturnAddressTo(scratch1); 406 __ PopReturnAddressTo(scratch_in);
499
500 // receiver 407 // receiver
501 __ push(receiver); 408 __ push(receiver);
502
503 // Write the arguments to stack frame. 409 // Write the arguments to stack frame.
504 for (int i = 0; i < argc; i++) { 410 for (int i = 0; i < argc; i++) {
505 Register arg = values[argc-1-i]; 411 Register arg = values[argc-1-i];
506 ASSERT(!receiver.is(arg)); 412 ASSERT(!receiver.is(arg));
507 ASSERT(!scratch1.is(arg)); 413 ASSERT(!scratch_in.is(arg));
508 ASSERT(!scratch2.is(arg));
509 ASSERT(!scratch3.is(arg));
510 __ push(arg); 414 __ push(arg);
511 } 415 }
416 __ PushReturnAddressFrom(scratch_in);
417 // Stack now matches JSFunction abi.
512 418
513 typedef FunctionCallbackArguments FCA; 419 // Abi for CallApiFunctionStub.
420 Register callee = rax;
421 Register call_data = rbx;
422 Register holder = rcx;
423 Register api_function_address = rdx;
424 Register scratch = rdi; // scratch_in is no longer valid.
514 425
515 STATIC_ASSERT(FCA::kHolderIndex == 0); 426 // Put holder in place.
516 STATIC_ASSERT(FCA::kIsolateIndex == 1); 427 CallOptimization::HolderLookup holder_lookup;
517 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); 428 Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType(
518 STATIC_ASSERT(FCA::kReturnValueOffset == 3); 429 receiver_map,
519 STATIC_ASSERT(FCA::kDataIndex == 4); 430 &holder_lookup);
520 STATIC_ASSERT(FCA::kCalleeIndex == 5); 431 switch (holder_lookup) {
521 STATIC_ASSERT(FCA::kContextSaveIndex == 6); 432 case CallOptimization::kHolderIsReceiver:
522 STATIC_ASSERT(FCA::kArgsLength == 7); 433 __ Move(holder, receiver);
523 434 break;
524 // context save 435 case CallOptimization::kHolderFound:
525 __ push(rsi); 436 __ Move(holder, api_holder);
526 437 break;
527 // Get the function and setup the context. 438 case CallOptimization::kHolderNotFound:
528 Handle<JSFunction> function = optimization.constant_function(); 439 UNREACHABLE();
529 __ Move(scratch2, function); 440 break;
530 __ push(scratch2); 441 }
531 442
532 Isolate* isolate = masm->isolate(); 443 Isolate* isolate = masm->isolate();
444 Handle<JSFunction> function = optimization.constant_function();
533 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 445 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
534 Handle<Object> call_data(api_call_info->data(), isolate); 446 Handle<Object> call_data_obj(api_call_info->data(), isolate);
535 // Push data from ExecutableAccessorInfo. 447
448 // Put callee in place.
449 __ Move(callee, function);
450
536 bool call_data_undefined = false; 451 bool call_data_undefined = false;
537 if (isolate->heap()->InNewSpace(*call_data)) { 452 // Put call_data in place.
538 __ Move(scratch2, api_call_info); 453 if (isolate->heap()->InNewSpace(*call_data_obj)) {
539 __ movp(scratch3, FieldOperand(scratch2, CallHandlerInfo::kDataOffset)); 454 __ Move(scratch, api_call_info);
540 } else if (call_data->IsUndefined()) { 455 __ movp(call_data, FieldOperand(scratch, CallHandlerInfo::kDataOffset));
456 } else if (call_data_obj->IsUndefined()) {
541 call_data_undefined = true; 457 call_data_undefined = true;
542 __ LoadRoot(scratch3, Heap::kUndefinedValueRootIndex); 458 __ LoadRoot(call_data, Heap::kUndefinedValueRootIndex);
543 } else { 459 } else {
544 __ Move(scratch3, call_data); 460 __ Move(call_data, call_data_obj);
545 }
546 // call data
547 __ push(scratch3);
548 if (!call_data_undefined) {
549 __ LoadRoot(scratch3, Heap::kUndefinedValueRootIndex);
550 }
551 // return value
552 __ push(scratch3);
553 // return value default
554 __ push(scratch3);
555 // isolate
556 __ Move(scratch3,
557 ExternalReference::isolate_address(masm->isolate()));
558 __ push(scratch3);
559 // holder
560 __ push(receiver);
561
562 ASSERT(!scratch1.is(rax));
563 // store receiver address for GenerateFastApiCallBody
564 __ movp(rax, rsp);
565 __ PushReturnAddressFrom(scratch1);
566
567 GenerateFastApiCallBody(masm, optimization, argc, true);
568 }
569
570
571 static void GenerateFastApiCallBody(MacroAssembler* masm,
572 const CallOptimization& optimization,
573 int argc,
574 bool restore_context) {
575 // ----------- S t a t e -------------
576 // -- rsp[0] : return address
577 // -- rsp[8] - rsp[56] : FunctionCallbackInfo, incl.
578 // : object passing the type check
579 // (set by CheckPrototypes)
580 // -- rsp[64] : last argument
581 // -- ...
582 // -- rsp[(argc + 7) * 8] : first argument
583 // -- rsp[(argc + 8) * 8] : receiver
584 //
585 // rax : receiver address
586 // -----------------------------------
587 typedef FunctionCallbackArguments FCA;
588
589 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
590 // Function address is a foreign pointer outside V8's heap.
591 Address function_address = v8::ToCData<Address>(api_call_info->callback());
592
593 // Allocate the v8::Arguments structure in the arguments' space since
594 // it's not controlled by GC.
595 const int kApiStackSpace = 4;
596
597 __ PrepareCallApiFunction(kApiStackSpace);
598
599 __ movp(StackSpaceOperand(0), rax); // FunctionCallbackInfo::implicit_args_.
600 __ addq(rax, Immediate((argc + kFastApiCallArguments - 1) * kPointerSize));
601 __ movp(StackSpaceOperand(1), rax); // FunctionCallbackInfo::values_.
602 __ Set(StackSpaceOperand(2), argc); // FunctionCallbackInfo::length_.
603 // FunctionCallbackInfo::is_construct_call_.
604 __ Set(StackSpaceOperand(3), 0);
605
606 #if defined(__MINGW64__) || defined(_WIN64)
607 Register arguments_arg = rcx;
608 Register callback_arg = rdx;
609 #else
610 Register arguments_arg = rdi;
611 Register callback_arg = rsi;
612 #endif
613
614 // v8::InvocationCallback's argument.
615 __ lea(arguments_arg, StackSpaceOperand(0));
616
617 Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback);
618
619 StackArgumentsAccessor args_from_rbp(rbp, kFastApiCallArguments,
620 ARGUMENTS_DONT_CONTAIN_RECEIVER);
621 Operand context_restore_operand = args_from_rbp.GetArgumentOperand(
622 kFastApiCallArguments - 1 - FCA::kContextSaveIndex);
623 Operand return_value_operand = args_from_rbp.GetArgumentOperand(
624 kFastApiCallArguments - 1 - FCA::kReturnValueOffset);
625 __ CallApiFunctionAndReturn(
626 function_address,
627 thunk_address,
628 callback_arg,
629 argc + kFastApiCallArguments + 1,
630 return_value_operand,
631 restore_context ? &context_restore_operand : NULL);
632 }
633
634
635 class CallInterceptorCompiler BASE_EMBEDDED {
636 public:
637 CallInterceptorCompiler(CallStubCompiler* stub_compiler,
638 const ParameterCount& arguments,
639 Register name)
640 : stub_compiler_(stub_compiler),
641 arguments_(arguments),
642 name_(name) {}
643
644 void Compile(MacroAssembler* masm,
645 Handle<JSObject> object,
646 Handle<JSObject> holder,
647 Handle<Name> name,
648 LookupResult* lookup,
649 Register receiver,
650 Register scratch1,
651 Register scratch2,
652 Register scratch3,
653 Label* miss) {
654 ASSERT(holder->HasNamedInterceptor());
655 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
656
657 // Check that the receiver isn't a smi.
658 __ JumpIfSmi(receiver, miss);
659
660 CallOptimization optimization(lookup);
661 if (optimization.is_constant_call()) {
662 CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3,
663 holder, lookup, name, optimization, miss);
664 } else {
665 CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3,
666 name, holder, miss);
667 }
668 } 461 }
669 462
670 private: 463 // Put api_function_address in place.
671 void CompileCacheable(MacroAssembler* masm, 464 Address function_address = v8::ToCData<Address>(api_call_info->callback());
672 Handle<JSObject> object, 465 __ Move(
673 Register receiver, 466 api_function_address, function_address, RelocInfo::EXTERNAL_REFERENCE);
674 Register scratch1,
675 Register scratch2,
676 Register scratch3,
677 Handle<JSObject> interceptor_holder,
678 LookupResult* lookup,
679 Handle<Name> name,
680 const CallOptimization& optimization,
681 Label* miss_label) {
682 ASSERT(optimization.is_constant_call());
683 ASSERT(!lookup->holder()->IsGlobalObject());
684 467
685 int depth1 = kInvalidProtoDepth; 468 // Jump to stub.
686 int depth2 = kInvalidProtoDepth; 469 CallApiFunctionStub stub(is_store, call_data_undefined, argc);
687 bool can_do_fast_api_call = false; 470 __ TailCallStub(&stub);
688 if (optimization.is_simple_api_call() && 471 }
689 !lookup->holder()->IsGlobalObject()) {
690 depth1 = optimization.GetPrototypeDepthOfExpectedType(
691 object, interceptor_holder);
692 if (depth1 == kInvalidProtoDepth) {
693 depth2 = optimization.GetPrototypeDepthOfExpectedType(
694 interceptor_holder, Handle<JSObject>(lookup->holder()));
695 }
696 can_do_fast_api_call =
697 depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth;
698 }
699
700 Counters* counters = masm->isolate()->counters();
701 __ IncrementCounter(counters->call_const_interceptor(), 1);
702
703 if (can_do_fast_api_call) {
704 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1);
705 ReserveSpaceForFastApiCall(masm, scratch1);
706 }
707
708 // Check that the maps from receiver to interceptor's holder
709 // haven't changed and thus we can invoke interceptor.
710 Label miss_cleanup;
711 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
712 Register holder =
713 stub_compiler_->CheckPrototypes(
714 IC::CurrentTypeOf(object, masm->isolate()), receiver,
715 interceptor_holder, scratch1, scratch2, scratch3,
716 name, depth1, miss);
717
718 // Invoke an interceptor and if it provides a value,
719 // branch to |regular_invoke|.
720 Label regular_invoke;
721 LoadWithInterceptor(masm, receiver, holder, interceptor_holder,
722 &regular_invoke);
723
724 // Interceptor returned nothing for this property. Try to use cached
725 // constant function.
726
727 // Check that the maps from interceptor's holder to constant function's
728 // holder haven't changed and thus we can use cached constant function.
729 if (*interceptor_holder != lookup->holder()) {
730 stub_compiler_->CheckPrototypes(
731 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder,
732 handle(lookup->holder()), scratch1, scratch2, scratch3,
733 name, depth2, miss);
734 } else {
735 // CheckPrototypes has a side effect of fetching a 'holder'
736 // for API (object which is instanceof for the signature). It's
737 // safe to omit it here, as if present, it should be fetched
738 // by the previous CheckPrototypes.
739 ASSERT(depth2 == kInvalidProtoDepth);
740 }
741
742 // Invoke function.
743 if (can_do_fast_api_call) {
744 GenerateFastApiCall(masm, optimization, arguments_.immediate());
745 } else {
746 Handle<JSFunction> fun = optimization.constant_function();
747 stub_compiler_->GenerateJumpFunction(object, fun);
748 }
749
750 // Deferred code for fast API call case---clean preallocated space.
751 if (can_do_fast_api_call) {
752 __ bind(&miss_cleanup);
753 FreeSpaceForFastApiCall(masm, scratch1);
754 __ jmp(miss_label);
755 }
756
757 // Invoke a regular function.
758 __ bind(&regular_invoke);
759 if (can_do_fast_api_call) {
760 FreeSpaceForFastApiCall(masm, scratch1);
761 }
762 }
763
764 void CompileRegular(MacroAssembler* masm,
765 Handle<JSObject> object,
766 Register receiver,
767 Register scratch1,
768 Register scratch2,
769 Register scratch3,
770 Handle<Name> name,
771 Handle<JSObject> interceptor_holder,
772 Label* miss_label) {
773 Register holder =
774 stub_compiler_->CheckPrototypes(
775 IC::CurrentTypeOf(object, masm->isolate()), receiver,
776 interceptor_holder, scratch1, scratch2, scratch3, name, miss_label);
777
778 FrameScope scope(masm, StackFrame::INTERNAL);
779 // Save the name_ register across the call.
780 __ push(name_);
781
782 CompileCallLoadPropertyWithInterceptor(
783 masm, receiver, holder, name_, interceptor_holder,
784 IC::kLoadPropertyWithInterceptorForCall);
785
786 // Restore the name_ register.
787 __ pop(name_);
788
789 // Leave the internal frame.
790 }
791
792 void LoadWithInterceptor(MacroAssembler* masm,
793 Register receiver,
794 Register holder,
795 Handle<JSObject> holder_obj,
796 Label* interceptor_succeeded) {
797 {
798 FrameScope scope(masm, StackFrame::INTERNAL);
799 __ push(receiver);
800 __ push(holder);
801 __ push(name_);
802
803 CompileCallLoadPropertyWithInterceptor(
804 masm, receiver, holder, name_, holder_obj,
805 IC::kLoadPropertyWithInterceptorOnly);
806
807 __ pop(name_);
808 __ pop(holder);
809 __ pop(receiver);
810 // Leave the internal frame.
811 }
812
813 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex);
814 __ j(not_equal, interceptor_succeeded);
815 }
816
817 CallStubCompiler* stub_compiler_;
818 const ParameterCount& arguments_;
819 Register name_;
820 };
821 472
822 473
823 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, 474 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
824 Label* label, 475 Label* label,
825 Handle<Name> name) { 476 Handle<Name> name) {
826 if (!label->is_unused()) { 477 if (!label->is_unused()) {
827 __ bind(label); 478 __ bind(label);
828 __ Move(this->name(), name); 479 __ Move(this->name(), name);
829 } 480 }
830 } 481 }
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
1106 757
1107 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { 758 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) {
1108 __ jmp(code, RelocInfo::CODE_TARGET); 759 __ jmp(code, RelocInfo::CODE_TARGET);
1109 } 760 }
1110 761
1111 762
1112 #undef __ 763 #undef __
1113 #define __ ACCESS_MASM((masm())) 764 #define __ ACCESS_MASM((masm()))
1114 765
1115 766
1116 Register StubCompiler::CheckPrototypes(Handle<Type> type, 767 Register StubCompiler::CheckPrototypes(Handle<HeapType> type,
1117 Register object_reg, 768 Register object_reg,
1118 Handle<JSObject> holder, 769 Handle<JSObject> holder,
1119 Register holder_reg, 770 Register holder_reg,
1120 Register scratch1, 771 Register scratch1,
1121 Register scratch2, 772 Register scratch2,
1122 Handle<Name> name, 773 Handle<Name> name,
1123 int save_at_depth,
1124 Label* miss, 774 Label* miss,
1125 PrototypeCheckType check) { 775 PrototypeCheckType check) {
1126 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); 776 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate()));
1127 // Make sure that the type feedback oracle harvests the receiver map.
1128 // TODO(svenpanne) Remove this hack when all ICs are reworked.
1129 __ Move(scratch1, receiver_map);
1130 777
1131 // Make sure there's no overlap between holder and object registers. 778 // Make sure there's no overlap between holder and object registers.
1132 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 779 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
1133 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) 780 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
1134 && !scratch2.is(scratch1)); 781 && !scratch2.is(scratch1));
1135 782
1136 // Keep track of the current object in register reg. On the first 783 // Keep track of the current object in register reg. On the first
1137 // iteration, reg is an alias for object_reg, on later iterations, 784 // iteration, reg is an alias for object_reg, on later iterations,
1138 // it is an alias for holder_reg. 785 // it is an alias for holder_reg.
1139 Register reg = object_reg; 786 Register reg = object_reg;
1140 int depth = 0; 787 int depth = 0;
1141 788
1142 StackArgumentsAccessor args(rsp, kFastApiCallArguments,
1143 ARGUMENTS_DONT_CONTAIN_RECEIVER);
1144 const int kHolderIndex = kFastApiCallArguments - 1 -
1145 FunctionCallbackArguments::kHolderIndex;
1146
1147 if (save_at_depth == depth) {
1148 __ movp(args.GetArgumentOperand(kHolderIndex), object_reg);
1149 }
1150
1151 Handle<JSObject> current = Handle<JSObject>::null(); 789 Handle<JSObject> current = Handle<JSObject>::null();
1152 if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant()); 790 if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant());
1153 Handle<JSObject> prototype = Handle<JSObject>::null(); 791 Handle<JSObject> prototype = Handle<JSObject>::null();
1154 Handle<Map> current_map = receiver_map; 792 Handle<Map> current_map = receiver_map;
1155 Handle<Map> holder_map(holder->map()); 793 Handle<Map> holder_map(holder->map());
1156 // Traverse the prototype chain and check the maps in the prototype chain for 794 // Traverse the prototype chain and check the maps in the prototype chain for
1157 // fast and global objects or do negative lookup for normal objects. 795 // fast and global objects or do negative lookup for normal objects.
1158 while (!current_map.is_identical_to(holder_map)) { 796 while (!current_map.is_identical_to(holder_map)) {
1159 ++depth; 797 ++depth;
1160 798
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1206 if (in_new_space) { 844 if (in_new_space) {
1207 // The prototype is in new space; we cannot store a reference to it 845 // The prototype is in new space; we cannot store a reference to it
1208 // in the code. Load it from the map. 846 // in the code. Load it from the map.
1209 __ movp(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); 847 __ movp(reg, FieldOperand(scratch1, Map::kPrototypeOffset));
1210 } else { 848 } else {
1211 // The prototype is in old space; load it directly. 849 // The prototype is in old space; load it directly.
1212 __ Move(reg, prototype); 850 __ Move(reg, prototype);
1213 } 851 }
1214 } 852 }
1215 853
1216 if (save_at_depth == depth) {
1217 __ movp(args.GetArgumentOperand(kHolderIndex), reg);
1218 }
1219
1220 // Go to the next object in the prototype chain. 854 // Go to the next object in the prototype chain.
1221 current = prototype; 855 current = prototype;
1222 current_map = handle(current->map()); 856 current_map = handle(current->map());
1223 } 857 }
1224 858
1225 // Log the check depth. 859 // Log the check depth.
1226 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); 860 LOG(isolate(), IntEvent("check-maps-depth", depth + 1));
1227 861
1228 if (depth != 0 || check == CHECK_ALL_MAPS) { 862 if (depth != 0 || check == CHECK_ALL_MAPS) {
1229 // Check the holder map. 863 // Check the holder map.
(...skipping 28 matching lines...) Expand all
1258 Label success; 892 Label success;
1259 __ jmp(&success); 893 __ jmp(&success);
1260 GenerateRestoreName(masm(), miss, name); 894 GenerateRestoreName(masm(), miss, name);
1261 TailCallBuiltin(masm(), MissBuiltin(kind())); 895 TailCallBuiltin(masm(), MissBuiltin(kind()));
1262 __ bind(&success); 896 __ bind(&success);
1263 } 897 }
1264 } 898 }
1265 899
1266 900
1267 Register LoadStubCompiler::CallbackHandlerFrontend( 901 Register LoadStubCompiler::CallbackHandlerFrontend(
1268 Handle<Type> type, 902 Handle<HeapType> type,
1269 Register object_reg, 903 Register object_reg,
1270 Handle<JSObject> holder, 904 Handle<JSObject> holder,
1271 Handle<Name> name, 905 Handle<Name> name,
1272 Handle<Object> callback) { 906 Handle<Object> callback) {
1273 Label miss; 907 Label miss;
1274 908
1275 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss); 909 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss);
1276 910
1277 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { 911 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) {
1278 ASSERT(!reg.is(scratch2())); 912 ASSERT(!reg.is(scratch2()));
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1327 } else { 961 } else {
1328 KeyedLoadFieldStub stub(field.is_inobject(holder), 962 KeyedLoadFieldStub stub(field.is_inobject(holder),
1329 field.translate(holder), 963 field.translate(holder),
1330 representation); 964 representation);
1331 GenerateTailCall(masm(), stub.GetCode(isolate())); 965 GenerateTailCall(masm(), stub.GetCode(isolate()));
1332 } 966 }
1333 } 967 }
1334 968
1335 969
1336 void LoadStubCompiler::GenerateLoadCallback( 970 void LoadStubCompiler::GenerateLoadCallback(
1337 const CallOptimization& call_optimization) {
1338 GenerateFastApiCall(
1339 masm(), call_optimization, receiver(),
1340 scratch1(), scratch2(), name(), 0, NULL);
1341 }
1342
1343
1344 void LoadStubCompiler::GenerateLoadCallback(
1345 Register reg, 971 Register reg,
1346 Handle<ExecutableAccessorInfo> callback) { 972 Handle<ExecutableAccessorInfo> callback) {
1347 // Insert additional parameters into the stack frame above return address. 973 // Insert additional parameters into the stack frame above return address.
1348 ASSERT(!scratch4().is(reg)); 974 ASSERT(!scratch4().is(reg));
1349 __ PopReturnAddressTo(scratch4()); 975 __ PopReturnAddressTo(scratch4());
1350 976
1351 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); 977 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0);
1352 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); 978 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1);
1353 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); 979 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2);
1354 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); 980 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3);
(...skipping 12 matching lines...) Expand all
1367 ASSERT(!kScratchRegister.is(reg)); 993 ASSERT(!kScratchRegister.is(reg));
1368 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); 994 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex);
1369 __ push(kScratchRegister); // return value 995 __ push(kScratchRegister); // return value
1370 __ push(kScratchRegister); // return value default 996 __ push(kScratchRegister); // return value default
1371 __ PushAddress(ExternalReference::isolate_address(isolate())); 997 __ PushAddress(ExternalReference::isolate_address(isolate()));
1372 __ push(reg); // holder 998 __ push(reg); // holder
1373 __ push(name()); // name 999 __ push(name()); // name
1374 // Save a pointer to where we pushed the arguments pointer. This will be 1000 // Save a pointer to where we pushed the arguments pointer. This will be
1375 // passed as the const PropertyAccessorInfo& to the C++ callback. 1001 // passed as the const PropertyAccessorInfo& to the C++ callback.
1376 1002
1377 Address getter_address = v8::ToCData<Address>(callback->getter());
1378
1379 #if defined(__MINGW64__) || defined(_WIN64)
1380 Register getter_arg = r8;
1381 Register accessor_info_arg = rdx;
1382 Register name_arg = rcx;
1383 #else
1384 Register getter_arg = rdx;
1385 Register accessor_info_arg = rsi;
1386 Register name_arg = rdi;
1387 #endif
1388
1389 ASSERT(!name_arg.is(scratch4()));
1390 __ movp(name_arg, rsp);
1391 __ PushReturnAddressFrom(scratch4()); 1003 __ PushReturnAddressFrom(scratch4());
1392 1004
1393 // v8::Arguments::values_ and handler for name. 1005 // Abi for CallApiGetter
1394 const int kStackSpace = PropertyCallbackArguments::kArgsLength + 1; 1006 Register api_function_address = r8;
1007 Address getter_address = v8::ToCData<Address>(callback->getter());
1008 __ Move(api_function_address, getter_address, RelocInfo::EXTERNAL_REFERENCE);
1395 1009
1396 // Allocate v8::AccessorInfo in non-GCed stack space. 1010 CallApiGetterStub stub;
1397 const int kArgStackSpace = 1; 1011 __ TailCallStub(&stub);
1398
1399 __ PrepareCallApiFunction(kArgStackSpace);
1400 __ lea(rax, Operand(name_arg, 1 * kPointerSize));
1401
1402 // v8::PropertyAccessorInfo::args_.
1403 __ movp(StackSpaceOperand(0), rax);
1404
1405 // The context register (rsi) has been saved in PrepareCallApiFunction and
1406 // could be used to pass arguments.
1407 __ lea(accessor_info_arg, StackSpaceOperand(0));
1408
1409 Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback);
1410
1411 // The name handler is counted as an argument.
1412 StackArgumentsAccessor args(rbp, PropertyCallbackArguments::kArgsLength);
1413 Operand return_value_operand = args.GetArgumentOperand(
1414 PropertyCallbackArguments::kArgsLength - 1 -
1415 PropertyCallbackArguments::kReturnValueOffset);
1416 __ CallApiFunctionAndReturn(getter_address,
1417 thunk_address,
1418 getter_arg,
1419 kStackSpace,
1420 return_value_operand,
1421 NULL);
1422 } 1012 }
1423 1013
1424 1014
1425 void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { 1015 void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) {
1426 // Return the constant value. 1016 // Return the constant value.
1427 __ Move(rax, value); 1017 __ Move(rax, value);
1428 __ ret(0); 1018 __ ret(0);
1429 } 1019 }
1430 1020
1431 1021
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
1513 this->name(), interceptor_holder); 1103 this->name(), interceptor_holder);
1514 __ PushReturnAddressFrom(scratch2()); 1104 __ PushReturnAddressFrom(scratch2());
1515 1105
1516 ExternalReference ref = ExternalReference( 1106 ExternalReference ref = ExternalReference(
1517 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), isolate()); 1107 IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), isolate());
1518 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1); 1108 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1);
1519 } 1109 }
1520 } 1110 }
1521 1111
1522 1112
1523 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) {
1524 if (kind_ == Code::KEYED_CALL_IC) {
1525 __ Cmp(rcx, name);
1526 __ j(not_equal, miss);
1527 }
1528 }
1529
1530
1531 void CallStubCompiler::GenerateFunctionCheck(Register function,
1532 Register scratch,
1533 Label* miss) {
1534 __ JumpIfSmi(function, miss);
1535 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch);
1536 __ j(not_equal, miss);
1537 }
1538
1539
1540 void CallStubCompiler::GenerateLoadFunctionFromCell(
1541 Handle<Cell> cell,
1542 Handle<JSFunction> function,
1543 Label* miss) {
1544 // Get the value from the cell.
1545 __ Move(rdi, cell);
1546 __ movp(rdi, FieldOperand(rdi, Cell::kValueOffset));
1547
1548 // Check that the cell contains the same function.
1549 if (heap()->InNewSpace(*function)) {
1550 // We can't embed a pointer to a function in new space so we have
1551 // to verify that the shared function info is unchanged. This has
1552 // the nice side effect that multiple closures based on the same
1553 // function can all use this call IC. Before we load through the
1554 // function, we have to verify that it still is a function.
1555 GenerateFunctionCheck(rdi, rax, miss);
1556
1557 // Check the shared function info. Make sure it hasn't changed.
1558 __ Move(rax, Handle<SharedFunctionInfo>(function->shared()));
1559 __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax);
1560 } else {
1561 __ Cmp(rdi, function);
1562 }
1563 __ j(not_equal, miss);
1564 }
1565
1566
1567 void CallStubCompiler::GenerateMissBranch() {
1568 Handle<Code> code =
1569 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
1570 kind_,
1571 extra_state());
1572 __ Jump(code, RelocInfo::CODE_TARGET);
1573 }
1574
1575
1576 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
1577 Handle<JSObject> holder,
1578 PropertyIndex index,
1579 Handle<Name> name) {
1580 Label miss;
1581
1582 Register reg = HandlerFrontendHeader(
1583 object, holder, name, RECEIVER_MAP_CHECK, &miss);
1584
1585 GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder),
1586 index.translate(holder), Representation::Tagged());
1587 GenerateJumpFunction(object, rdi, &miss);
1588
1589 HandlerFrontendFooter(&miss);
1590
1591 // Return the generated code.
1592 return GetCode(Code::FAST, name);
1593 }
1594
1595
1596 Handle<Code> CallStubCompiler::CompileArrayPushCall(
1597 Handle<Object> object,
1598 Handle<JSObject> holder,
1599 Handle<Cell> cell,
1600 Handle<JSFunction> function,
1601 Handle<String> name,
1602 Code::StubType type) {
1603 // If object is not an array or is observed or sealed, bail out to regular
1604 // call.
1605 if (!object->IsJSArray() ||
1606 !cell.is_null() ||
1607 Handle<JSArray>::cast(object)->map()->is_observed() ||
1608 !Handle<JSArray>::cast(object)->map()->is_extensible()) {
1609 return Handle<Code>::null();
1610 }
1611
1612 Label miss;
1613
1614 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
1615
1616 const int argc = arguments().immediate();
1617 StackArgumentsAccessor args(rsp, argc);
1618 if (argc == 0) {
1619 // Noop, return the length.
1620 __ movp(rax, FieldOperand(rdx, JSArray::kLengthOffset));
1621 __ ret((argc + 1) * kPointerSize);
1622 } else {
1623 Label call_builtin;
1624
1625 if (argc == 1) { // Otherwise fall through to call builtin.
1626 Label attempt_to_grow_elements, with_write_barrier, check_double;
1627
1628 // Get the elements array of the object.
1629 __ movp(rdi, FieldOperand(rdx, JSArray::kElementsOffset));
1630
1631 // Check that the elements are in fast mode and writable.
1632 __ Cmp(FieldOperand(rdi, HeapObject::kMapOffset),
1633 factory()->fixed_array_map());
1634 __ j(not_equal, &check_double);
1635
1636 // Get the array's length into rax and calculate new length.
1637 __ SmiToInteger32(rax, FieldOperand(rdx, JSArray::kLengthOffset));
1638 STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue);
1639 __ addl(rax, Immediate(argc));
1640
1641 // Get the elements' length into rcx.
1642 __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
1643
1644 // Check if we could survive without allocation.
1645 __ cmpl(rax, rcx);
1646 __ j(greater, &attempt_to_grow_elements);
1647
1648 // Check if value is a smi.
1649 __ movp(rcx, args.GetArgumentOperand(1));
1650 __ JumpIfNotSmi(rcx, &with_write_barrier);
1651
1652 // Save new length.
1653 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
1654
1655 // Store the value.
1656 __ movp(FieldOperand(rdi,
1657 rax,
1658 times_pointer_size,
1659 FixedArray::kHeaderSize - argc * kPointerSize),
1660 rcx);
1661
1662 __ Integer32ToSmi(rax, rax); // Return new length as smi.
1663 __ ret((argc + 1) * kPointerSize);
1664
1665 __ bind(&check_double);
1666
1667 // Check that the elements are in double mode.
1668 __ Cmp(FieldOperand(rdi, HeapObject::kMapOffset),
1669 factory()->fixed_double_array_map());
1670 __ j(not_equal, &call_builtin);
1671
1672 // Get the array's length into rax and calculate new length.
1673 __ SmiToInteger32(rax, FieldOperand(rdx, JSArray::kLengthOffset));
1674 STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue);
1675 __ addl(rax, Immediate(argc));
1676
1677 // Get the elements' length into rcx.
1678 __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
1679
1680 // Check if we could survive without allocation.
1681 __ cmpl(rax, rcx);
1682 __ j(greater, &call_builtin);
1683
1684 __ movp(rcx, args.GetArgumentOperand(1));
1685 __ StoreNumberToDoubleElements(
1686 rcx, rdi, rax, xmm0, &call_builtin, argc * kDoubleSize);
1687
1688 // Save new length.
1689 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
1690 __ Integer32ToSmi(rax, rax); // Return new length as smi.
1691 __ ret((argc + 1) * kPointerSize);
1692
1693 __ bind(&with_write_barrier);
1694
1695 __ movp(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
1696
1697 if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) {
1698 Label fast_object, not_fast_object;
1699 __ CheckFastObjectElements(rbx, &not_fast_object, Label::kNear);
1700 __ jmp(&fast_object);
1701 // In case of fast smi-only, convert to fast object, otherwise bail out.
1702 __ bind(&not_fast_object);
1703 __ CheckFastSmiElements(rbx, &call_builtin);
1704 __ Cmp(FieldOperand(rcx, HeapObject::kMapOffset),
1705 factory()->heap_number_map());
1706 __ j(equal, &call_builtin);
1707 // rdx: receiver
1708 // rbx: map
1709
1710 Label try_holey_map;
1711 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
1712 FAST_ELEMENTS,
1713 rbx,
1714 rdi,
1715 &try_holey_map);
1716
1717 ElementsTransitionGenerator::
1718 GenerateMapChangeElementsTransition(masm(),
1719 DONT_TRACK_ALLOCATION_SITE,
1720 NULL);
1721 // Restore edi.
1722 __ movp(rdi, FieldOperand(rdx, JSArray::kElementsOffset));
1723 __ jmp(&fast_object);
1724
1725 __ bind(&try_holey_map);
1726 __ LoadTransitionedArrayMapConditional(FAST_HOLEY_SMI_ELEMENTS,
1727 FAST_HOLEY_ELEMENTS,
1728 rbx,
1729 rdi,
1730 &call_builtin);
1731 ElementsTransitionGenerator::
1732 GenerateMapChangeElementsTransition(masm(),
1733 DONT_TRACK_ALLOCATION_SITE,
1734 NULL);
1735 __ movp(rdi, FieldOperand(rdx, JSArray::kElementsOffset));
1736 __ bind(&fast_object);
1737 } else {
1738 __ CheckFastObjectElements(rbx, &call_builtin);
1739 }
1740
1741 // Save new length.
1742 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
1743
1744 // Store the value.
1745 __ lea(rdx, FieldOperand(rdi,
1746 rax, times_pointer_size,
1747 FixedArray::kHeaderSize - argc * kPointerSize));
1748 __ movp(Operand(rdx, 0), rcx);
1749
1750 __ RecordWrite(rdi, rdx, rcx, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
1751 OMIT_SMI_CHECK);
1752
1753 __ Integer32ToSmi(rax, rax); // Return new length as smi.
1754 __ ret((argc + 1) * kPointerSize);
1755
1756 __ bind(&attempt_to_grow_elements);
1757 if (!FLAG_inline_new) {
1758 __ jmp(&call_builtin);
1759 }
1760
1761 __ movp(rbx, args.GetArgumentOperand(1));
1762 // Growing elements that are SMI-only requires special handling in case
1763 // the new element is non-Smi. For now, delegate to the builtin.
1764 Label no_fast_elements_check;
1765 __ JumpIfSmi(rbx, &no_fast_elements_check);
1766 __ movp(rcx, FieldOperand(rdx, HeapObject::kMapOffset));
1767 __ CheckFastObjectElements(rcx, &call_builtin, Label::kFar);
1768 __ bind(&no_fast_elements_check);
1769
1770 ExternalReference new_space_allocation_top =
1771 ExternalReference::new_space_allocation_top_address(isolate());
1772 ExternalReference new_space_allocation_limit =
1773 ExternalReference::new_space_allocation_limit_address(isolate());
1774
1775 const int kAllocationDelta = 4;
1776 // Load top.
1777 __ Load(rcx, new_space_allocation_top);
1778
1779 // Check if it's the end of elements.
1780 __ lea(rdx, FieldOperand(rdi,
1781 rax, times_pointer_size,
1782 FixedArray::kHeaderSize - argc * kPointerSize));
1783 __ cmpq(rdx, rcx);
1784 __ j(not_equal, &call_builtin);
1785 __ addq(rcx, Immediate(kAllocationDelta * kPointerSize));
1786 Operand limit_operand =
1787 masm()->ExternalOperand(new_space_allocation_limit);
1788 __ cmpq(rcx, limit_operand);
1789 __ j(above, &call_builtin);
1790
1791 // We fit and could grow elements.
1792 __ Store(new_space_allocation_top, rcx);
1793
1794 // Push the argument...
1795 __ movp(Operand(rdx, 0), rbx);
1796 // ... and fill the rest with holes.
1797 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
1798 for (int i = 1; i < kAllocationDelta; i++) {
1799 __ movp(Operand(rdx, i * kPointerSize), kScratchRegister);
1800 }
1801
1802 // We know the elements array is in new space so we don't need the
1803 // remembered set, but we just pushed a value onto it so we may have to
1804 // tell the incremental marker to rescan the object that we just grew. We
1805 // don't need to worry about the holes because they are in old space and
1806 // already marked black.
1807 __ RecordWrite(rdi, rdx, rbx, kDontSaveFPRegs, OMIT_REMEMBERED_SET);
1808
1809 // Restore receiver to rdx as finish sequence assumes it's here.
1810 __ movp(rdx, args.GetReceiverOperand());
1811
1812 // Increment element's and array's sizes.
1813 __ SmiAddConstant(FieldOperand(rdi, FixedArray::kLengthOffset),
1814 Smi::FromInt(kAllocationDelta));
1815
1816 // Make new length a smi before returning it.
1817 __ Integer32ToSmi(rax, rax);
1818 __ movp(FieldOperand(rdx, JSArray::kLengthOffset), rax);
1819
1820 __ ret((argc + 1) * kPointerSize);
1821 }
1822
1823 __ bind(&call_builtin);
1824 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush,
1825 isolate()),
1826 argc + 1,
1827 1);
1828 }
1829
1830 HandlerFrontendFooter(&miss);
1831
1832 // Return the generated code.
1833 return GetCode(type, name);
1834 }
1835
1836
1837 Handle<Code> CallStubCompiler::CompileArrayPopCall(
1838 Handle<Object> object,
1839 Handle<JSObject> holder,
1840 Handle<Cell> cell,
1841 Handle<JSFunction> function,
1842 Handle<String> name,
1843 Code::StubType type) {
1844 // If object is not an array or is observed or sealed, bail out to regular
1845 // call.
1846 if (!object->IsJSArray() ||
1847 !cell.is_null() ||
1848 Handle<JSArray>::cast(object)->map()->is_observed() ||
1849 !Handle<JSArray>::cast(object)->map()->is_extensible()) {
1850 return Handle<Code>::null();
1851 }
1852
1853 Label miss, return_undefined, call_builtin;
1854
1855 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
1856
1857 // Get the elements array of the object.
1858 __ movp(rbx, FieldOperand(rdx, JSArray::kElementsOffset));
1859
1860 // Check that the elements are in fast mode and writable.
1861 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
1862 Heap::kFixedArrayMapRootIndex);
1863 __ j(not_equal, &call_builtin);
1864
1865 // Get the array's length into rcx and calculate new length.
1866 __ SmiToInteger32(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
1867 __ subl(rcx, Immediate(1));
1868 __ j(negative, &return_undefined);
1869
1870 // Get the last element.
1871 __ LoadRoot(r9, Heap::kTheHoleValueRootIndex);
1872 __ movp(rax, FieldOperand(rbx,
1873 rcx, times_pointer_size,
1874 FixedArray::kHeaderSize));
1875 // Check if element is already the hole.
1876 __ cmpq(rax, r9);
1877 // If so, call slow-case to also check prototypes for value.
1878 __ j(equal, &call_builtin);
1879
1880 // Set the array's length.
1881 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rcx);
1882
1883 // Fill with the hole and return original value.
1884 __ movp(FieldOperand(rbx,
1885 rcx, times_pointer_size,
1886 FixedArray::kHeaderSize),
1887 r9);
1888 const int argc = arguments().immediate();
1889 __ ret((argc + 1) * kPointerSize);
1890
1891 __ bind(&return_undefined);
1892 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
1893 __ ret((argc + 1) * kPointerSize);
1894
1895 __ bind(&call_builtin);
1896 __ TailCallExternalReference(
1897 ExternalReference(Builtins::c_ArrayPop, isolate()),
1898 argc + 1,
1899 1);
1900
1901 HandlerFrontendFooter(&miss);
1902
1903 // Return the generated code.
1904 return GetCode(type, name);
1905 }
1906
1907
1908 Handle<Code> CallStubCompiler::CompileFastApiCall(
1909 const CallOptimization& optimization,
1910 Handle<Object> object,
1911 Handle<JSObject> holder,
1912 Handle<Cell> cell,
1913 Handle<JSFunction> function,
1914 Handle<String> name) {
1915 ASSERT(optimization.is_simple_api_call());
1916 // Bail out if object is a global object as we don't want to
1917 // repatch it to global receiver.
1918 if (object->IsGlobalObject()) return Handle<Code>::null();
1919 if (!cell.is_null()) return Handle<Code>::null();
1920 if (!object->IsJSObject()) return Handle<Code>::null();
1921 int depth = optimization.GetPrototypeDepthOfExpectedType(
1922 Handle<JSObject>::cast(object), holder);
1923 if (depth == kInvalidProtoDepth) return Handle<Code>::null();
1924
1925 Label miss, miss_before_stack_reserved;
1926 GenerateNameCheck(name, &miss_before_stack_reserved);
1927
1928 const int argc = arguments().immediate();
1929 StackArgumentsAccessor args(rsp, argc);
1930 __ movp(rdx, args.GetReceiverOperand());
1931
1932 // Check that the receiver isn't a smi.
1933 __ JumpIfSmi(rdx, &miss_before_stack_reserved);
1934
1935 Counters* counters = isolate()->counters();
1936 __ IncrementCounter(counters->call_const(), 1);
1937 __ IncrementCounter(counters->call_const_fast_api(), 1);
1938
1939 // Allocate space for v8::Arguments implicit values. Must be initialized
1940 // before calling any runtime function.
1941 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
1942
1943 // Check that the maps haven't changed and find a Holder as a side effect.
1944 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
1945 rbx, rax, rdi, name, depth, &miss);
1946
1947 // Move the return address on top of the stack.
1948 __ movq(rax,
1949 StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize));
1950 __ movq(StackOperandForReturnAddress(0), rax);
1951
1952 GenerateFastApiCall(masm(), optimization, argc);
1953
1954 __ bind(&miss);
1955 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
1956
1957 HandlerFrontendFooter(&miss_before_stack_reserved);
1958
1959 // Return the generated code.
1960 return GetCode(function);
1961 }
1962
1963
1964 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { 1113 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
1965 Label success; 1114 Label success;
1966 // Check that the object is a boolean. 1115 // Check that the object is a boolean.
1967 __ CompareRoot(object, Heap::kTrueValueRootIndex); 1116 __ Cmp(object, factory()->true_value());
1968 __ j(equal, &success); 1117 __ j(equal, &success);
1969 __ CompareRoot(object, Heap::kFalseValueRootIndex); 1118 __ Cmp(object, factory()->false_value());
1970 __ j(not_equal, miss); 1119 __ j(not_equal, miss);
1971 __ bind(&success); 1120 __ bind(&success);
1972 } 1121 }
1973 1122
1974 1123
1975 void CallStubCompiler::PatchImplicitReceiver(Handle<Object> object) {
1976 if (object->IsGlobalObject()) {
1977 StackArgumentsAccessor args(rsp, arguments());
1978 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
1979 __ movp(args.GetReceiverOperand(), rdx);
1980 }
1981 }
1982
1983
1984 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
1985 Handle<JSObject> holder,
1986 Handle<Name> name,
1987 CheckType check,
1988 Label* miss) {
1989 GenerateNameCheck(name, miss);
1990
1991 Register reg = rdx;
1992
1993 StackArgumentsAccessor args(rsp, arguments());
1994 __ movp(reg, args.GetReceiverOperand());
1995
1996 // Check that the receiver isn't a smi.
1997 if (check != NUMBER_CHECK) {
1998 __ JumpIfSmi(reg, miss);
1999 }
2000
2001 // Make sure that it's okay not to patch the on stack receiver
2002 // unless we're doing a receiver map check.
2003 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
2004
2005 Counters* counters = isolate()->counters();
2006 switch (check) {
2007 case RECEIVER_MAP_CHECK:
2008 __ IncrementCounter(counters->call_const(), 1);
2009
2010 // Check that the maps haven't changed.
2011 reg = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), reg, holder,
2012 rbx, rax, rdi, name, miss);
2013 break;
2014
2015 case STRING_CHECK: {
2016 // Check that the object is a string.
2017 __ CmpObjectType(reg, FIRST_NONSTRING_TYPE, rax);
2018 __ j(above_equal, miss);
2019 // Check that the maps starting from the prototype haven't changed.
2020 GenerateDirectLoadGlobalFunctionPrototype(
2021 masm(), Context::STRING_FUNCTION_INDEX, rax, miss);
2022 break;
2023 }
2024 case SYMBOL_CHECK: {
2025 // Check that the object is a symbol.
2026 __ CmpObjectType(reg, SYMBOL_TYPE, rax);
2027 __ j(not_equal, miss);
2028 // Check that the maps starting from the prototype haven't changed.
2029 GenerateDirectLoadGlobalFunctionPrototype(
2030 masm(), Context::SYMBOL_FUNCTION_INDEX, rax, miss);
2031 break;
2032 }
2033 case NUMBER_CHECK: {
2034 Label fast;
2035 // Check that the object is a smi or a heap number.
2036 __ JumpIfSmi(reg, &fast);
2037 __ CmpObjectType(reg, HEAP_NUMBER_TYPE, rax);
2038 __ j(not_equal, miss);
2039 __ bind(&fast);
2040 // Check that the maps starting from the prototype haven't changed.
2041 GenerateDirectLoadGlobalFunctionPrototype(
2042 masm(), Context::NUMBER_FUNCTION_INDEX, rax, miss);
2043 break;
2044 }
2045 case BOOLEAN_CHECK: {
2046 GenerateBooleanCheck(reg, miss);
2047 // Check that the maps starting from the prototype haven't changed.
2048 GenerateDirectLoadGlobalFunctionPrototype(
2049 masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, miss);
2050 break;
2051 }
2052 }
2053
2054 if (check != RECEIVER_MAP_CHECK) {
2055 Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
2056 reg = CheckPrototypes(
2057 IC::CurrentTypeOf(prototype, isolate()),
2058 rax, holder, rbx, rdx, rdi, name, miss);
2059 }
2060
2061 return reg;
2062 }
2063
2064
2065 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
2066 Register function,
2067 Label* miss) {
2068 // Check that the function really is a function.
2069 GenerateFunctionCheck(function, rbx, miss);
2070
2071 if (!function.is(rdi)) __ movp(rdi, function);
2072 PatchImplicitReceiver(object);
2073
2074 // Invoke the function.
2075 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, NullCallWrapper());
2076 }
2077
2078
2079 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
2080 Handle<JSObject> holder,
2081 Handle<Name> name) {
2082 Label miss;
2083 GenerateNameCheck(name, &miss);
2084
2085 LookupResult lookup(isolate());
2086 LookupPostInterceptor(holder, name, &lookup);
2087
2088 // Get the receiver from the stack.
2089 StackArgumentsAccessor args(rsp, arguments());
2090 __ movp(rdx, args.GetReceiverOperand());
2091
2092 CallInterceptorCompiler compiler(this, arguments(), rcx);
2093 compiler.Compile(masm(), object, holder, name, &lookup, rdx, rbx, rdi, rax,
2094 &miss);
2095
2096 // Restore receiver.
2097 __ movp(rdx, args.GetReceiverOperand());
2098
2099 GenerateJumpFunction(object, rax, &miss);
2100
2101 HandlerFrontendFooter(&miss);
2102
2103 // Return the generated code.
2104 return GetCode(Code::FAST, name);
2105 }
2106
2107
2108 Handle<Code> CallStubCompiler::CompileCallGlobal(
2109 Handle<JSObject> object,
2110 Handle<GlobalObject> holder,
2111 Handle<PropertyCell> cell,
2112 Handle<JSFunction> function,
2113 Handle<Name> name) {
2114 if (HasCustomCallGenerator(function)) {
2115 Handle<Code> code = CompileCustomCall(
2116 object, holder, cell, function, Handle<String>::cast(name),
2117 Code::NORMAL);
2118 // A null handle means bail out to the regular compiler code below.
2119 if (!code.is_null()) return code;
2120 }
2121
2122 Label miss;
2123 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
2124 // Potentially loads a closure that matches the shared function info of the
2125 // function, rather than function.
2126 GenerateLoadFunctionFromCell(cell, function, &miss);
2127 Counters* counters = isolate()->counters();
2128 __ IncrementCounter(counters->call_global_inline(), 1);
2129 GenerateJumpFunction(object, rdi, function);
2130 HandlerFrontendFooter(&miss);
2131
2132 // Return the generated code.
2133 return GetCode(Code::NORMAL, name);
2134 }
2135
2136
2137 Handle<Code> StoreStubCompiler::CompileStoreCallback( 1124 Handle<Code> StoreStubCompiler::CompileStoreCallback(
2138 Handle<JSObject> object, 1125 Handle<JSObject> object,
2139 Handle<JSObject> holder, 1126 Handle<JSObject> holder,
2140 Handle<Name> name, 1127 Handle<Name> name,
2141 Handle<ExecutableAccessorInfo> callback) { 1128 Handle<ExecutableAccessorInfo> callback) {
2142 Register holder_reg = HandlerFrontend( 1129 Register holder_reg = HandlerFrontend(
2143 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); 1130 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name);
2144 1131
2145 __ PopReturnAddressTo(scratch1()); 1132 __ PopReturnAddressTo(scratch1());
2146 __ push(receiver()); 1133 __ push(receiver());
2147 __ push(holder_reg); 1134 __ push(holder_reg);
2148 __ Push(callback); // callback info 1135 __ Push(callback); // callback info
2149 __ Push(name); 1136 __ Push(name);
2150 __ push(value()); 1137 __ push(value());
2151 __ PushReturnAddressFrom(scratch1()); 1138 __ PushReturnAddressFrom(scratch1());
2152 1139
2153 // Do tail-call to the runtime system. 1140 // Do tail-call to the runtime system.
2154 ExternalReference store_callback_property = 1141 ExternalReference store_callback_property =
2155 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); 1142 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate());
2156 __ TailCallExternalReference(store_callback_property, 5, 1); 1143 __ TailCallExternalReference(store_callback_property, 5, 1);
2157 1144
2158 // Return the generated code. 1145 // Return the generated code.
2159 return GetCode(kind(), Code::FAST, name); 1146 return GetCode(kind(), Code::FAST, name);
2160 } 1147 }
2161 1148
2162 1149
2163 Handle<Code> StoreStubCompiler::CompileStoreCallback(
2164 Handle<JSObject> object,
2165 Handle<JSObject> holder,
2166 Handle<Name> name,
2167 const CallOptimization& call_optimization) {
2168 HandlerFrontend(IC::CurrentTypeOf(object, isolate()),
2169 receiver(), holder, name);
2170
2171 Register values[] = { value() };
2172 GenerateFastApiCall(
2173 masm(), call_optimization, receiver(), scratch1(),
2174 scratch2(), this->name(), 1, values);
2175
2176 // Return the generated code.
2177 return GetCode(kind(), Code::FAST, name);
2178 }
2179
2180
2181 #undef __ 1150 #undef __
2182 #define __ ACCESS_MASM(masm) 1151 #define __ ACCESS_MASM(masm)
2183 1152
2184 1153
2185 void StoreStubCompiler::GenerateStoreViaSetter( 1154 void StoreStubCompiler::GenerateStoreViaSetter(
2186 MacroAssembler* masm, 1155 MacroAssembler* masm,
1156 Handle<HeapType> type,
2187 Handle<JSFunction> setter) { 1157 Handle<JSFunction> setter) {
2188 // ----------- S t a t e ------------- 1158 // ----------- S t a t e -------------
2189 // -- rax : value 1159 // -- rax : value
2190 // -- rcx : name 1160 // -- rcx : name
2191 // -- rdx : receiver 1161 // -- rdx : receiver
2192 // -- rsp[0] : return address 1162 // -- rsp[0] : return address
2193 // ----------------------------------- 1163 // -----------------------------------
2194 { 1164 {
2195 FrameScope scope(masm, StackFrame::INTERNAL); 1165 FrameScope scope(masm, StackFrame::INTERNAL);
1166 Register receiver = rdx;
1167 Register value = rax;
2196 1168
2197 // Save value register, so we can restore it later. 1169 // Save value register, so we can restore it later.
2198 __ push(rax); 1170 __ push(value);
2199 1171
2200 if (!setter.is_null()) { 1172 if (!setter.is_null()) {
2201 // Call the JavaScript setter with receiver and value on the stack. 1173 // Call the JavaScript setter with receiver and value on the stack.
2202 __ push(rdx); 1174 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
2203 __ push(rax); 1175 // Swap in the global receiver.
1176 __ movp(receiver,
1177 FieldOperand(receiver, JSGlobalObject::kGlobalReceiverOffset));
1178 }
1179 __ push(receiver);
1180 __ push(value);
2204 ParameterCount actual(1); 1181 ParameterCount actual(1);
2205 ParameterCount expected(setter); 1182 ParameterCount expected(setter);
2206 __ InvokeFunction(setter, expected, actual, 1183 __ InvokeFunction(setter, expected, actual,
2207 CALL_FUNCTION, NullCallWrapper()); 1184 CALL_FUNCTION, NullCallWrapper());
2208 } else { 1185 } else {
2209 // If we generate a global code snippet for deoptimization only, remember 1186 // If we generate a global code snippet for deoptimization only, remember
2210 // the place to continue after deoptimization. 1187 // the place to continue after deoptimization.
2211 masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset()); 1188 masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset());
2212 } 1189 }
2213 1190
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
2272 __ bind(&miss); 1249 __ bind(&miss);
2273 1250
2274 TailCallBuiltin(masm(), MissBuiltin(kind())); 1251 TailCallBuiltin(masm(), MissBuiltin(kind()));
2275 1252
2276 // Return the generated code. 1253 // Return the generated code.
2277 return GetICCode( 1254 return GetICCode(
2278 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); 1255 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC);
2279 } 1256 }
2280 1257
2281 1258
2282 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<Type> type, 1259 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<HeapType> type,
2283 Handle<JSObject> last, 1260 Handle<JSObject> last,
2284 Handle<Name> name) { 1261 Handle<Name> name) {
2285 NonexistentHandlerFrontend(type, last, name); 1262 NonexistentHandlerFrontend(type, last, name);
2286 1263
2287 // Return undefined if maps of the full prototype chain are still the 1264 // Return undefined if maps of the full prototype chain are still the
2288 // same and no global property with this name contains a value. 1265 // same and no global property with this name contains a value.
2289 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 1266 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
2290 __ ret(0); 1267 __ ret(0);
2291 1268
2292 // Return the generated code. 1269 // Return the generated code.
(...skipping 27 matching lines...) Expand all
2320 static Register registers[] = { rdx, rcx, rax, rbx, rdi, r8 }; 1297 static Register registers[] = { rdx, rcx, rax, rbx, rdi, r8 };
2321 return registers; 1298 return registers;
2322 } 1299 }
2323 1300
2324 1301
2325 #undef __ 1302 #undef __
2326 #define __ ACCESS_MASM(masm) 1303 #define __ ACCESS_MASM(masm)
2327 1304
2328 1305
2329 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, 1306 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm,
1307 Handle<HeapType> type,
2330 Register receiver, 1308 Register receiver,
2331 Handle<JSFunction> getter) { 1309 Handle<JSFunction> getter) {
2332 // ----------- S t a t e ------------- 1310 // ----------- S t a t e -------------
2333 // -- rax : receiver 1311 // -- rax : receiver
2334 // -- rcx : name 1312 // -- rcx : name
2335 // -- rsp[0] : return address 1313 // -- rsp[0] : return address
2336 // ----------------------------------- 1314 // -----------------------------------
2337 { 1315 {
2338 FrameScope scope(masm, StackFrame::INTERNAL); 1316 FrameScope scope(masm, StackFrame::INTERNAL);
2339 1317
2340 if (!getter.is_null()) { 1318 if (!getter.is_null()) {
2341 // Call the JavaScript getter with the receiver on the stack. 1319 // Call the JavaScript getter with the receiver on the stack.
1320 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
1321 // Swap in the global receiver.
1322 __ movp(receiver,
1323 FieldOperand(receiver, JSGlobalObject::kGlobalReceiverOffset));
1324 }
2342 __ push(receiver); 1325 __ push(receiver);
2343 ParameterCount actual(0); 1326 ParameterCount actual(0);
2344 ParameterCount expected(getter); 1327 ParameterCount expected(getter);
2345 __ InvokeFunction(getter, expected, actual, 1328 __ InvokeFunction(getter, expected, actual,
2346 CALL_FUNCTION, NullCallWrapper()); 1329 CALL_FUNCTION, NullCallWrapper());
2347 } else { 1330 } else {
2348 // If we generate a global code snippet for deoptimization only, remember 1331 // If we generate a global code snippet for deoptimization only, remember
2349 // the place to continue after deoptimization. 1332 // the place to continue after deoptimization.
2350 masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset()); 1333 masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset());
2351 } 1334 }
2352 1335
2353 // Restore context register. 1336 // Restore context register.
2354 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1337 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2355 } 1338 }
2356 __ ret(0); 1339 __ ret(0);
2357 } 1340 }
2358 1341
2359 1342
2360 #undef __ 1343 #undef __
2361 #define __ ACCESS_MASM(masm()) 1344 #define __ ACCESS_MASM(masm())
2362 1345
2363 1346
2364 Handle<Code> LoadStubCompiler::CompileLoadGlobal( 1347 Handle<Code> LoadStubCompiler::CompileLoadGlobal(
2365 Handle<Type> type, 1348 Handle<HeapType> type,
2366 Handle<GlobalObject> global, 1349 Handle<GlobalObject> global,
2367 Handle<PropertyCell> cell, 1350 Handle<PropertyCell> cell,
2368 Handle<Name> name, 1351 Handle<Name> name,
2369 bool is_dont_delete) { 1352 bool is_dont_delete) {
2370 Label miss; 1353 Label miss;
2371 // TODO(verwaest): Directly store to rax. Currently we cannot do this, since 1354 // TODO(verwaest): Directly store to rax. Currently we cannot do this, since
2372 // rax is used as receiver(), which we would otherwise clobber before a 1355 // rax is used as receiver(), which we would otherwise clobber before a
2373 // potential miss. 1356 // potential miss.
2374 HandlerFrontendHeader(type, receiver(), global, name, &miss); 1357 HandlerFrontendHeader(type, receiver(), global, name, &miss);
2375 1358
2376 // Get the value from the cell. 1359 // Get the value from the cell.
2377 __ Move(rbx, cell); 1360 __ Move(rbx, cell);
2378 __ movp(rbx, FieldOperand(rbx, PropertyCell::kValueOffset)); 1361 __ movp(rbx, FieldOperand(rbx, PropertyCell::kValueOffset));
2379 1362
2380 // Check for deleted property if property can actually be deleted. 1363 // Check for deleted property if property can actually be deleted.
2381 if (!is_dont_delete) { 1364 if (!is_dont_delete) {
2382 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); 1365 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
2383 __ j(equal, &miss); 1366 __ j(equal, &miss);
2384 } else if (FLAG_debug_code) { 1367 } else if (FLAG_debug_code) {
2385 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); 1368 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
2386 __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); 1369 __ Check(not_equal, kDontDeleteCellsCannotContainTheHole);
2387 } 1370 }
2388 1371
2389 HandlerFrontendFooter(name, &miss);
2390
2391 Counters* counters = isolate()->counters(); 1372 Counters* counters = isolate()->counters();
2392 __ IncrementCounter(counters->named_load_global_stub(), 1); 1373 __ IncrementCounter(counters->named_load_global_stub(), 1);
2393 __ movp(rax, rbx); 1374 __ movp(rax, rbx);
2394 __ ret(0); 1375 __ ret(0);
2395 1376
1377 HandlerFrontendFooter(name, &miss);
1378
2396 // Return the generated code. 1379 // Return the generated code.
2397 return GetCode(kind(), Code::NORMAL, name); 1380 return GetCode(kind(), Code::NORMAL, name);
2398 } 1381 }
2399 1382
2400 1383
2401 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( 1384 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC(
2402 TypeHandleList* types, 1385 TypeHandleList* types,
2403 CodeHandleList* handlers, 1386 CodeHandleList* handlers,
2404 Handle<Name> name, 1387 Handle<Name> name,
2405 Code::StubType type, 1388 Code::StubType type,
2406 IcCheckType check) { 1389 IcCheckType check) {
2407 Label miss; 1390 Label miss;
2408 1391
2409 if (check == PROPERTY && 1392 if (check == PROPERTY &&
2410 (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) { 1393 (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) {
2411 __ Cmp(this->name(), name); 1394 __ Cmp(this->name(), name);
2412 __ j(not_equal, &miss); 1395 __ j(not_equal, &miss);
2413 } 1396 }
2414 1397
2415 Label number_case; 1398 Label number_case;
2416 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; 1399 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss;
2417 __ JumpIfSmi(receiver(), smi_target); 1400 __ JumpIfSmi(receiver(), smi_target);
2418 1401
2419 Register map_reg = scratch1(); 1402 Register map_reg = scratch1();
2420 __ movp(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); 1403 __ movp(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset));
2421 int receiver_count = types->length(); 1404 int receiver_count = types->length();
2422 int number_of_handled_maps = 0; 1405 int number_of_handled_maps = 0;
2423 for (int current = 0; current < receiver_count; ++current) { 1406 for (int current = 0; current < receiver_count; ++current) {
2424 Handle<Type> type = types->at(current); 1407 Handle<HeapType> type = types->at(current);
2425 Handle<Map> map = IC::TypeToMap(*type, isolate()); 1408 Handle<Map> map = IC::TypeToMap(*type, isolate());
2426 if (!map->is_deprecated()) { 1409 if (!map->is_deprecated()) {
2427 number_of_handled_maps++; 1410 number_of_handled_maps++;
2428 // Check map and tail call if there's a match 1411 // Check map and tail call if there's a match
2429 __ Cmp(map_reg, map); 1412 __ Cmp(map_reg, map);
2430 if (type->Is(Type::Number())) { 1413 if (type->Is(HeapType::Number())) {
2431 ASSERT(!number_case.is_unused()); 1414 ASSERT(!number_case.is_unused());
2432 __ bind(&number_case); 1415 __ bind(&number_case);
2433 } 1416 }
2434 __ j(equal, handlers->at(current), RelocInfo::CODE_TARGET); 1417 __ j(equal, handlers->at(current), RelocInfo::CODE_TARGET);
2435 } 1418 }
2436 } 1419 }
2437 ASSERT(number_of_handled_maps > 0); 1420 ASSERT(number_of_handled_maps > 0);
2438 1421
2439 __ bind(&miss); 1422 __ bind(&miss);
2440 TailCallBuiltin(masm(), MissBuiltin(kind())); 1423 TailCallBuiltin(masm(), MissBuiltin(kind()));
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
2490 // ----------------------------------- 1473 // -----------------------------------
2491 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); 1474 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
2492 } 1475 }
2493 1476
2494 1477
2495 #undef __ 1478 #undef __
2496 1479
2497 } } // namespace v8::internal 1480 } } // namespace v8::internal
2498 1481
2499 #endif // V8_TARGET_ARCH_X64 1482 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/macro-assembler-x64.cc ('k') | src/zone-allocator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698