| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 // Bail out if the receiver has a named interceptor or requires access checks. | 119 // Bail out if the receiver has a named interceptor or requires access checks. |
| 120 Register map = scratch1; | 120 Register map = scratch1; |
| 121 __ lw(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 121 __ lw(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 122 __ lbu(scratch0, FieldMemOperand(map, Map::kBitFieldOffset)); | 122 __ lbu(scratch0, FieldMemOperand(map, Map::kBitFieldOffset)); |
| 123 __ And(at, scratch0, Operand(kInterceptorOrAccessCheckNeededMask)); | 123 __ And(at, scratch0, Operand(kInterceptorOrAccessCheckNeededMask)); |
| 124 __ Branch(miss_label, ne, at, Operand(zero_reg)); | 124 __ Branch(miss_label, ne, at, Operand(zero_reg)); |
| 125 | 125 |
| 126 | 126 |
| 127 // Check that receiver is a JSObject. | 127 // Check that receiver is a JSObject. |
| 128 __ lbu(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); | 128 __ lbu(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
| 129 __ Branch(miss_label, lt, scratch0, Operand(FIRST_JS_OBJECT_TYPE)); | 129 __ Branch(miss_label, lt, scratch0, Operand(FIRST_SPEC_OBJECT_TYPE)); |
| 130 | 130 |
| 131 // Load properties array. | 131 // Load properties array. |
| 132 Register properties = scratch0; | 132 Register properties = scratch0; |
| 133 __ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | 133 __ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
| 134 // Check that the properties array is a dictionary. | 134 // Check that the properties array is a dictionary. |
| 135 __ lw(map, FieldMemOperand(properties, HeapObject::kMapOffset)); | 135 __ lw(map, FieldMemOperand(properties, HeapObject::kMapOffset)); |
| 136 Register tmp = properties; | 136 Register tmp = properties; |
| 137 __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); | 137 __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); |
| 138 __ Branch(miss_label, ne, map, Operand(tmp)); | 138 __ Branch(miss_label, ne, map, Operand(tmp)); |
| 139 | 139 |
| (...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 465 } | 465 } |
| 466 | 466 |
| 467 Handle<Code> ic(code); | 467 Handle<Code> ic(code); |
| 468 __ Jump(ic, RelocInfo::CODE_TARGET); | 468 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 469 } | 469 } |
| 470 | 470 |
| 471 | 471 |
| 472 static void GenerateCallFunction(MacroAssembler* masm, | 472 static void GenerateCallFunction(MacroAssembler* masm, |
| 473 Object* object, | 473 Object* object, |
| 474 const ParameterCount& arguments, | 474 const ParameterCount& arguments, |
| 475 Label* miss) { | 475 Label* miss, |
| 476 Code::ExtraICState extra_ic_state) { |
| 476 // ----------- S t a t e ------------- | 477 // ----------- S t a t e ------------- |
| 477 // -- a0: receiver | 478 // -- a0: receiver |
| 478 // -- a1: function to call | 479 // -- a1: function to call |
| 479 // ----------------------------------- | 480 // ----------------------------------- |
| 480 // Check that the function really is a function. | 481 // Check that the function really is a function. |
| 481 __ JumpIfSmi(a1, miss); | 482 __ JumpIfSmi(a1, miss); |
| 482 __ GetObjectType(a1, a3, a3); | 483 __ GetObjectType(a1, a3, a3); |
| 483 __ Branch(miss, ne, a3, Operand(JS_FUNCTION_TYPE)); | 484 __ Branch(miss, ne, a3, Operand(JS_FUNCTION_TYPE)); |
| 484 | 485 |
| 485 // Patch the receiver on the stack with the global proxy if | 486 // Patch the receiver on the stack with the global proxy if |
| 486 // necessary. | 487 // necessary. |
| 487 if (object->IsGlobalObject()) { | 488 if (object->IsGlobalObject()) { |
| 488 __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset)); | 489 __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset)); |
| 489 __ sw(a3, MemOperand(sp, arguments.immediate() * kPointerSize)); | 490 __ sw(a3, MemOperand(sp, arguments.immediate() * kPointerSize)); |
| 490 } | 491 } |
| 491 | 492 |
| 492 // Invoke the function. | 493 // Invoke the function. |
| 493 __ InvokeFunction(a1, arguments, JUMP_FUNCTION); | 494 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state) |
| 495 ? CALL_AS_FUNCTION |
| 496 : CALL_AS_METHOD; |
| 497 __ InvokeFunction(a1, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind); |
| 494 } | 498 } |
| 495 | 499 |
| 496 | 500 |
| 497 static void PushInterceptorArguments(MacroAssembler* masm, | 501 static void PushInterceptorArguments(MacroAssembler* masm, |
| 498 Register receiver, | 502 Register receiver, |
| 499 Register holder, | 503 Register holder, |
| 500 Register name, | 504 Register name, |
| 501 JSObject* holder_obj) { | 505 JSObject* holder_obj) { |
| 502 __ push(name); | 506 __ push(name); |
| 503 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); | 507 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 622 ExternalReference(&fun, | 626 ExternalReference(&fun, |
| 623 ExternalReference::DIRECT_API_CALL, | 627 ExternalReference::DIRECT_API_CALL, |
| 624 masm->isolate()); | 628 masm->isolate()); |
| 625 return masm->TryCallApiFunctionAndReturn(ref, kStackUnwindSpace); | 629 return masm->TryCallApiFunctionAndReturn(ref, kStackUnwindSpace); |
| 626 } | 630 } |
| 627 | 631 |
| 628 class CallInterceptorCompiler BASE_EMBEDDED { | 632 class CallInterceptorCompiler BASE_EMBEDDED { |
| 629 public: | 633 public: |
| 630 CallInterceptorCompiler(StubCompiler* stub_compiler, | 634 CallInterceptorCompiler(StubCompiler* stub_compiler, |
| 631 const ParameterCount& arguments, | 635 const ParameterCount& arguments, |
| 632 Register name) | 636 Register name, |
| 637 Code::ExtraICState extra_ic_state) |
| 633 : stub_compiler_(stub_compiler), | 638 : stub_compiler_(stub_compiler), |
| 634 arguments_(arguments), | 639 arguments_(arguments), |
| 635 name_(name) {} | 640 name_(name), |
| 641 extra_ic_state_(extra_ic_state) {} |
| 636 | 642 |
| 637 MaybeObject* Compile(MacroAssembler* masm, | 643 MaybeObject* Compile(MacroAssembler* masm, |
| 638 JSObject* object, | 644 JSObject* object, |
| 639 JSObject* holder, | 645 JSObject* holder, |
| 640 String* name, | 646 String* name, |
| 641 LookupResult* lookup, | 647 LookupResult* lookup, |
| 642 Register receiver, | 648 Register receiver, |
| 643 Register scratch1, | 649 Register scratch1, |
| 644 Register scratch2, | 650 Register scratch2, |
| 645 Register scratch3, | 651 Register scratch3, |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 753 ASSERT(depth2 == kInvalidProtoDepth); | 759 ASSERT(depth2 == kInvalidProtoDepth); |
| 754 } | 760 } |
| 755 | 761 |
| 756 // Invoke function. | 762 // Invoke function. |
| 757 if (can_do_fast_api_call) { | 763 if (can_do_fast_api_call) { |
| 758 MaybeObject* result = GenerateFastApiDirectCall(masm, | 764 MaybeObject* result = GenerateFastApiDirectCall(masm, |
| 759 optimization, | 765 optimization, |
| 760 arguments_.immediate()); | 766 arguments_.immediate()); |
| 761 if (result->IsFailure()) return result; | 767 if (result->IsFailure()) return result; |
| 762 } else { | 768 } else { |
| 769 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) |
| 770 ? CALL_AS_FUNCTION |
| 771 : CALL_AS_METHOD; |
| 763 __ InvokeFunction(optimization.constant_function(), arguments_, | 772 __ InvokeFunction(optimization.constant_function(), arguments_, |
| 764 JUMP_FUNCTION); | 773 JUMP_FUNCTION, call_kind); |
| 765 } | 774 } |
| 766 | 775 |
| 767 // Deferred code for fast API call case---clean preallocated space. | 776 // Deferred code for fast API call case---clean preallocated space. |
| 768 if (can_do_fast_api_call) { | 777 if (can_do_fast_api_call) { |
| 769 __ bind(&miss_cleanup); | 778 __ bind(&miss_cleanup); |
| 770 FreeSpaceForFastApiCall(masm); | 779 FreeSpaceForFastApiCall(masm); |
| 771 __ Branch(miss_label); | 780 __ Branch(miss_label); |
| 772 } | 781 } |
| 773 | 782 |
| 774 // Invoke a regular function. | 783 // Invoke a regular function. |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 837 __ LeaveInternalFrame(); | 846 __ LeaveInternalFrame(); |
| 838 | 847 |
| 839 // If interceptor returns no-result sentinel, call the constant function. | 848 // If interceptor returns no-result sentinel, call the constant function. |
| 840 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); | 849 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); |
| 841 __ Branch(interceptor_succeeded, ne, v0, Operand(scratch)); | 850 __ Branch(interceptor_succeeded, ne, v0, Operand(scratch)); |
| 842 } | 851 } |
| 843 | 852 |
| 844 StubCompiler* stub_compiler_; | 853 StubCompiler* stub_compiler_; |
| 845 const ParameterCount& arguments_; | 854 const ParameterCount& arguments_; |
| 846 Register name_; | 855 Register name_; |
| 856 Code::ExtraICState extra_ic_state_; |
| 847 }; | 857 }; |
| 848 | 858 |
| 849 | 859 |
| 850 | 860 |
| 851 // Generate code to check that a global property cell is empty. Create | 861 // Generate code to check that a global property cell is empty. Create |
| 852 // the property cell at compilation time if no cell exists for the | 862 // the property cell at compilation time if no cell exists for the |
| 853 // property. | 863 // property. |
| 854 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCell( | 864 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCell( |
| 855 MacroAssembler* masm, | 865 MacroAssembler* masm, |
| 856 GlobalObject* global, | 866 GlobalObject* global, |
| (...skipping 639 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1496 | 1506 |
| 1497 // Get the receiver of the function from the stack into a0. | 1507 // Get the receiver of the function from the stack into a0. |
| 1498 __ lw(a0, MemOperand(sp, argc * kPointerSize)); | 1508 __ lw(a0, MemOperand(sp, argc * kPointerSize)); |
| 1499 // Check that the receiver isn't a smi. | 1509 // Check that the receiver isn't a smi. |
| 1500 __ JumpIfSmi(a0, &miss, t0); | 1510 __ JumpIfSmi(a0, &miss, t0); |
| 1501 | 1511 |
| 1502 // Do the right check and compute the holder register. | 1512 // Do the right check and compute the holder register. |
| 1503 Register reg = CheckPrototypes(object, a0, holder, a1, a3, t0, name, &miss); | 1513 Register reg = CheckPrototypes(object, a0, holder, a1, a3, t0, name, &miss); |
| 1504 GenerateFastPropertyLoad(masm(), a1, reg, holder, index); | 1514 GenerateFastPropertyLoad(masm(), a1, reg, holder, index); |
| 1505 | 1515 |
| 1506 GenerateCallFunction(masm(), object, arguments(), &miss); | 1516 GenerateCallFunction(masm(), object, arguments(), &miss, extra_ic_state_); |
| 1507 | 1517 |
| 1508 // Handle call cache miss. | 1518 // Handle call cache miss. |
| 1509 __ bind(&miss); | 1519 __ bind(&miss); |
| 1510 MaybeObject* maybe_result = GenerateMissBranch(); | 1520 MaybeObject* maybe_result = GenerateMissBranch(); |
| 1511 if (maybe_result->IsFailure()) return maybe_result; | 1521 if (maybe_result->IsFailure()) return maybe_result; |
| 1512 | 1522 |
| 1513 // Return the generated code. | 1523 // Return the generated code. |
| 1514 return GetCode(FIELD, name); | 1524 return GetCode(FIELD, name); |
| 1515 } | 1525 } |
| 1516 | 1526 |
| (...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1994 char_from_code_generator.GenerateFast(masm()); | 2004 char_from_code_generator.GenerateFast(masm()); |
| 1995 __ Drop(argc + 1); | 2005 __ Drop(argc + 1); |
| 1996 __ Ret(); | 2006 __ Ret(); |
| 1997 | 2007 |
| 1998 StubRuntimeCallHelper call_helper; | 2008 StubRuntimeCallHelper call_helper; |
| 1999 char_from_code_generator.GenerateSlow(masm(), call_helper); | 2009 char_from_code_generator.GenerateSlow(masm(), call_helper); |
| 2000 | 2010 |
| 2001 // Tail call the full function. We do not have to patch the receiver | 2011 // Tail call the full function. We do not have to patch the receiver |
| 2002 // because the function makes no use of it. | 2012 // because the function makes no use of it. |
| 2003 __ bind(&slow); | 2013 __ bind(&slow); |
| 2004 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); | 2014 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); |
| 2005 | 2015 |
| 2006 __ bind(&miss); | 2016 __ bind(&miss); |
| 2007 // a2: function name. | 2017 // a2: function name. |
| 2008 MaybeObject* maybe_result = GenerateMissBranch(); | 2018 MaybeObject* maybe_result = GenerateMissBranch(); |
| 2009 if (maybe_result->IsFailure()) return maybe_result; | 2019 if (maybe_result->IsFailure()) return maybe_result; |
| 2010 | 2020 |
| 2011 // Return the generated code. | 2021 // Return the generated code. |
| 2012 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 2022 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); |
| 2013 } | 2023 } |
| 2014 | 2024 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2079 __ floor_w_d(f0, f0); | 2089 __ floor_w_d(f0, f0); |
| 2080 | 2090 |
| 2081 // Start checking for special cases. | 2091 // Start checking for special cases. |
| 2082 // Get the argument exponent and clear the sign bit. | 2092 // Get the argument exponent and clear the sign bit. |
| 2083 __ lw(t1, FieldMemOperand(v0, HeapNumber::kValueOffset + kPointerSize)); | 2093 __ lw(t1, FieldMemOperand(v0, HeapNumber::kValueOffset + kPointerSize)); |
| 2084 __ And(t2, t1, Operand(~HeapNumber::kSignMask)); | 2094 __ And(t2, t1, Operand(~HeapNumber::kSignMask)); |
| 2085 __ srl(t2, t2, HeapNumber::kMantissaBitsInTopWord); | 2095 __ srl(t2, t2, HeapNumber::kMantissaBitsInTopWord); |
| 2086 | 2096 |
| 2087 // Retrieve FCSR and check for fpu errors. | 2097 // Retrieve FCSR and check for fpu errors. |
| 2088 __ cfc1(t5, FCSR); | 2098 __ cfc1(t5, FCSR); |
| 2089 __ srl(t5, t5, kFCSRFlagShift); | 2099 __ And(t5, t5, Operand(kFCSRExceptionFlagMask)); |
| 2090 // Flag 1 marks an inaccurate but still good result so we ignore it. | |
| 2091 __ And(t5, t5, Operand(kFCSRFlagMask ^ 1)); | |
| 2092 __ Branch(&no_fpu_error, eq, t5, Operand(zero_reg)); | 2100 __ Branch(&no_fpu_error, eq, t5, Operand(zero_reg)); |
| 2093 | 2101 |
| 2094 // Check for NaN, Infinity, and -Infinity. | 2102 // Check for NaN, Infinity, and -Infinity. |
| 2095 // They are invariant through a Math.Floor call, so just | 2103 // They are invariant through a Math.Floor call, so just |
| 2096 // return the original argument. | 2104 // return the original argument. |
| 2097 __ Subu(t3, t2, Operand(HeapNumber::kExponentMask | 2105 __ Subu(t3, t2, Operand(HeapNumber::kExponentMask |
| 2098 >> HeapNumber::kMantissaBitsInTopWord)); | 2106 >> HeapNumber::kMantissaBitsInTopWord)); |
| 2099 __ Branch(&restore_fcsr_and_return, eq, t3, Operand(zero_reg)); | 2107 __ Branch(&restore_fcsr_and_return, eq, t3, Operand(zero_reg)); |
| 2100 // We had an overflow or underflow in the conversion. Check if we | 2108 // We had an overflow or underflow in the conversion. Check if we |
| 2101 // have a big exponent. | 2109 // have a big exponent. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 2130 __ Drop(argc + 1); | 2138 __ Drop(argc + 1); |
| 2131 __ Ret(); | 2139 __ Ret(); |
| 2132 | 2140 |
| 2133 __ bind(&wont_fit_smi); | 2141 __ bind(&wont_fit_smi); |
| 2134 // Restore FCSR and fall to slow case. | 2142 // Restore FCSR and fall to slow case. |
| 2135 __ ctc1(a3, FCSR); | 2143 __ ctc1(a3, FCSR); |
| 2136 | 2144 |
| 2137 __ bind(&slow); | 2145 __ bind(&slow); |
| 2138 // Tail call the full function. We do not have to patch the receiver | 2146 // Tail call the full function. We do not have to patch the receiver |
| 2139 // because the function makes no use of it. | 2147 // because the function makes no use of it. |
| 2140 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); | 2148 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); |
| 2141 | 2149 |
| 2142 __ bind(&miss); | 2150 __ bind(&miss); |
| 2143 // a2: function name. | 2151 // a2: function name. |
| 2144 MaybeObject* obj = GenerateMissBranch(); | 2152 MaybeObject* obj = GenerateMissBranch(); |
| 2145 if (obj->IsFailure()) return obj; | 2153 if (obj->IsFailure()) return obj; |
| 2146 | 2154 |
| 2147 // Return the generated code. | 2155 // Return the generated code. |
| 2148 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 2156 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); |
| 2149 } | 2157 } |
| 2150 | 2158 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2232 __ LoadRoot(t2, Heap::kHeapNumberMapRootIndex); | 2240 __ LoadRoot(t2, Heap::kHeapNumberMapRootIndex); |
| 2233 __ AllocateHeapNumber(v0, t0, t1, t2, &slow); | 2241 __ AllocateHeapNumber(v0, t0, t1, t2, &slow); |
| 2234 __ sw(a1, FieldMemOperand(v0, HeapNumber::kExponentOffset)); | 2242 __ sw(a1, FieldMemOperand(v0, HeapNumber::kExponentOffset)); |
| 2235 __ sw(a3, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); | 2243 __ sw(a3, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); |
| 2236 __ Drop(argc + 1); | 2244 __ Drop(argc + 1); |
| 2237 __ Ret(); | 2245 __ Ret(); |
| 2238 | 2246 |
| 2239 // Tail call the full function. We do not have to patch the receiver | 2247 // Tail call the full function. We do not have to patch the receiver |
| 2240 // because the function makes no use of it. | 2248 // because the function makes no use of it. |
| 2241 __ bind(&slow); | 2249 __ bind(&slow); |
| 2242 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); | 2250 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD); |
| 2243 | 2251 |
| 2244 __ bind(&miss); | 2252 __ bind(&miss); |
| 2245 // a2: function name. | 2253 // a2: function name. |
| 2246 MaybeObject* maybe_result = GenerateMissBranch(); | 2254 MaybeObject* maybe_result = GenerateMissBranch(); |
| 2247 if (maybe_result->IsFailure()) return maybe_result; | 2255 if (maybe_result->IsFailure()) return maybe_result; |
| 2248 | 2256 |
| 2249 // Return the generated code. | 2257 // Return the generated code. |
| 2250 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 2258 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); |
| 2251 } | 2259 } |
| 2252 | 2260 |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2418 CheckPrototypes(JSObject::cast(object->GetPrototype()), a0, holder, a3, | 2426 CheckPrototypes(JSObject::cast(object->GetPrototype()), a0, holder, a3, |
| 2419 a1, t0, name, &miss); | 2427 a1, t0, name, &miss); |
| 2420 } | 2428 } |
| 2421 break; | 2429 break; |
| 2422 } | 2430 } |
| 2423 | 2431 |
| 2424 default: | 2432 default: |
| 2425 UNREACHABLE(); | 2433 UNREACHABLE(); |
| 2426 } | 2434 } |
| 2427 | 2435 |
| 2428 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); | 2436 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) |
| 2437 ? CALL_AS_FUNCTION |
| 2438 : CALL_AS_METHOD; |
| 2439 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, call_kind); |
| 2429 | 2440 |
| 2430 // Handle call cache miss. | 2441 // Handle call cache miss. |
| 2431 __ bind(&miss); | 2442 __ bind(&miss); |
| 2432 | 2443 |
| 2433 MaybeObject* maybe_result = GenerateMissBranch(); | 2444 MaybeObject* maybe_result = GenerateMissBranch(); |
| 2434 if (maybe_result->IsFailure()) return maybe_result; | 2445 if (maybe_result->IsFailure()) return maybe_result; |
| 2435 | 2446 |
| 2436 // Return the generated code. | 2447 // Return the generated code. |
| 2437 return GetCode(function); | 2448 return GetCode(function); |
| 2438 } | 2449 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2452 | 2463 |
| 2453 // Get the number of arguments. | 2464 // Get the number of arguments. |
| 2454 const int argc = arguments().immediate(); | 2465 const int argc = arguments().immediate(); |
| 2455 | 2466 |
| 2456 LookupResult lookup; | 2467 LookupResult lookup; |
| 2457 LookupPostInterceptor(holder, name, &lookup); | 2468 LookupPostInterceptor(holder, name, &lookup); |
| 2458 | 2469 |
| 2459 // Get the receiver from the stack. | 2470 // Get the receiver from the stack. |
| 2460 __ lw(a1, MemOperand(sp, argc * kPointerSize)); | 2471 __ lw(a1, MemOperand(sp, argc * kPointerSize)); |
| 2461 | 2472 |
| 2462 CallInterceptorCompiler compiler(this, arguments(), a2); | 2473 CallInterceptorCompiler compiler(this, arguments(), a2, extra_ic_state_); |
| 2463 MaybeObject* result = compiler.Compile(masm(), | 2474 MaybeObject* result = compiler.Compile(masm(), |
| 2464 object, | 2475 object, |
| 2465 holder, | 2476 holder, |
| 2466 name, | 2477 name, |
| 2467 &lookup, | 2478 &lookup, |
| 2468 a1, | 2479 a1, |
| 2469 a3, | 2480 a3, |
| 2470 t0, | 2481 t0, |
| 2471 a0, | 2482 a0, |
| 2472 &miss); | 2483 &miss); |
| 2473 if (result->IsFailure()) { | 2484 if (result->IsFailure()) { |
| 2474 return result; | 2485 return result; |
| 2475 } | 2486 } |
| 2476 | 2487 |
| 2477 // Move returned value, the function to call, to a1. | 2488 // Move returned value, the function to call, to a1. |
| 2478 __ mov(a1, v0); | 2489 __ mov(a1, v0); |
| 2479 // Restore receiver. | 2490 // Restore receiver. |
| 2480 __ lw(a0, MemOperand(sp, argc * kPointerSize)); | 2491 __ lw(a0, MemOperand(sp, argc * kPointerSize)); |
| 2481 | 2492 |
| 2482 GenerateCallFunction(masm(), object, arguments(), &miss); | 2493 GenerateCallFunction(masm(), object, arguments(), &miss, extra_ic_state_); |
| 2483 | 2494 |
| 2484 // Handle call cache miss. | 2495 // Handle call cache miss. |
| 2485 __ bind(&miss); | 2496 __ bind(&miss); |
| 2486 MaybeObject* maybe_result = GenerateMissBranch(); | 2497 MaybeObject* maybe_result = GenerateMissBranch(); |
| 2487 if (maybe_result->IsFailure()) return maybe_result; | 2498 if (maybe_result->IsFailure()) return maybe_result; |
| 2488 | 2499 |
| 2489 // Return the generated code. | 2500 // Return the generated code. |
| 2490 return GetCode(INTERCEPTOR, name); | 2501 return GetCode(INTERCEPTOR, name); |
| 2491 } | 2502 } |
| 2492 | 2503 |
| 2493 | 2504 |
| 2494 MaybeObject* CallStubCompiler::CompileCallGlobal( | 2505 MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object, |
| 2495 JSObject* object, | 2506 GlobalObject* holder, |
| 2496 GlobalObject* holder, | 2507 JSGlobalPropertyCell* cell, |
| 2497 JSGlobalPropertyCell* cell, | 2508 JSFunction* function, |
| 2498 JSFunction* function, | 2509 String* name) { |
| 2499 String* name, | |
| 2500 Code::ExtraICState extra_ic_state) { | |
| 2501 // ----------- S t a t e ------------- | 2510 // ----------- S t a t e ------------- |
| 2502 // -- a2 : name | 2511 // -- a2 : name |
| 2503 // -- ra : return address | 2512 // -- ra : return address |
| 2504 // ----------------------------------- | 2513 // ----------------------------------- |
| 2505 | 2514 |
| 2506 if (HasCustomCallGenerator(function)) { | 2515 if (HasCustomCallGenerator(function)) { |
| 2507 MaybeObject* maybe_result = CompileCustomCall( | 2516 MaybeObject* maybe_result = CompileCustomCall( |
| 2508 object, holder, cell, function, name); | 2517 object, holder, cell, function, name); |
| 2509 Object* result; | 2518 Object* result; |
| 2510 if (!maybe_result->ToObject(&result)) return maybe_result; | 2519 if (!maybe_result->ToObject(&result)) return maybe_result; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2531 | 2540 |
| 2532 // Setup the context (function already in r1). | 2541 // Setup the context (function already in r1). |
| 2533 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); | 2542 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); |
| 2534 | 2543 |
| 2535 // Jump to the cached code (tail call). | 2544 // Jump to the cached code (tail call). |
| 2536 Counters* counters = masm()->isolate()->counters(); | 2545 Counters* counters = masm()->isolate()->counters(); |
| 2537 __ IncrementCounter(counters->call_global_inline(), 1, a3, t0); | 2546 __ IncrementCounter(counters->call_global_inline(), 1, a3, t0); |
| 2538 ASSERT(function->is_compiled()); | 2547 ASSERT(function->is_compiled()); |
| 2539 Handle<Code> code(function->code()); | 2548 Handle<Code> code(function->code()); |
| 2540 ParameterCount expected(function->shared()->formal_parameter_count()); | 2549 ParameterCount expected(function->shared()->formal_parameter_count()); |
| 2541 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state) | 2550 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) |
| 2542 ? CALL_AS_FUNCTION | 2551 ? CALL_AS_FUNCTION |
| 2543 : CALL_AS_METHOD; | 2552 : CALL_AS_METHOD; |
| 2544 if (V8::UseCrankshaft()) { | 2553 if (V8::UseCrankshaft()) { |
| 2545 UNIMPLEMENTED_MIPS(); | 2554 UNIMPLEMENTED_MIPS(); |
| 2546 } else { | 2555 } else { |
| 2547 __ InvokeCode(code, expected, arguments(), RelocInfo::CODE_TARGET, | 2556 __ InvokeCode(code, expected, arguments(), RelocInfo::CODE_TARGET, |
| 2548 JUMP_FUNCTION, call_kind); | 2557 JUMP_FUNCTION, call_kind); |
| 2549 } | 2558 } |
| 2550 | 2559 |
| 2551 // Handle call cache miss. | 2560 // Handle call cache miss. |
| (...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3076 | 3085 |
| 3077 GenerateLoadFunctionPrototype(masm(), a1, a2, a3, &miss); | 3086 GenerateLoadFunctionPrototype(masm(), a1, a2, a3, &miss); |
| 3078 __ bind(&miss); | 3087 __ bind(&miss); |
| 3079 __ DecrementCounter(counters->keyed_load_function_prototype(), 1, a2, a3); | 3088 __ DecrementCounter(counters->keyed_load_function_prototype(), 1, a2, a3); |
| 3080 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3089 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3081 | 3090 |
| 3082 return GetCode(CALLBACKS, name); | 3091 return GetCode(CALLBACKS, name); |
| 3083 } | 3092 } |
| 3084 | 3093 |
| 3085 | 3094 |
| 3086 MaybeObject* KeyedLoadStubCompiler::CompileLoadFastElement(Map* receiver_map) { | 3095 MaybeObject* KeyedLoadStubCompiler::CompileLoadElement(Map* receiver_map) { |
| 3087 // ----------- S t a t e ------------- | 3096 // ----------- S t a t e ------------- |
| 3088 // -- ra : return address | 3097 // -- ra : return address |
| 3089 // -- a0 : key | 3098 // -- a0 : key |
| 3090 // -- a1 : receiver | 3099 // -- a1 : receiver |
| 3091 // ----------------------------------- | 3100 // ----------------------------------- |
| 3092 MaybeObject* maybe_stub = KeyedLoadFastElementStub().TryGetCode(); | |
| 3093 Code* stub; | 3101 Code* stub; |
| 3102 JSObject::ElementsKind elements_kind = receiver_map->elements_kind(); |
| 3103 MaybeObject* maybe_stub = KeyedLoadElementStub(elements_kind).TryGetCode(); |
| 3094 if (!maybe_stub->To(&stub)) return maybe_stub; | 3104 if (!maybe_stub->To(&stub)) return maybe_stub; |
| 3095 __ DispatchMap(a1, | 3105 __ DispatchMap(a1, |
| 3096 a2, | 3106 a2, |
| 3097 Handle<Map>(receiver_map), | 3107 Handle<Map>(receiver_map), |
| 3098 Handle<Code>(stub), | 3108 Handle<Code>(stub), |
| 3099 DO_SMI_CHECK); | 3109 DO_SMI_CHECK); |
| 3100 | 3110 |
| 3101 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); | 3111 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); |
| 3102 __ Jump(ic, RelocInfo::CODE_TARGET); | 3112 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 3103 | 3113 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3165 | 3175 |
| 3166 __ DecrementCounter(counters->keyed_store_field(), 1, a3, t0); | 3176 __ DecrementCounter(counters->keyed_store_field(), 1, a3, t0); |
| 3167 Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss(); | 3177 Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss(); |
| 3168 __ Jump(ic, RelocInfo::CODE_TARGET); | 3178 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 3169 | 3179 |
| 3170 // Return the generated code. | 3180 // Return the generated code. |
| 3171 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); | 3181 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); |
| 3172 } | 3182 } |
| 3173 | 3183 |
| 3174 | 3184 |
| 3175 MaybeObject* KeyedStoreStubCompiler::CompileStoreFastElement( | 3185 MaybeObject* KeyedStoreStubCompiler::CompileStoreElement(Map* receiver_map) { |
| 3176 Map* receiver_map) { | |
| 3177 // ----------- S t a t e ------------- | 3186 // ----------- S t a t e ------------- |
| 3178 // -- a0 : value | 3187 // -- a0 : value |
| 3179 // -- a1 : key | 3188 // -- a1 : key |
| 3180 // -- a2 : receiver | 3189 // -- a2 : receiver |
| 3181 // -- ra : return address | 3190 // -- ra : return address |
| 3182 // -- a3 : scratch | 3191 // -- a3 : scratch |
| 3183 // ----------------------------------- | 3192 // ----------------------------------- |
| 3193 Code* stub; |
| 3194 JSObject::ElementsKind elements_kind = receiver_map->elements_kind(); |
| 3184 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; | 3195 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; |
| 3185 MaybeObject* maybe_stub = | 3196 MaybeObject* maybe_stub = |
| 3186 KeyedStoreFastElementStub(is_js_array).TryGetCode(); | 3197 KeyedStoreElementStub(is_js_array, elements_kind).TryGetCode(); |
| 3187 Code* stub; | |
| 3188 if (!maybe_stub->To(&stub)) return maybe_stub; | 3198 if (!maybe_stub->To(&stub)) return maybe_stub; |
| 3189 __ DispatchMap(a2, | 3199 __ DispatchMap(a2, |
| 3190 a3, | 3200 a3, |
| 3191 Handle<Map>(receiver_map), | 3201 Handle<Map>(receiver_map), |
| 3192 Handle<Code>(stub), | 3202 Handle<Code>(stub), |
| 3193 DO_SMI_CHECK); | 3203 DO_SMI_CHECK); |
| 3194 | 3204 |
| 3195 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 3205 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| 3196 __ Jump(ic, RelocInfo::CODE_TARGET); | 3206 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 3197 | 3207 |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3373 __ bind(&generic_stub_call); | 3383 __ bind(&generic_stub_call); |
| 3374 Handle<Code> generic_construct_stub = | 3384 Handle<Code> generic_construct_stub = |
| 3375 masm()->isolate()->builtins()->JSConstructStubGeneric(); | 3385 masm()->isolate()->builtins()->JSConstructStubGeneric(); |
| 3376 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); | 3386 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); |
| 3377 | 3387 |
| 3378 // Return the generated code. | 3388 // Return the generated code. |
| 3379 return GetCode(); | 3389 return GetCode(); |
| 3380 } | 3390 } |
| 3381 | 3391 |
| 3382 | 3392 |
| 3383 MaybeObject* ExternalArrayLoadStubCompiler::CompileLoad( | |
| 3384 JSObject*receiver, ExternalArrayType array_type) { | |
| 3385 // ----------- S t a t e ------------- | |
| 3386 // -- ra : return address | |
| 3387 // -- a0 : key | |
| 3388 // -- a1 : receiver | |
| 3389 // ----------------------------------- | |
| 3390 MaybeObject* maybe_stub = | |
| 3391 KeyedLoadExternalArrayStub(array_type).TryGetCode(); | |
| 3392 Code* stub; | |
| 3393 if (!maybe_stub->To(&stub)) return maybe_stub; | |
| 3394 __ DispatchMap(a1, | |
| 3395 a2, | |
| 3396 Handle<Map>(receiver->map()), | |
| 3397 Handle<Code>(stub), | |
| 3398 DO_SMI_CHECK); | |
| 3399 | |
| 3400 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); | |
| 3401 __ Jump(ic, RelocInfo::CODE_TARGET); | |
| 3402 | |
| 3403 // Return the generated code. | |
| 3404 return GetCode(); | |
| 3405 } | |
| 3406 | |
| 3407 | |
| 3408 MaybeObject* ExternalArrayStoreStubCompiler::CompileStore( | |
| 3409 JSObject* receiver, ExternalArrayType array_type) { | |
| 3410 // ----------- S t a t e ------------- | |
| 3411 // -- a0 : value | |
| 3412 // -- a1 : name | |
| 3413 // -- a2 : receiver | |
| 3414 // -- ra : return address | |
| 3415 // ----------------------------------- | |
| 3416 MaybeObject* maybe_stub = | |
| 3417 KeyedStoreExternalArrayStub(array_type).TryGetCode(); | |
| 3418 Code* stub; | |
| 3419 if (!maybe_stub->To(&stub)) return maybe_stub; | |
| 3420 __ DispatchMap(a2, | |
| 3421 a3, | |
| 3422 Handle<Map>(receiver->map()), | |
| 3423 Handle<Code>(stub), | |
| 3424 DO_SMI_CHECK); | |
| 3425 | |
| 3426 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | |
| 3427 __ Jump(ic, RelocInfo::CODE_TARGET); | |
| 3428 | |
| 3429 return GetCode(); | |
| 3430 } | |
| 3431 | |
| 3432 | |
| 3433 #undef __ | 3393 #undef __ |
| 3434 #define __ ACCESS_MASM(masm) | 3394 #define __ ACCESS_MASM(masm) |
| 3435 | 3395 |
| 3436 | 3396 |
| 3437 static bool IsElementTypeSigned(ExternalArrayType array_type) { | 3397 void KeyedLoadStubCompiler::GenerateLoadDictionaryElement( |
| 3438 switch (array_type) { | 3398 MacroAssembler* masm) { |
| 3439 case kExternalByteArray: | 3399 // ---------- S t a t e -------------- |
| 3440 case kExternalShortArray: | 3400 // -- ra : return address |
| 3441 case kExternalIntArray: | 3401 // -- a0 : key |
| 3402 // -- a1 : receiver |
| 3403 // ----------------------------------- |
| 3404 Label slow, miss_force_generic; |
| 3405 |
| 3406 Register key = a0; |
| 3407 Register receiver = a1; |
| 3408 |
| 3409 __ JumpIfNotSmi(key, &miss_force_generic); |
| 3410 __ lw(t0, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
| 3411 __ sra(a2, a0, kSmiTagSize); |
| 3412 __ LoadFromNumberDictionary(&slow, t0, a0, v0, a2, a3, t1); |
| 3413 __ Ret(); |
| 3414 |
| 3415 // Slow case, key and receiver still in a0 and a1. |
| 3416 __ bind(&slow); |
| 3417 __ IncrementCounter( |
| 3418 masm->isolate()->counters()->keyed_load_external_array_slow(), |
| 3419 1, a2, a3); |
| 3420 // Entry registers are intact. |
| 3421 // ---------- S t a t e -------------- |
| 3422 // -- ra : return address |
| 3423 // -- a0 : key |
| 3424 // -- a1 : receiver |
| 3425 // ----------------------------------- |
| 3426 Handle<Code> slow_ic = |
| 3427 masm->isolate()->builtins()->KeyedLoadIC_Slow(); |
| 3428 __ Jump(slow_ic, RelocInfo::CODE_TARGET); |
| 3429 |
| 3430 // Miss case, call the runtime. |
| 3431 __ bind(&miss_force_generic); |
| 3432 |
| 3433 // ---------- S t a t e -------------- |
| 3434 // -- ra : return address |
| 3435 // -- a0 : key |
| 3436 // -- a1 : receiver |
| 3437 // ----------------------------------- |
| 3438 |
| 3439 Handle<Code> miss_ic = |
| 3440 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); |
| 3441 __ Jump(miss_ic, RelocInfo::CODE_TARGET); |
| 3442 } |
| 3443 |
| 3444 |
| 3445 static bool IsElementTypeSigned(JSObject::ElementsKind elements_kind) { |
| 3446 switch (elements_kind) { |
| 3447 case JSObject::EXTERNAL_BYTE_ELEMENTS: |
| 3448 case JSObject::EXTERNAL_SHORT_ELEMENTS: |
| 3449 case JSObject::EXTERNAL_INT_ELEMENTS: |
| 3442 return true; | 3450 return true; |
| 3443 | 3451 |
| 3444 case kExternalUnsignedByteArray: | 3452 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3445 case kExternalUnsignedShortArray: | 3453 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3446 case kExternalUnsignedIntArray: | 3454 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 3455 case JSObject::EXTERNAL_PIXEL_ELEMENTS: |
| 3447 return false; | 3456 return false; |
| 3448 | 3457 |
| 3449 default: | 3458 case JSObject::EXTERNAL_FLOAT_ELEMENTS: |
| 3459 case JSObject::EXTERNAL_DOUBLE_ELEMENTS: |
| 3460 case JSObject::FAST_ELEMENTS: |
| 3461 case JSObject::FAST_DOUBLE_ELEMENTS: |
| 3462 case JSObject::DICTIONARY_ELEMENTS: |
| 3463 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS: |
| 3450 UNREACHABLE(); | 3464 UNREACHABLE(); |
| 3451 return false; | 3465 return false; |
| 3452 } | 3466 } |
| 3467 return false; |
| 3453 } | 3468 } |
| 3454 | 3469 |
| 3455 | 3470 |
| 3456 void KeyedLoadStubCompiler::GenerateLoadExternalArray( | 3471 void KeyedLoadStubCompiler::GenerateLoadExternalArray( |
| 3457 MacroAssembler* masm, | 3472 MacroAssembler* masm, |
| 3458 ExternalArrayType array_type) { | 3473 JSObject::ElementsKind elements_kind) { |
| 3459 // ---------- S t a t e -------------- | 3474 // ---------- S t a t e -------------- |
| 3460 // -- ra : return address | 3475 // -- ra : return address |
| 3461 // -- a0 : key | 3476 // -- a0 : key |
| 3462 // -- a1 : receiver | 3477 // -- a1 : receiver |
| 3463 // ----------------------------------- | 3478 // ----------------------------------- |
| 3464 Label miss_force_generic, slow, failed_allocation; | 3479 Label miss_force_generic, slow, failed_allocation; |
| 3465 | 3480 |
| 3466 Register key = a0; | 3481 Register key = a0; |
| 3467 Register receiver = a1; | 3482 Register receiver = a1; |
| 3468 | 3483 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3482 __ Branch(&miss_force_generic, Uless, t1, Operand(t2)); | 3497 __ Branch(&miss_force_generic, Uless, t1, Operand(t2)); |
| 3483 | 3498 |
| 3484 __ lw(a3, FieldMemOperand(a3, ExternalArray::kExternalPointerOffset)); | 3499 __ lw(a3, FieldMemOperand(a3, ExternalArray::kExternalPointerOffset)); |
| 3485 // a3: base pointer of external storage | 3500 // a3: base pointer of external storage |
| 3486 | 3501 |
| 3487 // We are not untagging smi key and instead work with it | 3502 // We are not untagging smi key and instead work with it |
| 3488 // as if it was premultiplied by 2. | 3503 // as if it was premultiplied by 2. |
| 3489 ASSERT((kSmiTag == 0) && (kSmiTagSize == 1)); | 3504 ASSERT((kSmiTag == 0) && (kSmiTagSize == 1)); |
| 3490 | 3505 |
| 3491 Register value = a2; | 3506 Register value = a2; |
| 3492 switch (array_type) { | 3507 switch (elements_kind) { |
| 3493 case kExternalByteArray: | 3508 case JSObject::EXTERNAL_BYTE_ELEMENTS: |
| 3494 __ srl(t2, key, 1); | 3509 __ srl(t2, key, 1); |
| 3495 __ addu(t3, a3, t2); | 3510 __ addu(t3, a3, t2); |
| 3496 __ lb(value, MemOperand(t3, 0)); | 3511 __ lb(value, MemOperand(t3, 0)); |
| 3497 break; | 3512 break; |
| 3498 case kExternalPixelArray: | 3513 case JSObject::EXTERNAL_PIXEL_ELEMENTS: |
| 3499 case kExternalUnsignedByteArray: | 3514 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3500 __ srl(t2, key, 1); | 3515 __ srl(t2, key, 1); |
| 3501 __ addu(t3, a3, t2); | 3516 __ addu(t3, a3, t2); |
| 3502 __ lbu(value, MemOperand(t3, 0)); | 3517 __ lbu(value, MemOperand(t3, 0)); |
| 3503 break; | 3518 break; |
| 3504 case kExternalShortArray: | 3519 case JSObject::EXTERNAL_SHORT_ELEMENTS: |
| 3505 __ addu(t3, a3, key); | 3520 __ addu(t3, a3, key); |
| 3506 __ lh(value, MemOperand(t3, 0)); | 3521 __ lh(value, MemOperand(t3, 0)); |
| 3507 break; | 3522 break; |
| 3508 case kExternalUnsignedShortArray: | 3523 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3509 __ addu(t3, a3, key); | 3524 __ addu(t3, a3, key); |
| 3510 __ lhu(value, MemOperand(t3, 0)); | 3525 __ lhu(value, MemOperand(t3, 0)); |
| 3511 break; | 3526 break; |
| 3512 case kExternalIntArray: | 3527 case JSObject::EXTERNAL_INT_ELEMENTS: |
| 3513 case kExternalUnsignedIntArray: | 3528 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 3514 __ sll(t2, key, 1); | 3529 __ sll(t2, key, 1); |
| 3515 __ addu(t3, a3, t2); | 3530 __ addu(t3, a3, t2); |
| 3516 __ lw(value, MemOperand(t3, 0)); | 3531 __ lw(value, MemOperand(t3, 0)); |
| 3517 break; | 3532 break; |
| 3518 case kExternalFloatArray: | 3533 case JSObject::EXTERNAL_FLOAT_ELEMENTS: |
| 3519 __ sll(t3, t2, 2); | 3534 __ sll(t3, t2, 2); |
| 3520 __ addu(t3, a3, t3); | 3535 __ addu(t3, a3, t3); |
| 3521 if (CpuFeatures::IsSupported(FPU)) { | 3536 if (CpuFeatures::IsSupported(FPU)) { |
| 3522 CpuFeatures::Scope scope(FPU); | 3537 CpuFeatures::Scope scope(FPU); |
| 3523 __ lwc1(f0, MemOperand(t3, 0)); | 3538 __ lwc1(f0, MemOperand(t3, 0)); |
| 3524 } else { | 3539 } else { |
| 3525 __ lw(value, MemOperand(t3, 0)); | 3540 __ lw(value, MemOperand(t3, 0)); |
| 3526 } | 3541 } |
| 3527 break; | 3542 break; |
| 3528 case kExternalDoubleArray: | 3543 case JSObject::EXTERNAL_DOUBLE_ELEMENTS: |
| 3529 __ sll(t2, key, 2); | 3544 __ sll(t2, key, 2); |
| 3530 __ addu(t3, a3, t2); | 3545 __ addu(t3, a3, t2); |
| 3531 if (CpuFeatures::IsSupported(FPU)) { | 3546 if (CpuFeatures::IsSupported(FPU)) { |
| 3532 CpuFeatures::Scope scope(FPU); | 3547 CpuFeatures::Scope scope(FPU); |
| 3533 __ ldc1(f0, MemOperand(t3, 0)); | 3548 __ ldc1(f0, MemOperand(t3, 0)); |
| 3534 } else { | 3549 } else { |
| 3535 // t3: pointer to the beginning of the double we want to load. | 3550 // t3: pointer to the beginning of the double we want to load. |
| 3536 __ lw(a2, MemOperand(t3, 0)); | 3551 __ lw(a2, MemOperand(t3, 0)); |
| 3537 __ lw(a3, MemOperand(t3, Register::kSizeInBytes)); | 3552 __ lw(a3, MemOperand(t3, Register::kSizeInBytes)); |
| 3538 } | 3553 } |
| 3539 break; | 3554 break; |
| 3540 default: | 3555 case JSObject::FAST_ELEMENTS: |
| 3556 case JSObject::FAST_DOUBLE_ELEMENTS: |
| 3557 case JSObject::DICTIONARY_ELEMENTS: |
| 3558 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS: |
| 3541 UNREACHABLE(); | 3559 UNREACHABLE(); |
| 3542 break; | 3560 break; |
| 3543 } | 3561 } |
| 3544 | 3562 |
| 3545 // For integer array types: | 3563 // For integer array types: |
| 3546 // a2: value | 3564 // a2: value |
| 3547 // For float array type: | 3565 // For float array type: |
| 3548 // f0: value (if FPU is supported) | 3566 // f0: value (if FPU is supported) |
| 3549 // a2: value (if FPU is not supported) | 3567 // a2: value (if FPU is not supported) |
| 3550 // For double array type: | 3568 // For double array type: |
| 3551 // f0: value (if FPU is supported) | 3569 // f0: value (if FPU is supported) |
| 3552 // a2/a3: value (if FPU is not supported) | 3570 // a2/a3: value (if FPU is not supported) |
| 3553 | 3571 |
| 3554 if (array_type == kExternalIntArray) { | 3572 if (elements_kind == JSObject::EXTERNAL_INT_ELEMENTS) { |
| 3555 // For the Int and UnsignedInt array types, we need to see whether | 3573 // For the Int and UnsignedInt array types, we need to see whether |
| 3556 // the value can be represented in a Smi. If not, we need to convert | 3574 // the value can be represented in a Smi. If not, we need to convert |
| 3557 // it to a HeapNumber. | 3575 // it to a HeapNumber. |
| 3558 Label box_int; | 3576 Label box_int; |
| 3559 __ Subu(t3, value, Operand(0xC0000000)); // Non-smi value gives neg result. | 3577 __ Subu(t3, value, Operand(0xC0000000)); // Non-smi value gives neg result. |
| 3560 __ Branch(&box_int, lt, t3, Operand(zero_reg)); | 3578 __ Branch(&box_int, lt, t3, Operand(zero_reg)); |
| 3561 // Tag integer as smi and return it. | 3579 // Tag integer as smi and return it. |
| 3562 __ sll(v0, value, kSmiTagSize); | 3580 __ sll(v0, value, kSmiTagSize); |
| 3563 __ Ret(); | 3581 __ Ret(); |
| 3564 | 3582 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 3586 dest, | 3604 dest, |
| 3587 f0, | 3605 f0, |
| 3588 dst1, | 3606 dst1, |
| 3589 dst2, | 3607 dst2, |
| 3590 t1, | 3608 t1, |
| 3591 f2); | 3609 f2); |
| 3592 __ sw(dst1, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); | 3610 __ sw(dst1, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); |
| 3593 __ sw(dst2, FieldMemOperand(v0, HeapNumber::kExponentOffset)); | 3611 __ sw(dst2, FieldMemOperand(v0, HeapNumber::kExponentOffset)); |
| 3594 __ Ret(); | 3612 __ Ret(); |
| 3595 } | 3613 } |
| 3596 } else if (array_type == kExternalUnsignedIntArray) { | 3614 } else if (elements_kind == JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS) { |
| 3597 // The test is different for unsigned int values. Since we need | 3615 // The test is different for unsigned int values. Since we need |
| 3598 // the value to be in the range of a positive smi, we can't | 3616 // the value to be in the range of a positive smi, we can't |
| 3599 // handle either of the top two bits being set in the value. | 3617 // handle either of the top two bits being set in the value. |
| 3600 if (CpuFeatures::IsSupported(FPU)) { | 3618 if (CpuFeatures::IsSupported(FPU)) { |
| 3601 CpuFeatures::Scope scope(FPU); | 3619 CpuFeatures::Scope scope(FPU); |
| 3602 Label pl_box_int; | 3620 Label pl_box_int; |
| 3603 __ And(t2, value, Operand(0xC0000000)); | 3621 __ And(t2, value, Operand(0xC0000000)); |
| 3604 __ Branch(&pl_box_int, ne, t2, Operand(zero_reg)); | 3622 __ Branch(&pl_box_int, ne, t2, Operand(zero_reg)); |
| 3605 | 3623 |
| 3606 // It can fit in an Smi. | 3624 // It can fit in an Smi. |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3657 // space. | 3675 // space. |
| 3658 __ LoadRoot(t6, Heap::kHeapNumberMapRootIndex); | 3676 __ LoadRoot(t6, Heap::kHeapNumberMapRootIndex); |
| 3659 __ AllocateHeapNumber(t2, t3, t5, t6, &slow); | 3677 __ AllocateHeapNumber(t2, t3, t5, t6, &slow); |
| 3660 | 3678 |
| 3661 __ sw(hiword, FieldMemOperand(t2, HeapNumber::kExponentOffset)); | 3679 __ sw(hiword, FieldMemOperand(t2, HeapNumber::kExponentOffset)); |
| 3662 __ sw(loword, FieldMemOperand(t2, HeapNumber::kMantissaOffset)); | 3680 __ sw(loword, FieldMemOperand(t2, HeapNumber::kMantissaOffset)); |
| 3663 | 3681 |
| 3664 __ mov(v0, t2); | 3682 __ mov(v0, t2); |
| 3665 __ Ret(); | 3683 __ Ret(); |
| 3666 } | 3684 } |
| 3667 } else if (array_type == kExternalFloatArray) { | 3685 } else if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) { |
| 3668 // For the floating-point array type, we need to always allocate a | 3686 // For the floating-point array type, we need to always allocate a |
| 3669 // HeapNumber. | 3687 // HeapNumber. |
| 3670 if (CpuFeatures::IsSupported(FPU)) { | 3688 if (CpuFeatures::IsSupported(FPU)) { |
| 3671 CpuFeatures::Scope scope(FPU); | 3689 CpuFeatures::Scope scope(FPU); |
| 3672 // Allocate a HeapNumber for the result. Don't use a0 and a1 as | 3690 // Allocate a HeapNumber for the result. Don't use a0 and a1 as |
| 3673 // AllocateHeapNumber clobbers all registers - also when jumping due to | 3691 // AllocateHeapNumber clobbers all registers - also when jumping due to |
| 3674 // exhausted young space. | 3692 // exhausted young space. |
| 3675 __ LoadRoot(t6, Heap::kHeapNumberMapRootIndex); | 3693 __ LoadRoot(t6, Heap::kHeapNumberMapRootIndex); |
| 3676 __ AllocateHeapNumber(v0, t3, t5, t6, &slow); | 3694 __ AllocateHeapNumber(v0, t3, t5, t6, &slow); |
| 3677 // The float (single) value is already in fpu reg f0 (if we use float). | 3695 // The float (single) value is already in fpu reg f0 (if we use float). |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3724 | 3742 |
| 3725 __ srl(t0, t4, kMantissaShiftForHiWord); | 3743 __ srl(t0, t4, kMantissaShiftForHiWord); |
| 3726 __ or_(a2, a2, t0); | 3744 __ or_(a2, a2, t0); |
| 3727 __ sll(a0, t4, kMantissaShiftForLoWord); | 3745 __ sll(a0, t4, kMantissaShiftForLoWord); |
| 3728 | 3746 |
| 3729 __ sw(a2, FieldMemOperand(v0, HeapNumber::kExponentOffset)); | 3747 __ sw(a2, FieldMemOperand(v0, HeapNumber::kExponentOffset)); |
| 3730 __ sw(a0, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); | 3748 __ sw(a0, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); |
| 3731 __ Ret(); | 3749 __ Ret(); |
| 3732 } | 3750 } |
| 3733 | 3751 |
| 3734 } else if (array_type == kExternalDoubleArray) { | 3752 } else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) { |
| 3735 if (CpuFeatures::IsSupported(FPU)) { | 3753 if (CpuFeatures::IsSupported(FPU)) { |
| 3736 CpuFeatures::Scope scope(FPU); | 3754 CpuFeatures::Scope scope(FPU); |
| 3737 // Allocate a HeapNumber for the result. Don't use a0 and a1 as | 3755 // Allocate a HeapNumber for the result. Don't use a0 and a1 as |
| 3738 // AllocateHeapNumber clobbers all registers - also when jumping due to | 3756 // AllocateHeapNumber clobbers all registers - also when jumping due to |
| 3739 // exhausted young space. | 3757 // exhausted young space. |
| 3740 __ LoadRoot(t6, Heap::kHeapNumberMapRootIndex); | 3758 __ LoadRoot(t6, Heap::kHeapNumberMapRootIndex); |
| 3741 __ AllocateHeapNumber(v0, t3, t5, t6, &slow); | 3759 __ AllocateHeapNumber(v0, t3, t5, t6, &slow); |
| 3742 // The double value is already in f0 | 3760 // The double value is already in f0 |
| 3743 __ sdc1(f0, FieldMemOperand(v0, HeapNumber::kValueOffset)); | 3761 __ sdc1(f0, FieldMemOperand(v0, HeapNumber::kValueOffset)); |
| 3744 __ Ret(); | 3762 __ Ret(); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3778 | 3796 |
| 3779 __ bind(&miss_force_generic); | 3797 __ bind(&miss_force_generic); |
| 3780 Code* stub = masm->isolate()->builtins()->builtin( | 3798 Code* stub = masm->isolate()->builtins()->builtin( |
| 3781 Builtins::kKeyedLoadIC_MissForceGeneric); | 3799 Builtins::kKeyedLoadIC_MissForceGeneric); |
| 3782 __ Jump(Handle<Code>(stub), RelocInfo::CODE_TARGET); | 3800 __ Jump(Handle<Code>(stub), RelocInfo::CODE_TARGET); |
| 3783 } | 3801 } |
| 3784 | 3802 |
| 3785 | 3803 |
| 3786 void KeyedStoreStubCompiler::GenerateStoreExternalArray( | 3804 void KeyedStoreStubCompiler::GenerateStoreExternalArray( |
| 3787 MacroAssembler* masm, | 3805 MacroAssembler* masm, |
| 3788 ExternalArrayType array_type) { | 3806 JSObject::ElementsKind elements_kind) { |
| 3789 // ---------- S t a t e -------------- | 3807 // ---------- S t a t e -------------- |
| 3790 // -- a0 : value | 3808 // -- a0 : value |
| 3791 // -- a1 : key | 3809 // -- a1 : key |
| 3792 // -- a2 : receiver | 3810 // -- a2 : receiver |
| 3793 // -- ra : return address | 3811 // -- ra : return address |
| 3794 // ----------------------------------- | 3812 // ----------------------------------- |
| 3795 | 3813 |
| 3796 Label slow, check_heap_number, miss_force_generic; | 3814 Label slow, check_heap_number, miss_force_generic; |
| 3797 | 3815 |
| 3798 // Register usage. | 3816 // Register usage. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 3813 __ SmiUntag(t0, key); | 3831 __ SmiUntag(t0, key); |
| 3814 __ lw(t1, FieldMemOperand(a3, ExternalArray::kLengthOffset)); | 3832 __ lw(t1, FieldMemOperand(a3, ExternalArray::kLengthOffset)); |
| 3815 // Unsigned comparison catches both negative and too-large values. | 3833 // Unsigned comparison catches both negative and too-large values. |
| 3816 __ Branch(&miss_force_generic, Ugreater_equal, t0, Operand(t1)); | 3834 __ Branch(&miss_force_generic, Ugreater_equal, t0, Operand(t1)); |
| 3817 | 3835 |
| 3818 // Handle both smis and HeapNumbers in the fast path. Go to the | 3836 // Handle both smis and HeapNumbers in the fast path. Go to the |
| 3819 // runtime for all other kinds of values. | 3837 // runtime for all other kinds of values. |
| 3820 // a3: external array. | 3838 // a3: external array. |
| 3821 // t0: key (integer). | 3839 // t0: key (integer). |
| 3822 | 3840 |
| 3823 if (array_type == kExternalPixelArray) { | 3841 if (elements_kind == JSObject::EXTERNAL_PIXEL_ELEMENTS) { |
| 3824 // Double to pixel conversion is only implemented in the runtime for now. | 3842 // Double to pixel conversion is only implemented in the runtime for now. |
| 3825 __ JumpIfNotSmi(value, &slow); | 3843 __ JumpIfNotSmi(value, &slow); |
| 3826 } else { | 3844 } else { |
| 3827 __ JumpIfNotSmi(value, &check_heap_number); | 3845 __ JumpIfNotSmi(value, &check_heap_number); |
| 3828 } | 3846 } |
| 3829 __ SmiUntag(t1, value); | 3847 __ SmiUntag(t1, value); |
| 3830 __ lw(a3, FieldMemOperand(a3, ExternalArray::kExternalPointerOffset)); | 3848 __ lw(a3, FieldMemOperand(a3, ExternalArray::kExternalPointerOffset)); |
| 3831 | 3849 |
| 3832 // a3: base pointer of external storage. | 3850 // a3: base pointer of external storage. |
| 3833 // t0: key (integer). | 3851 // t0: key (integer). |
| 3834 // t1: value (integer). | 3852 // t1: value (integer). |
| 3835 | 3853 |
| 3836 switch (array_type) { | 3854 switch (elements_kind) { |
| 3837 case kExternalPixelArray: { | 3855 case JSObject::EXTERNAL_PIXEL_ELEMENTS: { |
| 3838 // Clamp the value to [0..255]. | 3856 // Clamp the value to [0..255]. |
| 3839 // v0 is used as a scratch register here. | 3857 // v0 is used as a scratch register here. |
| 3840 Label done; | 3858 Label done; |
| 3841 __ li(v0, Operand(255)); | 3859 __ li(v0, Operand(255)); |
| 3842 // Normal branch: nop in delay slot. | 3860 // Normal branch: nop in delay slot. |
| 3843 __ Branch(&done, gt, t1, Operand(v0)); | 3861 __ Branch(&done, gt, t1, Operand(v0)); |
| 3844 // Use delay slot in this branch. | 3862 // Use delay slot in this branch. |
| 3845 __ Branch(USE_DELAY_SLOT, &done, lt, t1, Operand(zero_reg)); | 3863 __ Branch(USE_DELAY_SLOT, &done, lt, t1, Operand(zero_reg)); |
| 3846 __ mov(v0, zero_reg); // In delay slot. | 3864 __ mov(v0, zero_reg); // In delay slot. |
| 3847 __ mov(v0, t1); // Value is in range 0..255. | 3865 __ mov(v0, t1); // Value is in range 0..255. |
| 3848 __ bind(&done); | 3866 __ bind(&done); |
| 3849 __ mov(t1, v0); | 3867 __ mov(t1, v0); |
| 3850 __ addu(t8, a3, t0); | 3868 __ addu(t8, a3, t0); |
| 3851 __ sb(t1, MemOperand(t8, 0)); | 3869 __ sb(t1, MemOperand(t8, 0)); |
| 3852 } | 3870 } |
| 3853 break; | 3871 break; |
| 3854 case kExternalByteArray: | 3872 case JSObject::EXTERNAL_BYTE_ELEMENTS: |
| 3855 case kExternalUnsignedByteArray: | 3873 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3856 __ addu(t8, a3, t0); | 3874 __ addu(t8, a3, t0); |
| 3857 __ sb(t1, MemOperand(t8, 0)); | 3875 __ sb(t1, MemOperand(t8, 0)); |
| 3858 break; | 3876 break; |
| 3859 case kExternalShortArray: | 3877 case JSObject::EXTERNAL_SHORT_ELEMENTS: |
| 3860 case kExternalUnsignedShortArray: | 3878 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3861 __ sll(t8, t0, 1); | 3879 __ sll(t8, t0, 1); |
| 3862 __ addu(t8, a3, t8); | 3880 __ addu(t8, a3, t8); |
| 3863 __ sh(t1, MemOperand(t8, 0)); | 3881 __ sh(t1, MemOperand(t8, 0)); |
| 3864 break; | 3882 break; |
| 3865 case kExternalIntArray: | 3883 case JSObject::EXTERNAL_INT_ELEMENTS: |
| 3866 case kExternalUnsignedIntArray: | 3884 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 3867 __ sll(t8, t0, 2); | 3885 __ sll(t8, t0, 2); |
| 3868 __ addu(t8, a3, t8); | 3886 __ addu(t8, a3, t8); |
| 3869 __ sw(t1, MemOperand(t8, 0)); | 3887 __ sw(t1, MemOperand(t8, 0)); |
| 3870 break; | 3888 break; |
| 3871 case kExternalFloatArray: | 3889 case JSObject::EXTERNAL_FLOAT_ELEMENTS: |
| 3872 // Perform int-to-float conversion and store to memory. | 3890 // Perform int-to-float conversion and store to memory. |
| 3873 StoreIntAsFloat(masm, a3, t0, t1, t2, t3, t4); | 3891 StoreIntAsFloat(masm, a3, t0, t1, t2, t3, t4); |
| 3874 break; | 3892 break; |
| 3875 case kExternalDoubleArray: | 3893 case JSObject::EXTERNAL_DOUBLE_ELEMENTS: |
| 3876 __ sll(t8, t0, 3); | 3894 __ sll(t8, t0, 3); |
| 3877 __ addu(a3, a3, t8); | 3895 __ addu(a3, a3, t8); |
| 3878 // a3: effective address of the double element | 3896 // a3: effective address of the double element |
| 3879 FloatingPointHelper::Destination destination; | 3897 FloatingPointHelper::Destination destination; |
| 3880 if (CpuFeatures::IsSupported(FPU)) { | 3898 if (CpuFeatures::IsSupported(FPU)) { |
| 3881 destination = FloatingPointHelper::kFPURegisters; | 3899 destination = FloatingPointHelper::kFPURegisters; |
| 3882 } else { | 3900 } else { |
| 3883 destination = FloatingPointHelper::kCoreRegisters; | 3901 destination = FloatingPointHelper::kCoreRegisters; |
| 3884 } | 3902 } |
| 3885 FloatingPointHelper::ConvertIntToDouble( | 3903 FloatingPointHelper::ConvertIntToDouble( |
| 3886 masm, t1, destination, | 3904 masm, t1, destination, |
| 3887 f0, t2, t3, // These are: double_dst, dst1, dst2. | 3905 f0, t2, t3, // These are: double_dst, dst1, dst2. |
| 3888 t0, f2); // These are: scratch2, single_scratch. | 3906 t0, f2); // These are: scratch2, single_scratch. |
| 3889 if (destination == FloatingPointHelper::kFPURegisters) { | 3907 if (destination == FloatingPointHelper::kFPURegisters) { |
| 3890 CpuFeatures::Scope scope(FPU); | 3908 CpuFeatures::Scope scope(FPU); |
| 3891 __ sdc1(f0, MemOperand(a3, 0)); | 3909 __ sdc1(f0, MemOperand(a3, 0)); |
| 3892 } else { | 3910 } else { |
| 3893 __ sw(t2, MemOperand(a3, 0)); | 3911 __ sw(t2, MemOperand(a3, 0)); |
| 3894 __ sw(t3, MemOperand(a3, Register::kSizeInBytes)); | 3912 __ sw(t3, MemOperand(a3, Register::kSizeInBytes)); |
| 3895 } | 3913 } |
| 3896 break; | 3914 break; |
| 3897 default: | 3915 case JSObject::FAST_ELEMENTS: |
| 3916 case JSObject::FAST_DOUBLE_ELEMENTS: |
| 3917 case JSObject::DICTIONARY_ELEMENTS: |
| 3918 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS: |
| 3898 UNREACHABLE(); | 3919 UNREACHABLE(); |
| 3899 break; | 3920 break; |
| 3900 } | 3921 } |
| 3901 | 3922 |
| 3902 // Entry registers are intact, a0 holds the value which is the return value. | 3923 // Entry registers are intact, a0 holds the value which is the return value. |
| 3903 __ mov(v0, value); | 3924 __ mov(v0, value); |
| 3904 __ Ret(); | 3925 __ Ret(); |
| 3905 | 3926 |
| 3906 if (array_type != kExternalPixelArray) { | 3927 if (elements_kind != JSObject::EXTERNAL_PIXEL_ELEMENTS) { |
| 3907 // a3: external array. | 3928 // a3: external array. |
| 3908 // t0: index (integer). | 3929 // t0: index (integer). |
| 3909 __ bind(&check_heap_number); | 3930 __ bind(&check_heap_number); |
| 3910 __ GetObjectType(value, t1, t2); | 3931 __ GetObjectType(value, t1, t2); |
| 3911 __ Branch(&slow, ne, t2, Operand(HEAP_NUMBER_TYPE)); | 3932 __ Branch(&slow, ne, t2, Operand(HEAP_NUMBER_TYPE)); |
| 3912 | 3933 |
| 3913 __ lw(a3, FieldMemOperand(a3, ExternalArray::kExternalPointerOffset)); | 3934 __ lw(a3, FieldMemOperand(a3, ExternalArray::kExternalPointerOffset)); |
| 3914 | 3935 |
| 3915 // a3: base pointer of external storage. | 3936 // a3: base pointer of external storage. |
| 3916 // t0: key (integer). | 3937 // t0: key (integer). |
| 3917 | 3938 |
| 3918 // The WebGL specification leaves the behavior of storing NaN and | 3939 // The WebGL specification leaves the behavior of storing NaN and |
| 3919 // +/-Infinity into integer arrays basically undefined. For more | 3940 // +/-Infinity into integer arrays basically undefined. For more |
| 3920 // reproducible behavior, convert these to zero. | 3941 // reproducible behavior, convert these to zero. |
| 3921 | 3942 |
| 3922 if (CpuFeatures::IsSupported(FPU)) { | 3943 if (CpuFeatures::IsSupported(FPU)) { |
| 3923 CpuFeatures::Scope scope(FPU); | 3944 CpuFeatures::Scope scope(FPU); |
| 3924 | 3945 |
| 3925 __ ldc1(f0, FieldMemOperand(a0, HeapNumber::kValueOffset)); | 3946 __ ldc1(f0, FieldMemOperand(a0, HeapNumber::kValueOffset)); |
| 3926 | 3947 |
| 3927 if (array_type == kExternalFloatArray) { | 3948 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) { |
| 3928 __ cvt_s_d(f0, f0); | 3949 __ cvt_s_d(f0, f0); |
| 3929 __ sll(t8, t0, 2); | 3950 __ sll(t8, t0, 2); |
| 3930 __ addu(t8, a3, t8); | 3951 __ addu(t8, a3, t8); |
| 3931 __ swc1(f0, MemOperand(t8, 0)); | 3952 __ swc1(f0, MemOperand(t8, 0)); |
| 3932 } else if (array_type == kExternalDoubleArray) { | 3953 } else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) { |
| 3933 __ sll(t8, t0, 3); | 3954 __ sll(t8, t0, 3); |
| 3934 __ addu(t8, a3, t8); | 3955 __ addu(t8, a3, t8); |
| 3935 __ sdc1(f0, MemOperand(t8, 0)); | 3956 __ sdc1(f0, MemOperand(t8, 0)); |
| 3936 } else { | 3957 } else { |
| 3937 Label done; | 3958 __ EmitECMATruncate(t3, f0, f2, t2, t1, t5); |
| 3938 | 3959 |
| 3939 // Need to perform float-to-int conversion. | 3960 switch (elements_kind) { |
| 3940 // Test whether exponent equal to 0x7FF (infinity or NaN). | 3961 case JSObject::EXTERNAL_BYTE_ELEMENTS: |
| 3941 | 3962 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3942 __ mfc1(t3, f1); // Move exponent word of double to t3 (as raw bits). | |
| 3943 __ li(t1, Operand(0x7FF00000)); | |
| 3944 __ And(t3, t3, Operand(t1)); | |
| 3945 __ Branch(USE_DELAY_SLOT, &done, eq, t3, Operand(t1)); | |
| 3946 __ mov(t3, zero_reg); // In delay slot. | |
| 3947 | |
| 3948 // Not infinity or NaN simply convert to int. | |
| 3949 if (IsElementTypeSigned(array_type)) { | |
| 3950 __ trunc_w_d(f0, f0); | |
| 3951 __ mfc1(t3, f0); | |
| 3952 } else { | |
| 3953 __ Trunc_uw_d(f0, t3); | |
| 3954 } | |
| 3955 | |
| 3956 // t3: HeapNumber converted to integer | |
| 3957 __ bind(&done); | |
| 3958 switch (array_type) { | |
| 3959 case kExternalByteArray: | |
| 3960 case kExternalUnsignedByteArray: | |
| 3961 __ addu(t8, a3, t0); | 3963 __ addu(t8, a3, t0); |
| 3962 __ sb(t3, MemOperand(t8, 0)); | 3964 __ sb(t3, MemOperand(t8, 0)); |
| 3963 break; | 3965 break; |
| 3964 case kExternalShortArray: | 3966 case JSObject::EXTERNAL_SHORT_ELEMENTS: |
| 3965 case kExternalUnsignedShortArray: | 3967 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3966 __ sll(t8, t0, 1); | 3968 __ sll(t8, t0, 1); |
| 3967 __ addu(t8, a3, t8); | 3969 __ addu(t8, a3, t8); |
| 3968 __ sh(t3, MemOperand(t8, 0)); | 3970 __ sh(t3, MemOperand(t8, 0)); |
| 3969 break; | 3971 break; |
| 3970 case kExternalIntArray: | 3972 case JSObject::EXTERNAL_INT_ELEMENTS: |
| 3971 case kExternalUnsignedIntArray: | 3973 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 3972 __ sll(t8, t0, 2); | 3974 __ sll(t8, t0, 2); |
| 3973 __ addu(t8, a3, t8); | 3975 __ addu(t8, a3, t8); |
| 3974 __ sw(t3, MemOperand(t8, 0)); | 3976 __ sw(t3, MemOperand(t8, 0)); |
| 3975 break; | 3977 break; |
| 3976 default: | 3978 case JSObject::EXTERNAL_PIXEL_ELEMENTS: |
| 3979 case JSObject::EXTERNAL_FLOAT_ELEMENTS: |
| 3980 case JSObject::EXTERNAL_DOUBLE_ELEMENTS: |
| 3981 case JSObject::FAST_ELEMENTS: |
| 3982 case JSObject::FAST_DOUBLE_ELEMENTS: |
| 3983 case JSObject::DICTIONARY_ELEMENTS: |
| 3984 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS: |
| 3977 UNREACHABLE(); | 3985 UNREACHABLE(); |
| 3978 break; | 3986 break; |
| 3979 } | 3987 } |
| 3980 } | 3988 } |
| 3981 | 3989 |
| 3982 // Entry registers are intact, a0 holds the value | 3990 // Entry registers are intact, a0 holds the value |
| 3983 // which is the return value. | 3991 // which is the return value. |
| 3984 __ mov(v0, value); | 3992 __ mov(v0, value); |
| 3985 __ Ret(); | 3993 __ Ret(); |
| 3986 } else { | 3994 } else { |
| 3987 // FPU is not available, do manual conversions. | 3995 // FPU is not available, do manual conversions. |
| 3988 | 3996 |
| 3989 __ lw(t3, FieldMemOperand(value, HeapNumber::kExponentOffset)); | 3997 __ lw(t3, FieldMemOperand(value, HeapNumber::kExponentOffset)); |
| 3990 __ lw(t4, FieldMemOperand(value, HeapNumber::kMantissaOffset)); | 3998 __ lw(t4, FieldMemOperand(value, HeapNumber::kMantissaOffset)); |
| 3991 | 3999 |
| 3992 if (array_type == kExternalFloatArray) { | 4000 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) { |
| 3993 Label done, nan_or_infinity_or_zero; | 4001 Label done, nan_or_infinity_or_zero; |
| 3994 static const int kMantissaInHiWordShift = | 4002 static const int kMantissaInHiWordShift = |
| 3995 kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord; | 4003 kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord; |
| 3996 | 4004 |
| 3997 static const int kMantissaInLoWordShift = | 4005 static const int kMantissaInLoWordShift = |
| 3998 kBitsPerInt - kMantissaInHiWordShift; | 4006 kBitsPerInt - kMantissaInHiWordShift; |
| 3999 | 4007 |
| 4000 // Test for all special exponent values: zeros, subnormal numbers, NaNs | 4008 // Test for all special exponent values: zeros, subnormal numbers, NaNs |
| 4001 // and infinities. All these should be converted to 0. | 4009 // and infinities. All these should be converted to 0. |
| 4002 __ li(t5, HeapNumber::kExponentMask); | 4010 __ li(t5, HeapNumber::kExponentMask); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4047 | 4055 |
| 4048 __ bind(&nan_or_infinity_or_zero); | 4056 __ bind(&nan_or_infinity_or_zero); |
| 4049 __ And(t7, t3, Operand(HeapNumber::kSignMask)); | 4057 __ And(t7, t3, Operand(HeapNumber::kSignMask)); |
| 4050 __ And(t3, t3, Operand(HeapNumber::kMantissaMask)); | 4058 __ And(t3, t3, Operand(HeapNumber::kMantissaMask)); |
| 4051 __ or_(t6, t6, t7); | 4059 __ or_(t6, t6, t7); |
| 4052 __ sll(t3, t3, kMantissaInHiWordShift); | 4060 __ sll(t3, t3, kMantissaInHiWordShift); |
| 4053 __ or_(t6, t6, t3); | 4061 __ or_(t6, t6, t3); |
| 4054 __ srl(t4, t4, kMantissaInLoWordShift); | 4062 __ srl(t4, t4, kMantissaInLoWordShift); |
| 4055 __ or_(t3, t6, t4); | 4063 __ or_(t3, t6, t4); |
| 4056 __ Branch(&done); | 4064 __ Branch(&done); |
| 4057 } else if (array_type == kExternalDoubleArray) { | 4065 } else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) { |
| 4058 __ sll(t8, t0, 3); | 4066 __ sll(t8, t0, 3); |
| 4059 __ addu(t8, a3, t8); | 4067 __ addu(t8, a3, t8); |
| 4060 // t8: effective address of destination element. | 4068 // t8: effective address of destination element. |
| 4061 __ sw(t4, MemOperand(t8, 0)); | 4069 __ sw(t4, MemOperand(t8, 0)); |
| 4062 __ sw(t3, MemOperand(t8, Register::kSizeInBytes)); | 4070 __ sw(t3, MemOperand(t8, Register::kSizeInBytes)); |
| 4063 __ Ret(); | 4071 __ Ret(); |
| 4064 } else { | 4072 } else { |
| 4065 bool is_signed_type = IsElementTypeSigned(array_type); | 4073 bool is_signed_type = IsElementTypeSigned(elements_kind); |
| 4066 int meaningfull_bits = is_signed_type ? (kBitsPerInt - 1) : kBitsPerInt; | 4074 int meaningfull_bits = is_signed_type ? (kBitsPerInt - 1) : kBitsPerInt; |
| 4067 int32_t min_value = is_signed_type ? 0x80000000 : 0x00000000; | 4075 int32_t min_value = is_signed_type ? 0x80000000 : 0x00000000; |
| 4068 | 4076 |
| 4069 Label done, sign; | 4077 Label done, sign; |
| 4070 | 4078 |
| 4071 // Test for all special exponent values: zeros, subnormal numbers, NaNs | 4079 // Test for all special exponent values: zeros, subnormal numbers, NaNs |
| 4072 // and infinities. All these should be converted to 0. | 4080 // and infinities. All these should be converted to 0. |
| 4073 __ li(t5, HeapNumber::kExponentMask); | 4081 __ li(t5, HeapNumber::kExponentMask); |
| 4074 __ and_(t6, t3, t5); | 4082 __ and_(t6, t3, t5); |
| 4075 __ movz(t3, zero_reg, t6); // Only if t6 is equal to zero. | 4083 __ movz(t3, zero_reg, t6); // Only if t6 is equal to zero. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4112 __ or_(t3, t3, t4); | 4120 __ or_(t3, t3, t4); |
| 4113 | 4121 |
| 4114 __ bind(&sign); | 4122 __ bind(&sign); |
| 4115 __ subu(t2, t3, zero_reg); | 4123 __ subu(t2, t3, zero_reg); |
| 4116 __ movz(t3, t2, t5); // Only if t5 is zero. | 4124 __ movz(t3, t2, t5); // Only if t5 is zero. |
| 4117 | 4125 |
| 4118 __ bind(&done); | 4126 __ bind(&done); |
| 4119 | 4127 |
| 4120 // Result is in t3. | 4128 // Result is in t3. |
| 4121 // This switch block should be exactly the same as above (FPU mode). | 4129 // This switch block should be exactly the same as above (FPU mode). |
| 4122 switch (array_type) { | 4130 switch (elements_kind) { |
| 4123 case kExternalByteArray: | 4131 case JSObject::EXTERNAL_BYTE_ELEMENTS: |
| 4124 case kExternalUnsignedByteArray: | 4132 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 4125 __ addu(t8, a3, t0); | 4133 __ addu(t8, a3, t0); |
| 4126 __ sb(t3, MemOperand(t8, 0)); | 4134 __ sb(t3, MemOperand(t8, 0)); |
| 4127 break; | 4135 break; |
| 4128 case kExternalShortArray: | 4136 case JSObject::EXTERNAL_SHORT_ELEMENTS: |
| 4129 case kExternalUnsignedShortArray: | 4137 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 4130 __ sll(t8, t0, 1); | 4138 __ sll(t8, t0, 1); |
| 4131 __ addu(t8, a3, t8); | 4139 __ addu(t8, a3, t8); |
| 4132 __ sh(t3, MemOperand(t8, 0)); | 4140 __ sh(t3, MemOperand(t8, 0)); |
| 4133 break; | 4141 break; |
| 4134 case kExternalIntArray: | 4142 case JSObject::EXTERNAL_INT_ELEMENTS: |
| 4135 case kExternalUnsignedIntArray: | 4143 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 4136 __ sll(t8, t0, 2); | 4144 __ sll(t8, t0, 2); |
| 4137 __ addu(t8, a3, t8); | 4145 __ addu(t8, a3, t8); |
| 4138 __ sw(t3, MemOperand(t8, 0)); | 4146 __ sw(t3, MemOperand(t8, 0)); |
| 4139 break; | 4147 break; |
| 4140 default: | 4148 case JSObject::EXTERNAL_PIXEL_ELEMENTS: |
| 4149 case JSObject::EXTERNAL_FLOAT_ELEMENTS: |
| 4150 case JSObject::EXTERNAL_DOUBLE_ELEMENTS: |
| 4151 case JSObject::FAST_ELEMENTS: |
| 4152 case JSObject::FAST_DOUBLE_ELEMENTS: |
| 4153 case JSObject::DICTIONARY_ELEMENTS: |
| 4154 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS: |
| 4141 UNREACHABLE(); | 4155 UNREACHABLE(); |
| 4142 break; | 4156 break; |
| 4143 } | 4157 } |
| 4144 } | 4158 } |
| 4145 } | 4159 } |
| 4146 } | 4160 } |
| 4147 | 4161 |
| 4148 // Slow case, key and receiver still in a0 and a1. | 4162 // Slow case, key and receiver still in a0 and a1. |
| 4149 __ bind(&slow); | 4163 __ bind(&slow); |
| 4150 __ IncrementCounter( | 4164 __ IncrementCounter( |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4232 Register receiver_reg = a2; | 4246 Register receiver_reg = a2; |
| 4233 Register scratch = a3; | 4247 Register scratch = a3; |
| 4234 Register elements_reg = t0; | 4248 Register elements_reg = t0; |
| 4235 Register scratch2 = t1; | 4249 Register scratch2 = t1; |
| 4236 Register scratch3 = t2; | 4250 Register scratch3 = t2; |
| 4237 | 4251 |
| 4238 // This stub is meant to be tail-jumped to, the receiver must already | 4252 // This stub is meant to be tail-jumped to, the receiver must already |
| 4239 // have been verified by the caller to not be a smi. | 4253 // have been verified by the caller to not be a smi. |
| 4240 | 4254 |
| 4241 // Check that the key is a smi. | 4255 // Check that the key is a smi. |
| 4242 __ JumpIfNotSmi(a0, &miss_force_generic); | 4256 __ JumpIfNotSmi(key_reg, &miss_force_generic); |
| 4243 | 4257 |
| 4244 // Get the elements array and make sure it is a fast element array, not 'cow'. | 4258 // Get the elements array and make sure it is a fast element array, not 'cow'. |
| 4245 __ lw(elements_reg, | 4259 __ lw(elements_reg, |
| 4246 FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); | 4260 FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); |
| 4247 __ CheckMap(elements_reg, | 4261 __ CheckMap(elements_reg, |
| 4248 scratch, | 4262 scratch, |
| 4249 Heap::kFixedArrayMapRootIndex, | 4263 Heap::kFixedArrayMapRootIndex, |
| 4250 &miss_force_generic, | 4264 &miss_force_generic, |
| 4251 DONT_DO_SMI_CHECK); | 4265 DONT_DO_SMI_CHECK); |
| 4252 | 4266 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 4276 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | 4290 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
| 4277 __ Jump(ic, RelocInfo::CODE_TARGET); | 4291 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 4278 } | 4292 } |
| 4279 | 4293 |
| 4280 | 4294 |
| 4281 #undef __ | 4295 #undef __ |
| 4282 | 4296 |
| 4283 } } // namespace v8::internal | 4297 } } // namespace v8::internal |
| 4284 | 4298 |
| 4285 #endif // V8_TARGET_ARCH_MIPS | 4299 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |