| 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 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 98 | 98 |
| 99 const int kInterceptorOrAccessCheckNeededMask = | 99 const int kInterceptorOrAccessCheckNeededMask = |
| 100 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 100 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
| 101 | 101 |
| 102 // Bail out if the receiver has a named interceptor or requires access checks. | 102 // Bail out if the receiver has a named interceptor or requires access checks. |
| 103 __ testb(FieldOperand(r0, Map::kBitFieldOffset), | 103 __ testb(FieldOperand(r0, Map::kBitFieldOffset), |
| 104 Immediate(kInterceptorOrAccessCheckNeededMask)); | 104 Immediate(kInterceptorOrAccessCheckNeededMask)); |
| 105 __ j(not_zero, miss_label); | 105 __ j(not_zero, miss_label); |
| 106 | 106 |
| 107 // Check that receiver is a JSObject. | 107 // Check that receiver is a JSObject. |
| 108 __ CmpInstanceType(r0, FIRST_JS_OBJECT_TYPE); | 108 __ CmpInstanceType(r0, FIRST_SPEC_OBJECT_TYPE); |
| 109 __ j(below, miss_label); | 109 __ j(below, miss_label); |
| 110 | 110 |
| 111 // Load properties array. | 111 // Load properties array. |
| 112 Register properties = r0; | 112 Register properties = r0; |
| 113 __ movq(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); | 113 __ movq(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
| 114 | 114 |
| 115 // Check that the properties array is a dictionary. | 115 // Check that the properties array is a dictionary. |
| 116 __ CompareRoot(FieldOperand(properties, HeapObject::kMapOffset), | 116 __ CompareRoot(FieldOperand(properties, HeapObject::kMapOffset), |
| 117 Heap::kHashTableMapRootIndex); | 117 Heap::kHashTableMapRootIndex); |
| 118 __ j(not_equal, miss_label); | 118 __ j(not_equal, miss_label); |
| (...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 471 // object. | 471 // object. |
| 472 return masm->TryCallApiFunctionAndReturn(&fun, | 472 return masm->TryCallApiFunctionAndReturn(&fun, |
| 473 argc + kFastApiCallArguments + 1); | 473 argc + kFastApiCallArguments + 1); |
| 474 } | 474 } |
| 475 | 475 |
| 476 | 476 |
| 477 class CallInterceptorCompiler BASE_EMBEDDED { | 477 class CallInterceptorCompiler BASE_EMBEDDED { |
| 478 public: | 478 public: |
| 479 CallInterceptorCompiler(StubCompiler* stub_compiler, | 479 CallInterceptorCompiler(StubCompiler* stub_compiler, |
| 480 const ParameterCount& arguments, | 480 const ParameterCount& arguments, |
| 481 Register name) | 481 Register name, |
| 482 Code::ExtraICState extra_ic_state) |
| 482 : stub_compiler_(stub_compiler), | 483 : stub_compiler_(stub_compiler), |
| 483 arguments_(arguments), | 484 arguments_(arguments), |
| 484 name_(name) {} | 485 name_(name), |
| 486 extra_ic_state_(extra_ic_state) {} |
| 485 | 487 |
| 486 MaybeObject* Compile(MacroAssembler* masm, | 488 MaybeObject* Compile(MacroAssembler* masm, |
| 487 JSObject* object, | 489 JSObject* object, |
| 488 JSObject* holder, | 490 JSObject* holder, |
| 489 String* name, | 491 String* name, |
| 490 LookupResult* lookup, | 492 LookupResult* lookup, |
| 491 Register receiver, | 493 Register receiver, |
| 492 Register scratch1, | 494 Register scratch1, |
| 493 Register scratch2, | 495 Register scratch2, |
| 494 Register scratch3, | 496 Register scratch3, |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 599 ASSERT(depth2 == kInvalidProtoDepth); | 601 ASSERT(depth2 == kInvalidProtoDepth); |
| 600 } | 602 } |
| 601 | 603 |
| 602 // Invoke function. | 604 // Invoke function. |
| 603 if (can_do_fast_api_call) { | 605 if (can_do_fast_api_call) { |
| 604 MaybeObject* result = GenerateFastApiCall(masm, | 606 MaybeObject* result = GenerateFastApiCall(masm, |
| 605 optimization, | 607 optimization, |
| 606 arguments_.immediate()); | 608 arguments_.immediate()); |
| 607 if (result->IsFailure()) return result; | 609 if (result->IsFailure()) return result; |
| 608 } else { | 610 } else { |
| 611 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) |
| 612 ? CALL_AS_FUNCTION |
| 613 : CALL_AS_METHOD; |
| 609 __ InvokeFunction(optimization.constant_function(), arguments_, | 614 __ InvokeFunction(optimization.constant_function(), arguments_, |
| 610 JUMP_FUNCTION); | 615 JUMP_FUNCTION, NullCallWrapper(), call_kind); |
| 611 } | 616 } |
| 612 | 617 |
| 613 // Deferred code for fast API call case---clean preallocated space. | 618 // Deferred code for fast API call case---clean preallocated space. |
| 614 if (can_do_fast_api_call) { | 619 if (can_do_fast_api_call) { |
| 615 __ bind(&miss_cleanup); | 620 __ bind(&miss_cleanup); |
| 616 FreeSpaceForFastApiCall(masm, scratch1); | 621 FreeSpaceForFastApiCall(masm, scratch1); |
| 617 __ jmp(miss_label); | 622 __ jmp(miss_label); |
| 618 } | 623 } |
| 619 | 624 |
| 620 // Invoke a regular function. | 625 // Invoke a regular function. |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 679 __ pop(receiver); // Restore the holder. | 684 __ pop(receiver); // Restore the holder. |
| 680 __ LeaveInternalFrame(); | 685 __ LeaveInternalFrame(); |
| 681 | 686 |
| 682 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); | 687 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); |
| 683 __ j(not_equal, interceptor_succeeded); | 688 __ j(not_equal, interceptor_succeeded); |
| 684 } | 689 } |
| 685 | 690 |
| 686 StubCompiler* stub_compiler_; | 691 StubCompiler* stub_compiler_; |
| 687 const ParameterCount& arguments_; | 692 const ParameterCount& arguments_; |
| 688 Register name_; | 693 Register name_; |
| 694 Code::ExtraICState extra_ic_state_; |
| 689 }; | 695 }; |
| 690 | 696 |
| 691 | 697 |
| 692 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { | 698 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { |
| 693 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); | 699 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); |
| 694 Code* code = NULL; | 700 Code* code = NULL; |
| 695 if (kind == Code::LOAD_IC) { | 701 if (kind == Code::LOAD_IC) { |
| 696 code = masm->isolate()->builtins()->builtin(Builtins::kLoadIC_Miss); | 702 code = masm->isolate()->builtins()->builtin(Builtins::kLoadIC_Miss); |
| 697 } else { | 703 } else { |
| 698 code = masm->isolate()->builtins()->builtin(Builtins::kKeyedLoadIC_Miss); | 704 code = masm->isolate()->builtins()->builtin(Builtins::kKeyedLoadIC_Miss); |
| (...skipping 644 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1343 __ j(not_equal, &miss); | 1349 __ j(not_equal, &miss); |
| 1344 | 1350 |
| 1345 // Patch the receiver on the stack with the global proxy if | 1351 // Patch the receiver on the stack with the global proxy if |
| 1346 // necessary. | 1352 // necessary. |
| 1347 if (object->IsGlobalObject()) { | 1353 if (object->IsGlobalObject()) { |
| 1348 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 1354 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 1349 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | 1355 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
| 1350 } | 1356 } |
| 1351 | 1357 |
| 1352 // Invoke the function. | 1358 // Invoke the function. |
| 1353 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION); | 1359 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) |
| 1360 ? CALL_AS_FUNCTION |
| 1361 : CALL_AS_METHOD; |
| 1362 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, |
| 1363 NullCallWrapper(), call_kind); |
| 1354 | 1364 |
| 1355 // Handle call cache miss. | 1365 // Handle call cache miss. |
| 1356 __ bind(&miss); | 1366 __ bind(&miss); |
| 1357 MaybeObject* maybe_result = GenerateMissBranch(); | 1367 MaybeObject* maybe_result = GenerateMissBranch(); |
| 1358 if (maybe_result->IsFailure()) return maybe_result; | 1368 if (maybe_result->IsFailure()) return maybe_result; |
| 1359 | 1369 |
| 1360 // Return the generated code. | 1370 // Return the generated code. |
| 1361 return GetCode(FIELD, name); | 1371 return GetCode(FIELD, name); |
| 1362 } | 1372 } |
| 1363 | 1373 |
| (...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1830 StringCharFromCodeGenerator char_from_code_generator(code, rax); | 1840 StringCharFromCodeGenerator char_from_code_generator(code, rax); |
| 1831 char_from_code_generator.GenerateFast(masm()); | 1841 char_from_code_generator.GenerateFast(masm()); |
| 1832 __ ret(2 * kPointerSize); | 1842 __ ret(2 * kPointerSize); |
| 1833 | 1843 |
| 1834 StubRuntimeCallHelper call_helper; | 1844 StubRuntimeCallHelper call_helper; |
| 1835 char_from_code_generator.GenerateSlow(masm(), call_helper); | 1845 char_from_code_generator.GenerateSlow(masm(), call_helper); |
| 1836 | 1846 |
| 1837 // Tail call the full function. We do not have to patch the receiver | 1847 // Tail call the full function. We do not have to patch the receiver |
| 1838 // because the function makes no use of it. | 1848 // because the function makes no use of it. |
| 1839 __ bind(&slow); | 1849 __ bind(&slow); |
| 1840 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); | 1850 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) |
| 1851 ? CALL_AS_FUNCTION |
| 1852 : CALL_AS_METHOD; |
| 1853 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
| 1854 NullCallWrapper(), call_kind); |
| 1841 | 1855 |
| 1842 __ bind(&miss); | 1856 __ bind(&miss); |
| 1843 // rcx: function name. | 1857 // rcx: function name. |
| 1844 MaybeObject* maybe_result = GenerateMissBranch(); | 1858 MaybeObject* maybe_result = GenerateMissBranch(); |
| 1845 if (maybe_result->IsFailure()) return maybe_result; | 1859 if (maybe_result->IsFailure()) return maybe_result; |
| 1846 | 1860 |
| 1847 // Return the generated code. | 1861 // Return the generated code. |
| 1848 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 1862 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); |
| 1849 } | 1863 } |
| 1850 | 1864 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1943 // number. We still have the sign mask in rdi. | 1957 // number. We still have the sign mask in rdi. |
| 1944 __ bind(&negative_sign); | 1958 __ bind(&negative_sign); |
| 1945 __ xor_(rbx, rdi); | 1959 __ xor_(rbx, rdi); |
| 1946 __ AllocateHeapNumber(rax, rdx, &slow); | 1960 __ AllocateHeapNumber(rax, rdx, &slow); |
| 1947 __ movq(FieldOperand(rax, HeapNumber::kValueOffset), rbx); | 1961 __ movq(FieldOperand(rax, HeapNumber::kValueOffset), rbx); |
| 1948 __ ret(2 * kPointerSize); | 1962 __ ret(2 * kPointerSize); |
| 1949 | 1963 |
| 1950 // Tail call the full function. We do not have to patch the receiver | 1964 // Tail call the full function. We do not have to patch the receiver |
| 1951 // because the function makes no use of it. | 1965 // because the function makes no use of it. |
| 1952 __ bind(&slow); | 1966 __ bind(&slow); |
| 1953 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); | 1967 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) |
| 1968 ? CALL_AS_FUNCTION |
| 1969 : CALL_AS_METHOD; |
| 1970 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
| 1971 NullCallWrapper(), call_kind); |
| 1954 | 1972 |
| 1955 __ bind(&miss); | 1973 __ bind(&miss); |
| 1956 // rcx: function name. | 1974 // rcx: function name. |
| 1957 MaybeObject* maybe_result = GenerateMissBranch(); | 1975 MaybeObject* maybe_result = GenerateMissBranch(); |
| 1958 if (maybe_result->IsFailure()) return maybe_result; | 1976 if (maybe_result->IsFailure()) return maybe_result; |
| 1959 | 1977 |
| 1960 // Return the generated code. | 1978 // Return the generated code. |
| 1961 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | 1979 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); |
| 1962 } | 1980 } |
| 1963 | 1981 |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2137 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, | 2155 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, |
| 2138 rbx, rdx, rdi, name, &miss); | 2156 rbx, rdx, rdi, name, &miss); |
| 2139 } | 2157 } |
| 2140 break; | 2158 break; |
| 2141 } | 2159 } |
| 2142 | 2160 |
| 2143 default: | 2161 default: |
| 2144 UNREACHABLE(); | 2162 UNREACHABLE(); |
| 2145 } | 2163 } |
| 2146 | 2164 |
| 2147 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); | 2165 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) |
| 2166 ? CALL_AS_FUNCTION |
| 2167 : CALL_AS_METHOD; |
| 2168 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, |
| 2169 NullCallWrapper(), call_kind); |
| 2148 | 2170 |
| 2149 // Handle call cache miss. | 2171 // Handle call cache miss. |
| 2150 __ bind(&miss); | 2172 __ bind(&miss); |
| 2151 MaybeObject* maybe_result = GenerateMissBranch(); | 2173 MaybeObject* maybe_result = GenerateMissBranch(); |
| 2152 if (maybe_result->IsFailure()) return maybe_result; | 2174 if (maybe_result->IsFailure()) return maybe_result; |
| 2153 | 2175 |
| 2154 // Return the generated code. | 2176 // Return the generated code. |
| 2155 return GetCode(function); | 2177 return GetCode(function); |
| 2156 } | 2178 } |
| 2157 | 2179 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2174 | 2196 |
| 2175 // Get the number of arguments. | 2197 // Get the number of arguments. |
| 2176 const int argc = arguments().immediate(); | 2198 const int argc = arguments().immediate(); |
| 2177 | 2199 |
| 2178 LookupResult lookup; | 2200 LookupResult lookup; |
| 2179 LookupPostInterceptor(holder, name, &lookup); | 2201 LookupPostInterceptor(holder, name, &lookup); |
| 2180 | 2202 |
| 2181 // Get the receiver from the stack. | 2203 // Get the receiver from the stack. |
| 2182 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 2204 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 2183 | 2205 |
| 2184 CallInterceptorCompiler compiler(this, arguments(), rcx); | 2206 CallInterceptorCompiler compiler(this, arguments(), rcx, extra_ic_state_); |
| 2185 MaybeObject* result = compiler.Compile(masm(), | 2207 MaybeObject* result = compiler.Compile(masm(), |
| 2186 object, | 2208 object, |
| 2187 holder, | 2209 holder, |
| 2188 name, | 2210 name, |
| 2189 &lookup, | 2211 &lookup, |
| 2190 rdx, | 2212 rdx, |
| 2191 rbx, | 2213 rbx, |
| 2192 rdi, | 2214 rdi, |
| 2193 rax, | 2215 rax, |
| 2194 &miss); | 2216 &miss); |
| 2195 if (result->IsFailure()) return result; | 2217 if (result->IsFailure()) return result; |
| 2196 | 2218 |
| 2197 // Restore receiver. | 2219 // Restore receiver. |
| 2198 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 2220 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 2199 | 2221 |
| 2200 // Check that the function really is a function. | 2222 // Check that the function really is a function. |
| 2201 __ JumpIfSmi(rax, &miss); | 2223 __ JumpIfSmi(rax, &miss); |
| 2202 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); | 2224 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); |
| 2203 __ j(not_equal, &miss); | 2225 __ j(not_equal, &miss); |
| 2204 | 2226 |
| 2205 // Patch the receiver on the stack with the global proxy if | 2227 // Patch the receiver on the stack with the global proxy if |
| 2206 // necessary. | 2228 // necessary. |
| 2207 if (object->IsGlobalObject()) { | 2229 if (object->IsGlobalObject()) { |
| 2208 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 2230 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 2209 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | 2231 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
| 2210 } | 2232 } |
| 2211 | 2233 |
| 2212 // Invoke the function. | 2234 // Invoke the function. |
| 2213 __ movq(rdi, rax); | 2235 __ movq(rdi, rax); |
| 2214 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION); | 2236 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) |
| 2237 ? CALL_AS_FUNCTION |
| 2238 : CALL_AS_METHOD; |
| 2239 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, |
| 2240 NullCallWrapper(), call_kind); |
| 2215 | 2241 |
| 2216 // Handle load cache miss. | 2242 // Handle load cache miss. |
| 2217 __ bind(&miss); | 2243 __ bind(&miss); |
| 2218 MaybeObject* maybe_result = GenerateMissBranch(); | 2244 MaybeObject* maybe_result = GenerateMissBranch(); |
| 2219 if (maybe_result->IsFailure()) return maybe_result; | 2245 if (maybe_result->IsFailure()) return maybe_result; |
| 2220 | 2246 |
| 2221 // Return the generated code. | 2247 // Return the generated code. |
| 2222 return GetCode(INTERCEPTOR, name); | 2248 return GetCode(INTERCEPTOR, name); |
| 2223 } | 2249 } |
| 2224 | 2250 |
| 2225 | 2251 |
| 2226 MaybeObject* CallStubCompiler::CompileCallGlobal( | 2252 MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object, |
| 2227 JSObject* object, | 2253 GlobalObject* holder, |
| 2228 GlobalObject* holder, | 2254 JSGlobalPropertyCell* cell, |
| 2229 JSGlobalPropertyCell* cell, | 2255 JSFunction* function, |
| 2230 JSFunction* function, | 2256 String* name) { |
| 2231 String* name, | |
| 2232 Code::ExtraICState extra_ic_state) { | |
| 2233 // ----------- S t a t e ------------- | 2257 // ----------- S t a t e ------------- |
| 2234 // rcx : function name | 2258 // rcx : function name |
| 2235 // rsp[0] : return address | 2259 // rsp[0] : return address |
| 2236 // rsp[8] : argument argc | 2260 // rsp[8] : argument argc |
| 2237 // rsp[16] : argument argc - 1 | 2261 // rsp[16] : argument argc - 1 |
| 2238 // ... | 2262 // ... |
| 2239 // rsp[argc * 8] : argument 1 | 2263 // rsp[argc * 8] : argument 1 |
| 2240 // rsp[(argc + 1) * 8] : argument 0 = receiver | 2264 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 2241 // ----------------------------------- | 2265 // ----------------------------------- |
| 2242 | 2266 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2267 } | 2291 } |
| 2268 | 2292 |
| 2269 // Setup the context (function already in rdi). | 2293 // Setup the context (function already in rdi). |
| 2270 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | 2294 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
| 2271 | 2295 |
| 2272 // Jump to the cached code (tail call). | 2296 // Jump to the cached code (tail call). |
| 2273 Counters* counters = isolate()->counters(); | 2297 Counters* counters = isolate()->counters(); |
| 2274 __ IncrementCounter(counters->call_global_inline(), 1); | 2298 __ IncrementCounter(counters->call_global_inline(), 1); |
| 2275 ASSERT(function->is_compiled()); | 2299 ASSERT(function->is_compiled()); |
| 2276 ParameterCount expected(function->shared()->formal_parameter_count()); | 2300 ParameterCount expected(function->shared()->formal_parameter_count()); |
| 2277 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state) | 2301 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) |
| 2278 ? CALL_AS_FUNCTION | 2302 ? CALL_AS_FUNCTION |
| 2279 : CALL_AS_METHOD; | 2303 : CALL_AS_METHOD; |
| 2280 if (V8::UseCrankshaft()) { | 2304 if (V8::UseCrankshaft()) { |
| 2281 // TODO(kasperl): For now, we always call indirectly through the | 2305 // TODO(kasperl): For now, we always call indirectly through the |
| 2282 // code field in the function to allow recompilation to take effect | 2306 // code field in the function to allow recompilation to take effect |
| 2283 // without changing any of the call sites. | 2307 // without changing any of the call sites. |
| 2284 __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); | 2308 __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); |
| 2285 __ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION, | 2309 __ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION, |
| 2286 NullCallWrapper(), call_kind); | 2310 NullCallWrapper(), call_kind); |
| 2287 } else { | 2311 } else { |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2522 __ bind(&miss); | 2546 __ bind(&miss); |
| 2523 __ DecrementCounter(counters->keyed_store_field(), 1); | 2547 __ DecrementCounter(counters->keyed_store_field(), 1); |
| 2524 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 2548 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| 2525 __ Jump(ic, RelocInfo::CODE_TARGET); | 2549 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 2526 | 2550 |
| 2527 // Return the generated code. | 2551 // Return the generated code. |
| 2528 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); | 2552 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); |
| 2529 } | 2553 } |
| 2530 | 2554 |
| 2531 | 2555 |
| 2532 MaybeObject* KeyedStoreStubCompiler::CompileStoreFastElement( | 2556 MaybeObject* KeyedStoreStubCompiler::CompileStoreElement(Map* receiver_map) { |
| 2533 Map* receiver_map) { | |
| 2534 // ----------- S t a t e ------------- | 2557 // ----------- S t a t e ------------- |
| 2535 // -- rax : value | 2558 // -- rax : value |
| 2536 // -- rcx : key | 2559 // -- rcx : key |
| 2537 // -- rdx : receiver | 2560 // -- rdx : receiver |
| 2538 // -- rsp[0] : return address | 2561 // -- rsp[0] : return address |
| 2539 // ----------------------------------- | 2562 // ----------------------------------- |
| 2563 Code* stub; |
| 2564 JSObject::ElementsKind elements_kind = receiver_map->elements_kind(); |
| 2540 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; | 2565 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; |
| 2541 MaybeObject* maybe_stub = | 2566 MaybeObject* maybe_stub = |
| 2542 KeyedStoreFastElementStub(is_js_array).TryGetCode(); | 2567 KeyedStoreElementStub(is_js_array, elements_kind).TryGetCode(); |
| 2543 Code* stub; | |
| 2544 if (!maybe_stub->To(&stub)) return maybe_stub; | 2568 if (!maybe_stub->To(&stub)) return maybe_stub; |
| 2545 __ DispatchMap(rdx, | 2569 __ DispatchMap(rdx, |
| 2546 Handle<Map>(receiver_map), | 2570 Handle<Map>(receiver_map), |
| 2547 Handle<Code>(stub), | 2571 Handle<Code>(stub), |
| 2548 DO_SMI_CHECK); | 2572 DO_SMI_CHECK); |
| 2549 | 2573 |
| 2550 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 2574 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| 2551 __ jmp(ic, RelocInfo::CODE_TARGET); | 2575 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 2552 | 2576 |
| 2553 // Return the generated code. | 2577 // Return the generated code. |
| (...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2982 GenerateLoadFunctionPrototype(masm(), rdx, rcx, rbx, &miss); | 3006 GenerateLoadFunctionPrototype(masm(), rdx, rcx, rbx, &miss); |
| 2983 __ bind(&miss); | 3007 __ bind(&miss); |
| 2984 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); | 3008 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); |
| 2985 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3009 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 2986 | 3010 |
| 2987 // Return the generated code. | 3011 // Return the generated code. |
| 2988 return GetCode(CALLBACKS, name); | 3012 return GetCode(CALLBACKS, name); |
| 2989 } | 3013 } |
| 2990 | 3014 |
| 2991 | 3015 |
| 2992 MaybeObject* KeyedLoadStubCompiler::CompileLoadFastElement(Map* receiver_map) { | 3016 MaybeObject* KeyedLoadStubCompiler::CompileLoadElement(Map* receiver_map) { |
| 2993 // ----------- S t a t e ------------- | 3017 // ----------- S t a t e ------------- |
| 2994 // -- rax : key | 3018 // -- rax : key |
| 2995 // -- rdx : receiver | 3019 // -- rdx : receiver |
| 2996 // -- rsp[0] : return address | 3020 // -- rsp[0] : return address |
| 2997 // ----------------------------------- | 3021 // ----------------------------------- |
| 2998 MaybeObject* maybe_stub = KeyedLoadFastElementStub().TryGetCode(); | |
| 2999 Code* stub; | 3022 Code* stub; |
| 3023 JSObject::ElementsKind elements_kind = receiver_map->elements_kind(); |
| 3024 MaybeObject* maybe_stub = KeyedLoadElementStub(elements_kind).TryGetCode(); |
| 3000 if (!maybe_stub->To(&stub)) return maybe_stub; | 3025 if (!maybe_stub->To(&stub)) return maybe_stub; |
| 3001 __ DispatchMap(rdx, | 3026 __ DispatchMap(rdx, |
| 3002 Handle<Map>(receiver_map), | 3027 Handle<Map>(receiver_map), |
| 3003 Handle<Code>(stub), | 3028 Handle<Code>(stub), |
| 3004 DO_SMI_CHECK); | 3029 DO_SMI_CHECK); |
| 3005 | 3030 |
| 3006 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); | 3031 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); |
| 3007 __ jmp(ic, RelocInfo::CODE_TARGET); | 3032 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 3008 | 3033 |
| 3009 // Return the generated code. | 3034 // Return the generated code. |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3168 Code* code = | 3193 Code* code = |
| 3169 isolate()->builtins()->builtin(Builtins::kJSConstructStubGeneric); | 3194 isolate()->builtins()->builtin(Builtins::kJSConstructStubGeneric); |
| 3170 Handle<Code> generic_construct_stub(code); | 3195 Handle<Code> generic_construct_stub(code); |
| 3171 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); | 3196 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); |
| 3172 | 3197 |
| 3173 // Return the generated code. | 3198 // Return the generated code. |
| 3174 return GetCode(); | 3199 return GetCode(); |
| 3175 } | 3200 } |
| 3176 | 3201 |
| 3177 | 3202 |
| 3178 MaybeObject* ExternalArrayLoadStubCompiler::CompileLoad( | |
| 3179 JSObject*receiver, ExternalArrayType array_type) { | |
| 3180 // ----------- S t a t e ------------- | |
| 3181 // -- rax : key | |
| 3182 // -- rdx : receiver | |
| 3183 // -- rsp[0] : return address | |
| 3184 // ----------------------------------- | |
| 3185 MaybeObject* maybe_stub = | |
| 3186 KeyedLoadExternalArrayStub(array_type).TryGetCode(); | |
| 3187 Code* stub; | |
| 3188 if (!maybe_stub->To(&stub)) return maybe_stub; | |
| 3189 __ DispatchMap(rdx, | |
| 3190 Handle<Map>(receiver->map()), | |
| 3191 Handle<Code>(stub), | |
| 3192 DO_SMI_CHECK); | |
| 3193 | |
| 3194 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); | |
| 3195 __ jmp(ic, RelocInfo::CODE_TARGET); | |
| 3196 | |
| 3197 // Return the generated code. | |
| 3198 return GetCode(); | |
| 3199 } | |
| 3200 | |
| 3201 MaybeObject* ExternalArrayStoreStubCompiler::CompileStore( | |
| 3202 JSObject* receiver, ExternalArrayType array_type) { | |
| 3203 // ----------- S t a t e ------------- | |
| 3204 // -- rax : value | |
| 3205 // -- rcx : key | |
| 3206 // -- rdx : receiver | |
| 3207 // -- rsp[0] : return address | |
| 3208 // ----------------------------------- | |
| 3209 MaybeObject* maybe_stub = | |
| 3210 KeyedStoreExternalArrayStub(array_type).TryGetCode(); | |
| 3211 Code* stub; | |
| 3212 if (!maybe_stub->To(&stub)) return maybe_stub; | |
| 3213 __ DispatchMap(rdx, | |
| 3214 Handle<Map>(receiver->map()), | |
| 3215 Handle<Code>(stub), | |
| 3216 DO_SMI_CHECK); | |
| 3217 | |
| 3218 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | |
| 3219 __ jmp(ic, RelocInfo::CODE_TARGET); | |
| 3220 | |
| 3221 return GetCode(); | |
| 3222 } | |
| 3223 | |
| 3224 | |
| 3225 #undef __ | 3203 #undef __ |
| 3226 #define __ ACCESS_MASM(masm) | 3204 #define __ ACCESS_MASM(masm) |
| 3227 | 3205 |
| 3228 | 3206 |
| 3229 void KeyedLoadStubCompiler::GenerateLoadExternalArray( | 3207 void KeyedLoadStubCompiler::GenerateLoadDictionaryElement( |
| 3230 MacroAssembler* masm, | 3208 MacroAssembler* masm) { |
| 3231 ExternalArrayType array_type) { | |
| 3232 // ----------- S t a t e ------------- | 3209 // ----------- S t a t e ------------- |
| 3233 // -- rax : key | 3210 // -- rax : key |
| 3234 // -- rdx : receiver | 3211 // -- rdx : receiver |
| 3212 // -- rsp[0] : return address |
| 3213 // ----------------------------------- |
| 3214 Label slow, miss_force_generic; |
| 3215 |
| 3216 // This stub is meant to be tail-jumped to, the receiver must already |
| 3217 // have been verified by the caller to not be a smi. |
| 3218 |
| 3219 __ JumpIfNotSmi(rax, &miss_force_generic); |
| 3220 __ SmiToInteger32(rbx, rax); |
| 3221 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); |
| 3222 |
| 3223 // Check whether the elements is a number dictionary. |
| 3224 // rdx: receiver |
| 3225 // rax: key |
| 3226 // rbx: key as untagged int32 |
| 3227 // rcx: elements |
| 3228 __ LoadFromNumberDictionary(&slow, rcx, rax, rbx, r9, rdi, rax); |
| 3229 __ ret(0); |
| 3230 |
| 3231 __ bind(&slow); |
| 3232 // ----------- S t a t e ------------- |
| 3233 // -- rax : key |
| 3234 // -- rdx : receiver |
| 3235 // -- rsp[0] : return address |
| 3236 // ----------------------------------- |
| 3237 Handle<Code> slow_ic = |
| 3238 masm->isolate()->builtins()->KeyedLoadIC_Slow(); |
| 3239 __ jmp(slow_ic, RelocInfo::CODE_TARGET); |
| 3240 |
| 3241 __ bind(&miss_force_generic); |
| 3242 // ----------- S t a t e ------------- |
| 3243 // -- rax : key |
| 3244 // -- rdx : receiver |
| 3245 // -- rsp[0] : return address |
| 3246 // ----------------------------------- |
| 3247 Handle<Code> miss_ic = |
| 3248 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); |
| 3249 __ jmp(miss_ic, RelocInfo::CODE_TARGET); |
| 3250 } |
| 3251 |
| 3252 void KeyedLoadStubCompiler::GenerateLoadExternalArray( |
| 3253 MacroAssembler* masm, |
| 3254 JSObject::ElementsKind elements_kind) { |
| 3255 // ----------- S t a t e ------------- |
| 3256 // -- rax : key |
| 3257 // -- rdx : receiver |
| 3235 // -- rsp[0] : return address | 3258 // -- rsp[0] : return address |
| 3236 // ----------------------------------- | 3259 // ----------------------------------- |
| 3237 Label slow, miss_force_generic; | 3260 Label slow, miss_force_generic; |
| 3238 | 3261 |
| 3239 // This stub is meant to be tail-jumped to, the receiver must already | 3262 // This stub is meant to be tail-jumped to, the receiver must already |
| 3240 // have been verified by the caller to not be a smi. | 3263 // have been verified by the caller to not be a smi. |
| 3241 | 3264 |
| 3242 // Check that the key is a smi. | 3265 // Check that the key is a smi. |
| 3243 __ JumpIfNotSmi(rax, &miss_force_generic); | 3266 __ JumpIfNotSmi(rax, &miss_force_generic); |
| 3244 | 3267 |
| 3245 // Check that the index is in range. | 3268 // Check that the index is in range. |
| 3246 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); | 3269 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); |
| 3247 __ SmiToInteger32(rcx, rax); | 3270 __ SmiToInteger32(rcx, rax); |
| 3248 __ cmpl(rcx, FieldOperand(rbx, ExternalArray::kLengthOffset)); | 3271 __ cmpl(rcx, FieldOperand(rbx, ExternalArray::kLengthOffset)); |
| 3249 // Unsigned comparison catches both negative and too-large values. | 3272 // Unsigned comparison catches both negative and too-large values. |
| 3250 __ j(above_equal, &miss_force_generic); | 3273 __ j(above_equal, &miss_force_generic); |
| 3251 | 3274 |
| 3252 // rax: index (as a smi) | 3275 // rax: index (as a smi) |
| 3253 // rdx: receiver (JSObject) | 3276 // rdx: receiver (JSObject) |
| 3254 // rcx: untagged index | 3277 // rcx: untagged index |
| 3255 // rbx: elements array | 3278 // rbx: elements array |
| 3256 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); | 3279 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); |
| 3257 // rbx: base pointer of external storage | 3280 // rbx: base pointer of external storage |
| 3258 switch (array_type) { | 3281 switch (elements_kind) { |
| 3259 case kExternalByteArray: | 3282 case JSObject::EXTERNAL_BYTE_ELEMENTS: |
| 3260 __ movsxbq(rcx, Operand(rbx, rcx, times_1, 0)); | 3283 __ movsxbq(rcx, Operand(rbx, rcx, times_1, 0)); |
| 3261 break; | 3284 break; |
| 3262 case kExternalPixelArray: | 3285 case JSObject::EXTERNAL_PIXEL_ELEMENTS: |
| 3263 case kExternalUnsignedByteArray: | 3286 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3264 __ movzxbq(rcx, Operand(rbx, rcx, times_1, 0)); | 3287 __ movzxbq(rcx, Operand(rbx, rcx, times_1, 0)); |
| 3265 break; | 3288 break; |
| 3266 case kExternalShortArray: | 3289 case JSObject::EXTERNAL_SHORT_ELEMENTS: |
| 3267 __ movsxwq(rcx, Operand(rbx, rcx, times_2, 0)); | 3290 __ movsxwq(rcx, Operand(rbx, rcx, times_2, 0)); |
| 3268 break; | 3291 break; |
| 3269 case kExternalUnsignedShortArray: | 3292 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3270 __ movzxwq(rcx, Operand(rbx, rcx, times_2, 0)); | 3293 __ movzxwq(rcx, Operand(rbx, rcx, times_2, 0)); |
| 3271 break; | 3294 break; |
| 3272 case kExternalIntArray: | 3295 case JSObject::EXTERNAL_INT_ELEMENTS: |
| 3273 __ movsxlq(rcx, Operand(rbx, rcx, times_4, 0)); | 3296 __ movsxlq(rcx, Operand(rbx, rcx, times_4, 0)); |
| 3274 break; | 3297 break; |
| 3275 case kExternalUnsignedIntArray: | 3298 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 3276 __ movl(rcx, Operand(rbx, rcx, times_4, 0)); | 3299 __ movl(rcx, Operand(rbx, rcx, times_4, 0)); |
| 3277 break; | 3300 break; |
| 3278 case kExternalFloatArray: | 3301 case JSObject::EXTERNAL_FLOAT_ELEMENTS: |
| 3279 __ cvtss2sd(xmm0, Operand(rbx, rcx, times_4, 0)); | 3302 __ cvtss2sd(xmm0, Operand(rbx, rcx, times_4, 0)); |
| 3280 break; | 3303 break; |
| 3281 case kExternalDoubleArray: | 3304 case JSObject::EXTERNAL_DOUBLE_ELEMENTS: |
| 3282 __ movsd(xmm0, Operand(rbx, rcx, times_8, 0)); | 3305 __ movsd(xmm0, Operand(rbx, rcx, times_8, 0)); |
| 3283 break; | 3306 break; |
| 3284 default: | 3307 default: |
| 3285 UNREACHABLE(); | 3308 UNREACHABLE(); |
| 3286 break; | 3309 break; |
| 3287 } | 3310 } |
| 3288 | 3311 |
| 3289 // rax: index | 3312 // rax: index |
| 3290 // rdx: receiver | 3313 // rdx: receiver |
| 3291 // For integer array types: | 3314 // For integer array types: |
| 3292 // rcx: value | 3315 // rcx: value |
| 3293 // For floating-point array type: | 3316 // For floating-point array type: |
| 3294 // xmm0: value as double. | 3317 // xmm0: value as double. |
| 3295 | 3318 |
| 3296 ASSERT(kSmiValueSize == 32); | 3319 ASSERT(kSmiValueSize == 32); |
| 3297 if (array_type == kExternalUnsignedIntArray) { | 3320 if (elements_kind == JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS) { |
| 3298 // For the UnsignedInt array type, we need to see whether | 3321 // For the UnsignedInt array type, we need to see whether |
| 3299 // the value can be represented in a Smi. If not, we need to convert | 3322 // the value can be represented in a Smi. If not, we need to convert |
| 3300 // it to a HeapNumber. | 3323 // it to a HeapNumber. |
| 3301 Label box_int; | 3324 Label box_int; |
| 3302 | 3325 |
| 3303 __ JumpIfUIntNotValidSmiValue(rcx, &box_int, Label::kNear); | 3326 __ JumpIfUIntNotValidSmiValue(rcx, &box_int, Label::kNear); |
| 3304 | 3327 |
| 3305 __ Integer32ToSmi(rax, rcx); | 3328 __ Integer32ToSmi(rax, rcx); |
| 3306 __ ret(0); | 3329 __ ret(0); |
| 3307 | 3330 |
| 3308 __ bind(&box_int); | 3331 __ bind(&box_int); |
| 3309 | 3332 |
| 3310 // Allocate a HeapNumber for the int and perform int-to-double | 3333 // Allocate a HeapNumber for the int and perform int-to-double |
| 3311 // conversion. | 3334 // conversion. |
| 3312 // The value is zero-extended since we loaded the value from memory | 3335 // The value is zero-extended since we loaded the value from memory |
| 3313 // with movl. | 3336 // with movl. |
| 3314 __ cvtqsi2sd(xmm0, rcx); | 3337 __ cvtqsi2sd(xmm0, rcx); |
| 3315 | 3338 |
| 3316 __ AllocateHeapNumber(rcx, rbx, &slow); | 3339 __ AllocateHeapNumber(rcx, rbx, &slow); |
| 3317 // Set the value. | 3340 // Set the value. |
| 3318 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0); | 3341 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0); |
| 3319 __ movq(rax, rcx); | 3342 __ movq(rax, rcx); |
| 3320 __ ret(0); | 3343 __ ret(0); |
| 3321 } else if (array_type == kExternalFloatArray || | 3344 } else if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS || |
| 3322 array_type == kExternalDoubleArray) { | 3345 elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) { |
| 3323 // For the floating-point array type, we need to always allocate a | 3346 // For the floating-point array type, we need to always allocate a |
| 3324 // HeapNumber. | 3347 // HeapNumber. |
| 3325 __ AllocateHeapNumber(rcx, rbx, &slow); | 3348 __ AllocateHeapNumber(rcx, rbx, &slow); |
| 3326 // Set the value. | 3349 // Set the value. |
| 3327 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0); | 3350 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0); |
| 3328 __ movq(rax, rcx); | 3351 __ movq(rax, rcx); |
| 3329 __ ret(0); | 3352 __ ret(0); |
| 3330 } else { | 3353 } else { |
| 3331 __ Integer32ToSmi(rax, rcx); | 3354 __ Integer32ToSmi(rax, rcx); |
| 3332 __ ret(0); | 3355 __ ret(0); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 3355 // -- rsp[0] : return address | 3378 // -- rsp[0] : return address |
| 3356 // ----------------------------------- | 3379 // ----------------------------------- |
| 3357 Handle<Code> miss_ic = | 3380 Handle<Code> miss_ic = |
| 3358 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); | 3381 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); |
| 3359 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | 3382 __ jmp(miss_ic, RelocInfo::CODE_TARGET); |
| 3360 } | 3383 } |
| 3361 | 3384 |
| 3362 | 3385 |
| 3363 void KeyedStoreStubCompiler::GenerateStoreExternalArray( | 3386 void KeyedStoreStubCompiler::GenerateStoreExternalArray( |
| 3364 MacroAssembler* masm, | 3387 MacroAssembler* masm, |
| 3365 ExternalArrayType array_type) { | 3388 JSObject::ElementsKind elements_kind) { |
| 3366 // ----------- S t a t e ------------- | 3389 // ----------- S t a t e ------------- |
| 3367 // -- rax : value | 3390 // -- rax : value |
| 3368 // -- rcx : key | 3391 // -- rcx : key |
| 3369 // -- rdx : receiver | 3392 // -- rdx : receiver |
| 3370 // -- rsp[0] : return address | 3393 // -- rsp[0] : return address |
| 3371 // ----------------------------------- | 3394 // ----------------------------------- |
| 3372 Label slow, miss_force_generic; | 3395 Label slow, miss_force_generic; |
| 3373 | 3396 |
| 3374 // This stub is meant to be tail-jumped to, the receiver must already | 3397 // This stub is meant to be tail-jumped to, the receiver must already |
| 3375 // have been verified by the caller to not be a smi. | 3398 // have been verified by the caller to not be a smi. |
| 3376 | 3399 |
| 3377 // Check that the key is a smi. | 3400 // Check that the key is a smi. |
| 3378 __ JumpIfNotSmi(rcx, &miss_force_generic); | 3401 __ JumpIfNotSmi(rcx, &miss_force_generic); |
| 3379 | 3402 |
| 3380 // Check that the index is in range. | 3403 // Check that the index is in range. |
| 3381 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); | 3404 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); |
| 3382 __ SmiToInteger32(rdi, rcx); // Untag the index. | 3405 __ SmiToInteger32(rdi, rcx); // Untag the index. |
| 3383 __ cmpl(rdi, FieldOperand(rbx, ExternalArray::kLengthOffset)); | 3406 __ cmpl(rdi, FieldOperand(rbx, ExternalArray::kLengthOffset)); |
| 3384 // Unsigned comparison catches both negative and too-large values. | 3407 // Unsigned comparison catches both negative and too-large values. |
| 3385 __ j(above_equal, &miss_force_generic); | 3408 __ j(above_equal, &miss_force_generic); |
| 3386 | 3409 |
| 3387 // Handle both smis and HeapNumbers in the fast path. Go to the | 3410 // Handle both smis and HeapNumbers in the fast path. Go to the |
| 3388 // runtime for all other kinds of values. | 3411 // runtime for all other kinds of values. |
| 3389 // rax: value | 3412 // rax: value |
| 3390 // rcx: key (a smi) | 3413 // rcx: key (a smi) |
| 3391 // rdx: receiver (a JSObject) | 3414 // rdx: receiver (a JSObject) |
| 3392 // rbx: elements array | 3415 // rbx: elements array |
| 3393 // rdi: untagged key | 3416 // rdi: untagged key |
| 3394 Label check_heap_number; | 3417 Label check_heap_number; |
| 3395 if (array_type == kExternalPixelArray) { | 3418 if (elements_kind == JSObject::EXTERNAL_PIXEL_ELEMENTS) { |
| 3396 // Float to pixel conversion is only implemented in the runtime for now. | 3419 // Float to pixel conversion is only implemented in the runtime for now. |
| 3397 __ JumpIfNotSmi(rax, &slow); | 3420 __ JumpIfNotSmi(rax, &slow); |
| 3398 } else { | 3421 } else { |
| 3399 __ JumpIfNotSmi(rax, &check_heap_number, Label::kNear); | 3422 __ JumpIfNotSmi(rax, &check_heap_number, Label::kNear); |
| 3400 } | 3423 } |
| 3401 // No more branches to slow case on this path. Key and receiver not needed. | 3424 // No more branches to slow case on this path. Key and receiver not needed. |
| 3402 __ SmiToInteger32(rdx, rax); | 3425 __ SmiToInteger32(rdx, rax); |
| 3403 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); | 3426 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); |
| 3404 // rbx: base pointer of external storage | 3427 // rbx: base pointer of external storage |
| 3405 switch (array_type) { | 3428 switch (elements_kind) { |
| 3406 case kExternalPixelArray: | 3429 case JSObject::EXTERNAL_PIXEL_ELEMENTS: |
| 3407 { // Clamp the value to [0..255]. | 3430 { // Clamp the value to [0..255]. |
| 3408 Label done; | 3431 Label done; |
| 3409 __ testl(rdx, Immediate(0xFFFFFF00)); | 3432 __ testl(rdx, Immediate(0xFFFFFF00)); |
| 3410 __ j(zero, &done, Label::kNear); | 3433 __ j(zero, &done, Label::kNear); |
| 3411 __ setcc(negative, rdx); // 1 if negative, 0 if positive. | 3434 __ setcc(negative, rdx); // 1 if negative, 0 if positive. |
| 3412 __ decb(rdx); // 0 if negative, 255 if positive. | 3435 __ decb(rdx); // 0 if negative, 255 if positive. |
| 3413 __ bind(&done); | 3436 __ bind(&done); |
| 3414 } | 3437 } |
| 3415 __ movb(Operand(rbx, rdi, times_1, 0), rdx); | 3438 __ movb(Operand(rbx, rdi, times_1, 0), rdx); |
| 3416 break; | 3439 break; |
| 3417 case kExternalByteArray: | 3440 case JSObject::EXTERNAL_BYTE_ELEMENTS: |
| 3418 case kExternalUnsignedByteArray: | 3441 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3419 __ movb(Operand(rbx, rdi, times_1, 0), rdx); | 3442 __ movb(Operand(rbx, rdi, times_1, 0), rdx); |
| 3420 break; | 3443 break; |
| 3421 case kExternalShortArray: | 3444 case JSObject::EXTERNAL_SHORT_ELEMENTS: |
| 3422 case kExternalUnsignedShortArray: | 3445 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3423 __ movw(Operand(rbx, rdi, times_2, 0), rdx); | 3446 __ movw(Operand(rbx, rdi, times_2, 0), rdx); |
| 3424 break; | 3447 break; |
| 3425 case kExternalIntArray: | 3448 case JSObject::EXTERNAL_INT_ELEMENTS: |
| 3426 case kExternalUnsignedIntArray: | 3449 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 3427 __ movl(Operand(rbx, rdi, times_4, 0), rdx); | 3450 __ movl(Operand(rbx, rdi, times_4, 0), rdx); |
| 3428 break; | 3451 break; |
| 3429 case kExternalFloatArray: | 3452 case JSObject::EXTERNAL_FLOAT_ELEMENTS: |
| 3430 // Need to perform int-to-float conversion. | 3453 // Need to perform int-to-float conversion. |
| 3431 __ cvtlsi2ss(xmm0, rdx); | 3454 __ cvtlsi2ss(xmm0, rdx); |
| 3432 __ movss(Operand(rbx, rdi, times_4, 0), xmm0); | 3455 __ movss(Operand(rbx, rdi, times_4, 0), xmm0); |
| 3433 break; | 3456 break; |
| 3434 case kExternalDoubleArray: | 3457 case JSObject::EXTERNAL_DOUBLE_ELEMENTS: |
| 3435 // Need to perform int-to-float conversion. | 3458 // Need to perform int-to-float conversion. |
| 3436 __ cvtlsi2sd(xmm0, rdx); | 3459 __ cvtlsi2sd(xmm0, rdx); |
| 3437 __ movsd(Operand(rbx, rdi, times_8, 0), xmm0); | 3460 __ movsd(Operand(rbx, rdi, times_8, 0), xmm0); |
| 3438 break; | 3461 break; |
| 3439 default: | 3462 case JSObject::FAST_ELEMENTS: |
| 3463 case JSObject::FAST_DOUBLE_ELEMENTS: |
| 3464 case JSObject::DICTIONARY_ELEMENTS: |
| 3465 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS: |
| 3440 UNREACHABLE(); | 3466 UNREACHABLE(); |
| 3441 break; | 3467 break; |
| 3442 } | 3468 } |
| 3443 __ ret(0); | 3469 __ ret(0); |
| 3444 | 3470 |
| 3445 // TODO(danno): handle heap number -> pixel array conversion | 3471 // TODO(danno): handle heap number -> pixel array conversion |
| 3446 if (array_type != kExternalPixelArray) { | 3472 if (elements_kind != JSObject::EXTERNAL_PIXEL_ELEMENTS) { |
| 3447 __ bind(&check_heap_number); | 3473 __ bind(&check_heap_number); |
| 3448 // rax: value | 3474 // rax: value |
| 3449 // rcx: key (a smi) | 3475 // rcx: key (a smi) |
| 3450 // rdx: receiver (a JSObject) | 3476 // rdx: receiver (a JSObject) |
| 3451 // rbx: elements array | 3477 // rbx: elements array |
| 3452 // rdi: untagged key | 3478 // rdi: untagged key |
| 3453 __ CmpObjectType(rax, HEAP_NUMBER_TYPE, kScratchRegister); | 3479 __ CmpObjectType(rax, HEAP_NUMBER_TYPE, kScratchRegister); |
| 3454 __ j(not_equal, &slow); | 3480 __ j(not_equal, &slow); |
| 3455 // No more branches to slow case on this path. | 3481 // No more branches to slow case on this path. |
| 3456 | 3482 |
| 3457 // The WebGL specification leaves the behavior of storing NaN and | 3483 // The WebGL specification leaves the behavior of storing NaN and |
| 3458 // +/-Infinity into integer arrays basically undefined. For more | 3484 // +/-Infinity into integer arrays basically undefined. For more |
| 3459 // reproducible behavior, convert these to zero. | 3485 // reproducible behavior, convert these to zero. |
| 3460 __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset)); | 3486 __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset)); |
| 3461 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); | 3487 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); |
| 3462 // rdi: untagged index | 3488 // rdi: untagged index |
| 3463 // rbx: base pointer of external storage | 3489 // rbx: base pointer of external storage |
| 3464 // top of FPU stack: value | 3490 // top of FPU stack: value |
| 3465 if (array_type == kExternalFloatArray) { | 3491 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) { |
| 3466 __ cvtsd2ss(xmm0, xmm0); | 3492 __ cvtsd2ss(xmm0, xmm0); |
| 3467 __ movss(Operand(rbx, rdi, times_4, 0), xmm0); | 3493 __ movss(Operand(rbx, rdi, times_4, 0), xmm0); |
| 3468 __ ret(0); | 3494 __ ret(0); |
| 3469 } else if (array_type == kExternalDoubleArray) { | 3495 } else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) { |
| 3470 __ movsd(Operand(rbx, rdi, times_8, 0), xmm0); | 3496 __ movsd(Operand(rbx, rdi, times_8, 0), xmm0); |
| 3471 __ ret(0); | 3497 __ ret(0); |
| 3472 } else { | 3498 } else { |
| 3473 // Perform float-to-int conversion with truncation (round-to-zero) | 3499 // Perform float-to-int conversion with truncation (round-to-zero) |
| 3474 // behavior. | 3500 // behavior. |
| 3475 | 3501 |
| 3476 // Convert to int32 and store the low byte/word. | 3502 // Convert to int32 and store the low byte/word. |
| 3477 // If the value is NaN or +/-infinity, the result is 0x80000000, | 3503 // If the value is NaN or +/-infinity, the result is 0x80000000, |
| 3478 // which is automatically zero when taken mod 2^n, n < 32. | 3504 // which is automatically zero when taken mod 2^n, n < 32. |
| 3479 // rdx: value (converted to an untagged integer) | 3505 // rdx: value (converted to an untagged integer) |
| 3480 // rdi: untagged index | 3506 // rdi: untagged index |
| 3481 // rbx: base pointer of external storage | 3507 // rbx: base pointer of external storage |
| 3482 switch (array_type) { | 3508 switch (elements_kind) { |
| 3483 case kExternalByteArray: | 3509 case JSObject::EXTERNAL_BYTE_ELEMENTS: |
| 3484 case kExternalUnsignedByteArray: | 3510 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3485 __ cvttsd2si(rdx, xmm0); | 3511 __ cvttsd2si(rdx, xmm0); |
| 3486 __ movb(Operand(rbx, rdi, times_1, 0), rdx); | 3512 __ movb(Operand(rbx, rdi, times_1, 0), rdx); |
| 3487 break; | 3513 break; |
| 3488 case kExternalShortArray: | 3514 case JSObject::EXTERNAL_SHORT_ELEMENTS: |
| 3489 case kExternalUnsignedShortArray: | 3515 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3490 __ cvttsd2si(rdx, xmm0); | 3516 __ cvttsd2si(rdx, xmm0); |
| 3491 __ movw(Operand(rbx, rdi, times_2, 0), rdx); | 3517 __ movw(Operand(rbx, rdi, times_2, 0), rdx); |
| 3492 break; | 3518 break; |
| 3493 case kExternalIntArray: | 3519 case JSObject::EXTERNAL_INT_ELEMENTS: |
| 3494 case kExternalUnsignedIntArray: { | 3520 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 3495 // Convert to int64, so that NaN and infinities become | 3521 // Convert to int64, so that NaN and infinities become |
| 3496 // 0x8000000000000000, which is zero mod 2^32. | 3522 // 0x8000000000000000, which is zero mod 2^32. |
| 3497 __ cvttsd2siq(rdx, xmm0); | 3523 __ cvttsd2siq(rdx, xmm0); |
| 3498 __ movl(Operand(rbx, rdi, times_4, 0), rdx); | 3524 __ movl(Operand(rbx, rdi, times_4, 0), rdx); |
| 3499 break; | 3525 break; |
| 3500 } | 3526 case JSObject::EXTERNAL_PIXEL_ELEMENTS: |
| 3501 default: | 3527 case JSObject::EXTERNAL_FLOAT_ELEMENTS: |
| 3528 case JSObject::EXTERNAL_DOUBLE_ELEMENTS: |
| 3529 case JSObject::FAST_ELEMENTS: |
| 3530 case JSObject::FAST_DOUBLE_ELEMENTS: |
| 3531 case JSObject::DICTIONARY_ELEMENTS: |
| 3532 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS: |
| 3502 UNREACHABLE(); | 3533 UNREACHABLE(); |
| 3503 break; | 3534 break; |
| 3504 } | 3535 } |
| 3505 __ ret(0); | 3536 __ ret(0); |
| 3506 } | 3537 } |
| 3507 } | 3538 } |
| 3508 | 3539 |
| 3509 // Slow case: call runtime. | 3540 // Slow case: call runtime. |
| 3510 __ bind(&slow); | 3541 __ bind(&slow); |
| 3511 | 3542 |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3625 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | 3656 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
| 3626 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); | 3657 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); |
| 3627 } | 3658 } |
| 3628 | 3659 |
| 3629 | 3660 |
| 3630 #undef __ | 3661 #undef __ |
| 3631 | 3662 |
| 3632 } } // namespace v8::internal | 3663 } } // namespace v8::internal |
| 3633 | 3664 |
| 3634 #endif // V8_TARGET_ARCH_X64 | 3665 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |