| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 560 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 571 | 571 |
| 572 ExternalReference ref = | 572 ExternalReference ref = |
| 573 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly)); | 573 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly)); |
| 574 __ mov(r0, Operand(5)); | 574 __ mov(r0, Operand(5)); |
| 575 __ mov(r1, Operand(ref)); | 575 __ mov(r1, Operand(ref)); |
| 576 | 576 |
| 577 CEntryStub stub(1); | 577 CEntryStub stub(1); |
| 578 __ CallStub(&stub); | 578 __ CallStub(&stub); |
| 579 } | 579 } |
| 580 | 580 |
| 581 static const int kFastApiCallArguments = 3; |
| 581 | 582 |
| 582 // Reserves space for the extra arguments to FastHandleApiCall in the | 583 // Reserves space for the extra arguments to FastHandleApiCall in the |
| 583 // caller's frame. | 584 // caller's frame. |
| 584 // | 585 // |
| 585 // These arguments are set by CheckPrototypes and GenerateFastApiCall. | 586 // These arguments are set by CheckPrototypes and GenerateFastApiDirectCall. |
| 586 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, | 587 static void ReserveSpaceForFastApiCall(MacroAssembler* masm, |
| 587 Register scratch) { | 588 Register scratch) { |
| 588 __ mov(scratch, Operand(Smi::FromInt(0))); | 589 __ mov(scratch, Operand(Smi::FromInt(0))); |
| 589 __ push(scratch); | 590 for (int i = 0; i < kFastApiCallArguments; i++) { |
| 590 __ push(scratch); | 591 __ push(scratch); |
| 591 __ push(scratch); | 592 } |
| 592 __ push(scratch); | |
| 593 } | 593 } |
| 594 | 594 |
| 595 | 595 |
| 596 // Undoes the effects of ReserveSpaceForFastApiCall. | 596 // Undoes the effects of ReserveSpaceForFastApiCall. |
| 597 static void FreeSpaceForFastApiCall(MacroAssembler* masm) { | 597 static void FreeSpaceForFastApiCall(MacroAssembler* masm) { |
| 598 __ Drop(4); | 598 __ Drop(kFastApiCallArguments); |
| 599 } | 599 } |
| 600 | 600 |
| 601 | 601 |
| 602 // Generates call to FastHandleApiCall builtin. | 602 static MaybeObject* GenerateFastApiDirectCall(MacroAssembler* masm, |
| 603 static void GenerateFastApiCall(MacroAssembler* masm, | 603 const CallOptimization& optimization, |
| 604 const CallOptimization& optimization, | 604 int argc) { |
| 605 int argc) { | 605 // ----------- S t a t e ------------- |
| 606 // -- sp[0] : holder (set by CheckPrototypes) |
| 607 // -- sp[4] : callee js function |
| 608 // -- sp[8] : call data |
| 609 // -- sp[12] : last js argument |
| 610 // -- ... |
| 611 // -- sp[(argc + 3) * 4] : first js argument |
| 612 // -- sp[(argc + 4) * 4] : receiver |
| 613 // ----------------------------------- |
| 606 // Get the function and setup the context. | 614 // Get the function and setup the context. |
| 607 JSFunction* function = optimization.constant_function(); | 615 JSFunction* function = optimization.constant_function(); |
| 608 __ mov(r5, Operand(Handle<JSFunction>(function))); | 616 __ mov(r5, Operand(Handle<JSFunction>(function))); |
| 609 __ ldr(cp, FieldMemOperand(r5, JSFunction::kContextOffset)); | 617 __ ldr(cp, FieldMemOperand(r5, JSFunction::kContextOffset)); |
| 610 | 618 |
| 611 // Pass the additional arguments FastHandleApiCall expects. | 619 // Pass the additional arguments FastHandleApiCall expects. |
| 612 bool info_loaded = false; | |
| 613 Object* callback = optimization.api_call_info()->callback(); | |
| 614 if (HEAP->InNewSpace(callback)) { | |
| 615 info_loaded = true; | |
| 616 __ Move(r0, Handle<CallHandlerInfo>(optimization.api_call_info())); | |
| 617 __ ldr(r7, FieldMemOperand(r0, CallHandlerInfo::kCallbackOffset)); | |
| 618 } else { | |
| 619 __ Move(r7, Handle<Object>(callback)); | |
| 620 } | |
| 621 Object* call_data = optimization.api_call_info()->data(); | 620 Object* call_data = optimization.api_call_info()->data(); |
| 621 Handle<CallHandlerInfo> api_call_info_handle(optimization.api_call_info()); |
| 622 if (HEAP->InNewSpace(call_data)) { | 622 if (HEAP->InNewSpace(call_data)) { |
| 623 if (!info_loaded) { | 623 __ Move(r0, api_call_info_handle); |
| 624 __ Move(r0, Handle<CallHandlerInfo>(optimization.api_call_info())); | |
| 625 } | |
| 626 __ ldr(r6, FieldMemOperand(r0, CallHandlerInfo::kDataOffset)); | 624 __ ldr(r6, FieldMemOperand(r0, CallHandlerInfo::kDataOffset)); |
| 627 } else { | 625 } else { |
| 628 __ Move(r6, Handle<Object>(call_data)); | 626 __ Move(r6, Handle<Object>(call_data)); |
| 629 } | 627 } |
| 628 // Store js function and call data. |
| 629 __ stm(ib, sp, r5.bit() | r6.bit()); |
| 630 | 630 |
| 631 __ add(sp, sp, Operand(1 * kPointerSize)); | 631 // r2 points to call data as expected by Arguments |
| 632 __ stm(ia, sp, r5.bit() | r6.bit() | r7.bit()); | 632 // (refer to layout above). |
| 633 __ sub(sp, sp, Operand(1 * kPointerSize)); | 633 __ add(r2, sp, Operand(2 * kPointerSize)); |
| 634 | 634 |
| 635 // Set the number of arguments. | 635 Object* callback = optimization.api_call_info()->callback(); |
| 636 __ mov(r0, Operand(argc + 4)); | 636 Address api_function_address = v8::ToCData<Address>(callback); |
| 637 ApiFunction fun(api_function_address); |
| 637 | 638 |
| 638 // Jump to the fast api call builtin (tail call). | 639 const int kApiStackSpace = 4; |
| 639 Handle<Code> code = Handle<Code>( | 640 __ EnterExitFrame(false, kApiStackSpace); |
| 640 Isolate::Current()->builtins()->builtin(Builtins::FastHandleApiCall)); | 641 |
| 641 ParameterCount expected(0); | 642 // r0 = v8::Arguments& |
| 642 __ InvokeCode(code, expected, expected, | 643 // Arguments is after the return address. |
| 643 RelocInfo::CODE_TARGET, JUMP_FUNCTION); | 644 __ add(r0, sp, Operand(1 * kPointerSize)); |
| 645 // v8::Arguments::implicit_args = data |
| 646 __ str(r2, MemOperand(r0, 0 * kPointerSize)); |
| 647 // v8::Arguments::values = last argument |
| 648 __ add(ip, r2, Operand(argc * kPointerSize)); |
| 649 __ str(ip, MemOperand(r0, 1 * kPointerSize)); |
| 650 // v8::Arguments::length_ = argc |
| 651 __ mov(ip, Operand(argc)); |
| 652 __ str(ip, MemOperand(r0, 2 * kPointerSize)); |
| 653 // v8::Arguments::is_construct_call = 0 |
| 654 __ mov(ip, Operand(0)); |
| 655 __ str(ip, MemOperand(r0, 3 * kPointerSize)); |
| 656 |
| 657 // Emitting a stub call may try to allocate (if the code is not |
| 658 // already generated). Do not allow the assembler to perform a |
| 659 // garbage collection but instead return the allocation failure |
| 660 // object. |
| 661 MaybeObject* result = masm->TryCallApiFunctionAndReturn( |
| 662 &fun, argc + kFastApiCallArguments + 1); |
| 663 if (result->IsFailure()) { |
| 664 return result; |
| 665 } |
| 666 return HEAP->undefined_value(); |
| 644 } | 667 } |
| 645 | 668 |
| 646 | |
| 647 class CallInterceptorCompiler BASE_EMBEDDED { | 669 class CallInterceptorCompiler BASE_EMBEDDED { |
| 648 public: | 670 public: |
| 649 CallInterceptorCompiler(StubCompiler* stub_compiler, | 671 CallInterceptorCompiler(StubCompiler* stub_compiler, |
| 650 const ParameterCount& arguments, | 672 const ParameterCount& arguments, |
| 651 Register name) | 673 Register name) |
| 652 : stub_compiler_(stub_compiler), | 674 : stub_compiler_(stub_compiler), |
| 653 arguments_(arguments), | 675 arguments_(arguments), |
| 654 name_(name) {} | 676 name_(name) {} |
| 655 | 677 |
| 656 void Compile(MacroAssembler* masm, | 678 MaybeObject* Compile(MacroAssembler* masm, |
| 657 JSObject* object, | 679 JSObject* object, |
| 658 JSObject* holder, | 680 JSObject* holder, |
| 659 String* name, | 681 String* name, |
| 660 LookupResult* lookup, | 682 LookupResult* lookup, |
| 661 Register receiver, | 683 Register receiver, |
| 662 Register scratch1, | 684 Register scratch1, |
| 663 Register scratch2, | 685 Register scratch2, |
| 664 Register scratch3, | 686 Register scratch3, |
| 665 Label* miss) { | 687 Label* miss) { |
| 666 ASSERT(holder->HasNamedInterceptor()); | 688 ASSERT(holder->HasNamedInterceptor()); |
| 667 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); | 689 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| 668 | 690 |
| 669 // Check that the receiver isn't a smi. | 691 // Check that the receiver isn't a smi. |
| 670 __ JumpIfSmi(receiver, miss); | 692 __ JumpIfSmi(receiver, miss); |
| 671 | 693 |
| 672 CallOptimization optimization(lookup); | 694 CallOptimization optimization(lookup); |
| 673 | 695 |
| 674 if (optimization.is_constant_call()) { | 696 if (optimization.is_constant_call()) { |
| 675 CompileCacheable(masm, | 697 return CompileCacheable(masm, |
| 676 object, | 698 object, |
| 677 receiver, | 699 receiver, |
| 678 scratch1, | 700 scratch1, |
| 679 scratch2, | 701 scratch2, |
| 680 scratch3, | 702 scratch3, |
| 681 holder, | 703 holder, |
| 682 lookup, | 704 lookup, |
| 683 name, | 705 name, |
| 684 optimization, | 706 optimization, |
| 685 miss); | 707 miss); |
| 686 } else { | 708 } else { |
| 687 CompileRegular(masm, | 709 CompileRegular(masm, |
| 688 object, | 710 object, |
| 689 receiver, | 711 receiver, |
| 690 scratch1, | 712 scratch1, |
| 691 scratch2, | 713 scratch2, |
| 692 scratch3, | 714 scratch3, |
| 693 name, | 715 name, |
| 694 holder, | 716 holder, |
| 695 miss); | 717 miss); |
| 718 return HEAP->undefined_value(); |
| 696 } | 719 } |
| 697 } | 720 } |
| 698 | 721 |
| 699 private: | 722 private: |
| 700 void CompileCacheable(MacroAssembler* masm, | 723 MaybeObject* CompileCacheable(MacroAssembler* masm, |
| 701 JSObject* object, | 724 JSObject* object, |
| 702 Register receiver, | 725 Register receiver, |
| 703 Register scratch1, | 726 Register scratch1, |
| 704 Register scratch2, | 727 Register scratch2, |
| 705 Register scratch3, | 728 Register scratch3, |
| 706 JSObject* interceptor_holder, | 729 JSObject* interceptor_holder, |
| 707 LookupResult* lookup, | 730 LookupResult* lookup, |
| 708 String* name, | 731 String* name, |
| 709 const CallOptimization& optimization, | 732 const CallOptimization& optimization, |
| 710 Label* miss_label) { | 733 Label* miss_label) { |
| 711 ASSERT(optimization.is_constant_call()); | 734 ASSERT(optimization.is_constant_call()); |
| 712 ASSERT(!lookup->holder()->IsGlobalObject()); | 735 ASSERT(!lookup->holder()->IsGlobalObject()); |
| 713 | 736 |
| 714 int depth1 = kInvalidProtoDepth; | 737 int depth1 = kInvalidProtoDepth; |
| 715 int depth2 = kInvalidProtoDepth; | 738 int depth2 = kInvalidProtoDepth; |
| 716 bool can_do_fast_api_call = false; | 739 bool can_do_fast_api_call = false; |
| 717 if (optimization.is_simple_api_call() && | 740 if (optimization.is_simple_api_call() && |
| 718 !lookup->holder()->IsGlobalObject()) { | 741 !lookup->holder()->IsGlobalObject()) { |
| 719 depth1 = | 742 depth1 = |
| 720 optimization.GetPrototypeDepthOfExpectedType(object, | 743 optimization.GetPrototypeDepthOfExpectedType(object, |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 764 } else { | 787 } else { |
| 765 // CheckPrototypes has a side effect of fetching a 'holder' | 788 // CheckPrototypes has a side effect of fetching a 'holder' |
| 766 // for API (object which is instanceof for the signature). It's | 789 // for API (object which is instanceof for the signature). It's |
| 767 // safe to omit it here, as if present, it should be fetched | 790 // safe to omit it here, as if present, it should be fetched |
| 768 // by the previous CheckPrototypes. | 791 // by the previous CheckPrototypes. |
| 769 ASSERT(depth2 == kInvalidProtoDepth); | 792 ASSERT(depth2 == kInvalidProtoDepth); |
| 770 } | 793 } |
| 771 | 794 |
| 772 // Invoke function. | 795 // Invoke function. |
| 773 if (can_do_fast_api_call) { | 796 if (can_do_fast_api_call) { |
| 774 GenerateFastApiCall(masm, optimization, arguments_.immediate()); | 797 MaybeObject* result = GenerateFastApiDirectCall(masm, |
| 798 optimization, |
| 799 arguments_.immediate()); |
| 800 if (result->IsFailure()) return result; |
| 775 } else { | 801 } else { |
| 776 __ InvokeFunction(optimization.constant_function(), arguments_, | 802 __ InvokeFunction(optimization.constant_function(), arguments_, |
| 777 JUMP_FUNCTION); | 803 JUMP_FUNCTION); |
| 778 } | 804 } |
| 779 | 805 |
| 780 // Deferred code for fast API call case---clean preallocated space. | 806 // Deferred code for fast API call case---clean preallocated space. |
| 781 if (can_do_fast_api_call) { | 807 if (can_do_fast_api_call) { |
| 782 __ bind(&miss_cleanup); | 808 __ bind(&miss_cleanup); |
| 783 FreeSpaceForFastApiCall(masm); | 809 FreeSpaceForFastApiCall(masm); |
| 784 __ b(miss_label); | 810 __ b(miss_label); |
| 785 } | 811 } |
| 786 | 812 |
| 787 // Invoke a regular function. | 813 // Invoke a regular function. |
| 788 __ bind(®ular_invoke); | 814 __ bind(®ular_invoke); |
| 789 if (can_do_fast_api_call) { | 815 if (can_do_fast_api_call) { |
| 790 FreeSpaceForFastApiCall(masm); | 816 FreeSpaceForFastApiCall(masm); |
| 791 } | 817 } |
| 818 |
| 819 return HEAP->undefined_value(); |
| 792 } | 820 } |
| 793 | 821 |
| 794 void CompileRegular(MacroAssembler* masm, | 822 void CompileRegular(MacroAssembler* masm, |
| 795 JSObject* object, | 823 JSObject* object, |
| 796 Register receiver, | 824 Register receiver, |
| 797 Register scratch1, | 825 Register scratch1, |
| 798 Register scratch2, | 826 Register scratch2, |
| 799 Register scratch3, | 827 Register scratch3, |
| 800 String* name, | 828 String* name, |
| 801 JSObject* interceptor_holder, | 829 JSObject* interceptor_holder, |
| (...skipping 1251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2053 | 2081 |
| 2054 // Backup FPSCR. | 2082 // Backup FPSCR. |
| 2055 __ vmrs(r3); | 2083 __ vmrs(r3); |
| 2056 // Set custom FPCSR: | 2084 // Set custom FPCSR: |
| 2057 // - Set rounding mode to "Round towards Minus Infinity" | 2085 // - Set rounding mode to "Round towards Minus Infinity" |
| 2058 // (ie bits [23:22] = 0b10). | 2086 // (ie bits [23:22] = 0b10). |
| 2059 // - Clear vfp cumulative exception flags (bits [3:0]). | 2087 // - Clear vfp cumulative exception flags (bits [3:0]). |
| 2060 // - Make sure Flush-to-zero mode control bit is unset (bit 22). | 2088 // - Make sure Flush-to-zero mode control bit is unset (bit 22). |
| 2061 __ bic(r9, r3, | 2089 __ bic(r9, r3, |
| 2062 Operand(kVFPExceptionMask | kVFPRoundingModeMask | kVFPFlushToZeroMask)); | 2090 Operand(kVFPExceptionMask | kVFPRoundingModeMask | kVFPFlushToZeroMask)); |
| 2063 __ orr(r9, r9, Operand(kVFPRoundToMinusInfinityBits)); | 2091 __ orr(r9, r9, Operand(kRoundToMinusInf)); |
| 2064 __ vmsr(r9); | 2092 __ vmsr(r9); |
| 2065 | 2093 |
| 2066 // Convert the argument to an integer. | 2094 // Convert the argument to an integer. |
| 2067 __ vcvt_s32_f64(s0, d1, Assembler::FPSCRRounding, al); | 2095 __ vcvt_s32_f64(s0, d1, kFPSCRRounding); |
| 2068 | 2096 |
| 2069 // Use vcvt latency to start checking for special cases. | 2097 // Use vcvt latency to start checking for special cases. |
| 2070 // Get the argument exponent and clear the sign bit. | 2098 // Get the argument exponent and clear the sign bit. |
| 2071 __ bic(r6, r5, Operand(HeapNumber::kSignMask)); | 2099 __ bic(r6, r5, Operand(HeapNumber::kSignMask)); |
| 2072 __ mov(r6, Operand(r6, LSR, HeapNumber::kMantissaBitsInTopWord)); | 2100 __ mov(r6, Operand(r6, LSR, HeapNumber::kMantissaBitsInTopWord)); |
| 2073 | 2101 |
| 2074 // Retrieve FPSCR and check for vfp exceptions. | 2102 // Retrieve FPSCR and check for vfp exceptions. |
| 2075 __ vmrs(r9); | 2103 __ vmrs(r9); |
| 2076 __ tst(r9, Operand(kVFPExceptionMask)); | 2104 __ tst(r9, Operand(kVFPExceptionMask)); |
| 2077 __ b(&no_vfp_exception, eq); | 2105 __ b(&no_vfp_exception, eq); |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2366 r1, r4, name, &miss); | 2394 r1, r4, name, &miss); |
| 2367 } | 2395 } |
| 2368 break; | 2396 break; |
| 2369 } | 2397 } |
| 2370 | 2398 |
| 2371 default: | 2399 default: |
| 2372 UNREACHABLE(); | 2400 UNREACHABLE(); |
| 2373 } | 2401 } |
| 2374 | 2402 |
| 2375 if (depth != kInvalidProtoDepth) { | 2403 if (depth != kInvalidProtoDepth) { |
| 2376 GenerateFastApiCall(masm(), optimization, argc); | 2404 MaybeObject* result = GenerateFastApiDirectCall(masm(), optimization, argc); |
| 2405 if (result->IsFailure()) return result; |
| 2377 } else { | 2406 } else { |
| 2378 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); | 2407 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); |
| 2379 } | 2408 } |
| 2380 | 2409 |
| 2381 // Handle call cache miss. | 2410 // Handle call cache miss. |
| 2382 __ bind(&miss); | 2411 __ bind(&miss); |
| 2383 if (depth != kInvalidProtoDepth) { | 2412 if (depth != kInvalidProtoDepth) { |
| 2384 FreeSpaceForFastApiCall(masm()); | 2413 FreeSpaceForFastApiCall(masm()); |
| 2385 } | 2414 } |
| 2386 | 2415 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2410 // Get the number of arguments. | 2439 // Get the number of arguments. |
| 2411 const int argc = arguments().immediate(); | 2440 const int argc = arguments().immediate(); |
| 2412 | 2441 |
| 2413 LookupResult lookup; | 2442 LookupResult lookup; |
| 2414 LookupPostInterceptor(holder, name, &lookup); | 2443 LookupPostInterceptor(holder, name, &lookup); |
| 2415 | 2444 |
| 2416 // Get the receiver from the stack. | 2445 // Get the receiver from the stack. |
| 2417 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 2446 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
| 2418 | 2447 |
| 2419 CallInterceptorCompiler compiler(this, arguments(), r2); | 2448 CallInterceptorCompiler compiler(this, arguments(), r2); |
| 2420 compiler.Compile(masm(), | 2449 MaybeObject* result = compiler.Compile(masm(), |
| 2421 object, | 2450 object, |
| 2422 holder, | 2451 holder, |
| 2423 name, | 2452 name, |
| 2424 &lookup, | 2453 &lookup, |
| 2425 r1, | 2454 r1, |
| 2426 r3, | 2455 r3, |
| 2427 r4, | 2456 r4, |
| 2428 r0, | 2457 r0, |
| 2429 &miss); | 2458 &miss); |
| 2459 if (result->IsFailure()) { |
| 2460 return result; |
| 2461 } |
| 2430 | 2462 |
| 2431 // Move returned value, the function to call, to r1. | 2463 // Move returned value, the function to call, to r1. |
| 2432 __ mov(r1, r0); | 2464 __ mov(r1, r0); |
| 2433 // Restore receiver. | 2465 // Restore receiver. |
| 2434 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); | 2466 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); |
| 2435 | 2467 |
| 2436 GenerateCallFunction(masm(), object, arguments(), &miss); | 2468 GenerateCallFunction(masm(), object, arguments(), &miss); |
| 2437 | 2469 |
| 2438 // Handle call cache miss. | 2470 // Handle call cache miss. |
| 2439 __ bind(&miss); | 2471 __ bind(&miss); |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2650 // -- r2 : name | 2682 // -- r2 : name |
| 2651 // -- lr : return address | 2683 // -- lr : return address |
| 2652 // ----------------------------------- | 2684 // ----------------------------------- |
| 2653 Label miss; | 2685 Label miss; |
| 2654 | 2686 |
| 2655 // Check that the map of the global has not changed. | 2687 // Check that the map of the global has not changed. |
| 2656 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); | 2688 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| 2657 __ cmp(r3, Operand(Handle<Map>(object->map()))); | 2689 __ cmp(r3, Operand(Handle<Map>(object->map()))); |
| 2658 __ b(ne, &miss); | 2690 __ b(ne, &miss); |
| 2659 | 2691 |
| 2692 // Check that the value in the cell is not the hole. If it is, this |
| 2693 // cell could have been deleted and reintroducing the global needs |
| 2694 // to update the property details in the property dictionary of the |
| 2695 // global object. We bail out to the runtime system to do that. |
| 2696 __ mov(r4, Operand(Handle<JSGlobalPropertyCell>(cell))); |
| 2697 __ LoadRoot(r5, Heap::kTheHoleValueRootIndex); |
| 2698 __ ldr(r6, FieldMemOperand(r4, JSGlobalPropertyCell::kValueOffset)); |
| 2699 __ cmp(r5, r6); |
| 2700 __ b(eq, &miss); |
| 2701 |
| 2660 // Store the value in the cell. | 2702 // Store the value in the cell. |
| 2661 __ mov(r2, Operand(Handle<JSGlobalPropertyCell>(cell))); | 2703 __ str(r0, FieldMemOperand(r4, JSGlobalPropertyCell::kValueOffset)); |
| 2662 __ str(r0, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset)); | |
| 2663 | 2704 |
| 2664 __ IncrementCounter(COUNTERS->named_store_global_inline(), 1, r4, r3); | 2705 __ IncrementCounter(COUNTERS->named_store_global_inline(), 1, r4, r3); |
| 2665 __ Ret(); | 2706 __ Ret(); |
| 2666 | 2707 |
| 2667 // Handle store cache miss. | 2708 // Handle store cache miss. |
| 2668 __ bind(&miss); | 2709 __ bind(&miss); |
| 2669 __ IncrementCounter(COUNTERS->named_store_global_inline_miss(), 1, r4, r3); | 2710 __ IncrementCounter(COUNTERS->named_store_global_inline_miss(), 1, r4, r3); |
| 2670 Handle<Code> ic(Isolate::Current()->builtins()->builtin( | 2711 Handle<Code> ic(Isolate::Current()->builtins()->builtin( |
| 2671 Builtins::StoreIC_Miss)); | 2712 Builtins::StoreIC_Miss)); |
| 2672 __ Jump(ic, RelocInfo::CODE_TARGET); | 2713 __ Jump(ic, RelocInfo::CODE_TARGET); |
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3080 __ Ret(); | 3121 __ Ret(); |
| 3081 | 3122 |
| 3082 __ bind(&miss); | 3123 __ bind(&miss); |
| 3083 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3124 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3084 | 3125 |
| 3085 // Return the generated code. | 3126 // Return the generated code. |
| 3086 return GetCode(NORMAL, NULL); | 3127 return GetCode(NORMAL, NULL); |
| 3087 } | 3128 } |
| 3088 | 3129 |
| 3089 | 3130 |
| 3131 MaybeObject* KeyedLoadStubCompiler::CompileLoadPixelArray(JSObject* receiver) { |
| 3132 // ----------- S t a t e ------------- |
| 3133 // -- lr : return address |
| 3134 // -- r0 : key |
| 3135 // -- r1 : receiver |
| 3136 // ----------------------------------- |
| 3137 Label miss; |
| 3138 |
| 3139 // Check that the map matches. |
| 3140 __ CheckMap(r1, r2, Handle<Map>(receiver->map()), &miss, false); |
| 3141 |
| 3142 GenerateFastPixelArrayLoad(masm(), |
| 3143 r1, |
| 3144 r0, |
| 3145 r2, |
| 3146 r3, |
| 3147 r4, |
| 3148 r5, |
| 3149 r0, |
| 3150 &miss, |
| 3151 &miss, |
| 3152 &miss); |
| 3153 |
| 3154 __ bind(&miss); |
| 3155 Handle<Code> ic(Isolate::Current()->builtins()->builtin( |
| 3156 Builtins::KeyedLoadIC_Miss)); |
| 3157 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 3158 |
| 3159 // Return the generated code. |
| 3160 return GetCode(NORMAL, NULL); |
| 3161 } |
| 3162 |
| 3163 |
| 3090 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, | 3164 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, |
| 3091 int index, | 3165 int index, |
| 3092 Map* transition, | 3166 Map* transition, |
| 3093 String* name) { | 3167 String* name) { |
| 3094 // ----------- S t a t e ------------- | 3168 // ----------- S t a t e ------------- |
| 3095 // -- r0 : value | 3169 // -- r0 : value |
| 3096 // -- r1 : name | 3170 // -- r1 : name |
| 3097 // -- r2 : receiver | 3171 // -- r2 : receiver |
| 3098 // -- lr : return address | 3172 // -- lr : return address |
| 3099 // ----------------------------------- | 3173 // ----------------------------------- |
| (...skipping 660 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3760 __ sub(r5, value, Operand(kHeapObjectTag)); | 3834 __ sub(r5, value, Operand(kHeapObjectTag)); |
| 3761 __ vldr(d0, r5, HeapNumber::kValueOffset); | 3835 __ vldr(d0, r5, HeapNumber::kValueOffset); |
| 3762 | 3836 |
| 3763 __ Sbfx(r6, r6, HeapNumber::kExponentShift, HeapNumber::kExponentBits); | 3837 __ Sbfx(r6, r6, HeapNumber::kExponentShift, HeapNumber::kExponentBits); |
| 3764 // NaNs and Infinities have all-one exponents so they sign extend to -1. | 3838 // NaNs and Infinities have all-one exponents so they sign extend to -1. |
| 3765 __ cmp(r6, Operand(-1)); | 3839 __ cmp(r6, Operand(-1)); |
| 3766 __ mov(r5, Operand(0), LeaveCC, eq); | 3840 __ mov(r5, Operand(0), LeaveCC, eq); |
| 3767 | 3841 |
| 3768 // Not infinity or NaN simply convert to int. | 3842 // Not infinity or NaN simply convert to int. |
| 3769 if (IsElementTypeSigned(array_type)) { | 3843 if (IsElementTypeSigned(array_type)) { |
| 3770 __ vcvt_s32_f64(s0, d0, Assembler::RoundToZero, ne); | 3844 __ vcvt_s32_f64(s0, d0, kDefaultRoundToZero, ne); |
| 3771 } else { | 3845 } else { |
| 3772 __ vcvt_u32_f64(s0, d0, Assembler::RoundToZero, ne); | 3846 __ vcvt_u32_f64(s0, d0, kDefaultRoundToZero, ne); |
| 3773 } | 3847 } |
| 3774 __ vmov(r5, s0, ne); | 3848 __ vmov(r5, s0, ne); |
| 3775 | 3849 |
| 3776 switch (array_type) { | 3850 switch (array_type) { |
| 3777 case kExternalByteArray: | 3851 case kExternalByteArray: |
| 3778 case kExternalUnsignedByteArray: | 3852 case kExternalUnsignedByteArray: |
| 3779 __ strb(r5, MemOperand(r3, r4, LSL, 0)); | 3853 __ strb(r5, MemOperand(r3, r4, LSL, 0)); |
| 3780 break; | 3854 break; |
| 3781 case kExternalShortArray: | 3855 case kExternalShortArray: |
| 3782 case kExternalUnsignedShortArray: | 3856 case kExternalUnsignedShortArray: |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3937 | 4011 |
| 3938 return GetCode(flags); | 4012 return GetCode(flags); |
| 3939 } | 4013 } |
| 3940 | 4014 |
| 3941 | 4015 |
| 3942 #undef __ | 4016 #undef __ |
| 3943 | 4017 |
| 3944 } } // namespace v8::internal | 4018 } } // namespace v8::internal |
| 3945 | 4019 |
| 3946 #endif // V8_TARGET_ARCH_ARM | 4020 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |