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

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

Issue 7348008: Merge up to 8597 to experimental/gc from the bleeding edge. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: '' Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/regexp-macro-assembler-x64.h ('k') | test/cctest/SConscript » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/x64/regexp-macro-assembler-x64.h ('k') | test/cctest/SConscript » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698