OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 Register prototype) { | 268 Register prototype) { |
269 __ LoadGlobalFunction(index, prototype); | 269 __ LoadGlobalFunction(index, prototype); |
270 __ LoadGlobalFunctionInitialMap(prototype, prototype); | 270 __ LoadGlobalFunctionInitialMap(prototype, prototype); |
271 // Load the prototype from the initial map. | 271 // Load the prototype from the initial map. |
272 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); | 272 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); |
273 } | 273 } |
274 | 274 |
275 | 275 |
276 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( | 276 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( |
277 MacroAssembler* masm, int index, Register prototype, Label* miss) { | 277 MacroAssembler* masm, int index, Register prototype, Label* miss) { |
| 278 Isolate* isolate = masm->isolate(); |
278 // Check we're still in the same context. | 279 // Check we're still in the same context. |
279 __ cmp(Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)), | 280 __ cmp(Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)), |
280 Isolate::Current()->global()); | 281 isolate->global()); |
281 __ j(not_equal, miss); | 282 __ j(not_equal, miss); |
282 // Get the global function with the given index. | 283 // Get the global function with the given index. |
283 JSFunction* function = JSFunction::cast( | 284 JSFunction* function = |
284 Isolate::Current()->global_context()->get(index)); | 285 JSFunction::cast(isolate->global_context()->get(index)); |
285 // Load its initial map. The global functions all have initial maps. | 286 // Load its initial map. The global functions all have initial maps. |
286 __ Set(prototype, Immediate(Handle<Map>(function->initial_map()))); | 287 __ Set(prototype, Immediate(Handle<Map>(function->initial_map()))); |
287 // Load the prototype from the initial map. | 288 // Load the prototype from the initial map. |
288 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); | 289 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); |
289 } | 290 } |
290 | 291 |
291 | 292 |
292 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, | 293 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, |
293 Register receiver, | 294 Register receiver, |
294 Register scratch, | 295 Register scratch, |
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
741 StubCompiler* stub_compiler_; | 742 StubCompiler* stub_compiler_; |
742 const ParameterCount& arguments_; | 743 const ParameterCount& arguments_; |
743 Register name_; | 744 Register name_; |
744 }; | 745 }; |
745 | 746 |
746 | 747 |
747 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { | 748 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { |
748 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); | 749 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); |
749 Code* code = NULL; | 750 Code* code = NULL; |
750 if (kind == Code::LOAD_IC) { | 751 if (kind == Code::LOAD_IC) { |
751 code = Isolate::Current()->builtins()->builtin(Builtins::LoadIC_Miss); | 752 code = masm->isolate()->builtins()->builtin(Builtins::kLoadIC_Miss); |
752 } else { | 753 } else { |
753 code = Isolate::Current()->builtins()->builtin(Builtins::KeyedLoadIC_Miss); | 754 code = masm->isolate()->builtins()->builtin(Builtins::kKeyedLoadIC_Miss); |
754 } | 755 } |
755 | 756 |
756 Handle<Code> ic(code); | 757 Handle<Code> ic(code); |
757 __ jmp(ic, RelocInfo::CODE_TARGET); | 758 __ jmp(ic, RelocInfo::CODE_TARGET); |
758 } | 759 } |
759 | 760 |
760 | 761 |
761 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 762 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
762 // but may be destroyed if store is successful. | 763 // but may be destroyed if store is successful. |
763 void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 764 void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
(...skipping 589 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1353 __ j(not_equal, miss, not_taken); | 1354 __ j(not_equal, miss, not_taken); |
1354 } else { | 1355 } else { |
1355 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function))); | 1356 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function))); |
1356 __ j(not_equal, miss, not_taken); | 1357 __ j(not_equal, miss, not_taken); |
1357 } | 1358 } |
1358 } | 1359 } |
1359 | 1360 |
1360 | 1361 |
1361 MaybeObject* CallStubCompiler::GenerateMissBranch() { | 1362 MaybeObject* CallStubCompiler::GenerateMissBranch() { |
1362 MaybeObject* maybe_obj = | 1363 MaybeObject* maybe_obj = |
1363 Isolate::Current()->stub_cache()->ComputeCallMiss( | 1364 masm()->isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), |
1364 arguments().immediate(), kind_); | 1365 kind_); |
1365 Object* obj; | 1366 Object* obj; |
1366 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1367 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
1367 __ jmp(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); | 1368 __ jmp(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); |
1368 return obj; | 1369 return obj; |
1369 } | 1370 } |
1370 | 1371 |
1371 | 1372 |
1372 MUST_USE_RESULT MaybeObject* CallStubCompiler::CompileCallField( | 1373 MUST_USE_RESULT MaybeObject* CallStubCompiler::CompileCallField( |
1373 JSObject* object, | 1374 JSObject* object, |
1374 JSObject* holder, | 1375 JSObject* holder, |
(...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1906 JSFunction* function, | 1907 JSFunction* function, |
1907 String* name) { | 1908 String* name) { |
1908 // ----------- S t a t e ------------- | 1909 // ----------- S t a t e ------------- |
1909 // -- ecx : name | 1910 // -- ecx : name |
1910 // -- esp[0] : return address | 1911 // -- esp[0] : return address |
1911 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1912 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1912 // -- ... | 1913 // -- ... |
1913 // -- esp[(argc + 1) * 4] : receiver | 1914 // -- esp[(argc + 1) * 4] : receiver |
1914 // ----------------------------------- | 1915 // ----------------------------------- |
1915 | 1916 |
1916 if (!Isolate::Current()->cpu_features()->IsSupported(SSE2)) | 1917 if (masm()->isolate()->cpu_features()->IsSupported(SSE2)) |
1917 return HEAP->undefined_value(); | 1918 return HEAP->undefined_value(); |
1918 CpuFeatures::Scope use_sse2(SSE2); | 1919 CpuFeatures::Scope use_sse2(SSE2); |
1919 | 1920 |
1920 const int argc = arguments().immediate(); | 1921 const int argc = arguments().immediate(); |
1921 | 1922 |
1922 // If the object is not a JSObject or we got an unexpected number of | 1923 // If the object is not a JSObject or we got an unexpected number of |
1923 // arguments, bail out to the regular call. | 1924 // arguments, bail out to the regular call. |
1924 if (!object->IsJSObject() || argc != 1) return HEAP->undefined_value(); | 1925 if (!object->IsJSObject() || argc != 1) return HEAP->undefined_value(); |
1925 | 1926 |
1926 Label miss; | 1927 Label miss; |
(...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2476 GenerateStoreField(masm(), | 2477 GenerateStoreField(masm(), |
2477 object, | 2478 object, |
2478 index, | 2479 index, |
2479 transition, | 2480 transition, |
2480 edx, ecx, ebx, | 2481 edx, ecx, ebx, |
2481 &miss); | 2482 &miss); |
2482 | 2483 |
2483 // Handle store cache miss. | 2484 // Handle store cache miss. |
2484 __ bind(&miss); | 2485 __ bind(&miss); |
2485 __ mov(ecx, Immediate(Handle<String>(name))); // restore name | 2486 __ mov(ecx, Immediate(Handle<String>(name))); // restore name |
2486 Handle<Code> ic(Isolate::Current()->builtins()->builtin( | 2487 Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); |
2487 Builtins::StoreIC_Miss)); | |
2488 __ jmp(ic, RelocInfo::CODE_TARGET); | 2488 __ jmp(ic, RelocInfo::CODE_TARGET); |
2489 | 2489 |
2490 // Return the generated code. | 2490 // Return the generated code. |
2491 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); | 2491 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); |
2492 } | 2492 } |
2493 | 2493 |
2494 | 2494 |
2495 MaybeObject* StoreStubCompiler::CompileStoreCallback(JSObject* object, | 2495 MaybeObject* StoreStubCompiler::CompileStoreCallback(JSObject* object, |
2496 AccessorInfo* callback, | 2496 AccessorInfo* callback, |
2497 String* name) { | 2497 String* name) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2529 __ push(ebx); // restore return address | 2529 __ push(ebx); // restore return address |
2530 | 2530 |
2531 // Do tail-call to the runtime system. | 2531 // Do tail-call to the runtime system. |
2532 Isolate* isolate = masm()->isolate(); | 2532 Isolate* isolate = masm()->isolate(); |
2533 ExternalReference store_callback_property = | 2533 ExternalReference store_callback_property = |
2534 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate); | 2534 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate); |
2535 __ TailCallExternalReference(store_callback_property, 4, 1); | 2535 __ TailCallExternalReference(store_callback_property, 4, 1); |
2536 | 2536 |
2537 // Handle store cache miss. | 2537 // Handle store cache miss. |
2538 __ bind(&miss); | 2538 __ bind(&miss); |
2539 Handle<Code> ic(isolate->builtins()->builtin(Builtins::StoreIC_Miss)); | 2539 Handle<Code> ic = isolate->builtins()->StoreIC_Miss(); |
2540 __ jmp(ic, RelocInfo::CODE_TARGET); | 2540 __ jmp(ic, RelocInfo::CODE_TARGET); |
2541 | 2541 |
2542 // Return the generated code. | 2542 // Return the generated code. |
2543 return GetCode(CALLBACKS, name); | 2543 return GetCode(CALLBACKS, name); |
2544 } | 2544 } |
2545 | 2545 |
2546 | 2546 |
2547 MaybeObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, | 2547 MaybeObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, |
2548 String* name) { | 2548 String* name) { |
2549 // ----------- S t a t e ------------- | 2549 // ----------- S t a t e ------------- |
(...skipping 30 matching lines...) Expand all Loading... |
2580 __ push(ebx); // restore return address | 2580 __ push(ebx); // restore return address |
2581 | 2581 |
2582 // Do tail-call to the runtime system. | 2582 // Do tail-call to the runtime system. |
2583 Isolate* isolate = masm()->isolate(); | 2583 Isolate* isolate = masm()->isolate(); |
2584 ExternalReference store_ic_property = | 2584 ExternalReference store_ic_property = |
2585 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate); | 2585 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate); |
2586 __ TailCallExternalReference(store_ic_property, 4, 1); | 2586 __ TailCallExternalReference(store_ic_property, 4, 1); |
2587 | 2587 |
2588 // Handle store cache miss. | 2588 // Handle store cache miss. |
2589 __ bind(&miss); | 2589 __ bind(&miss); |
2590 Handle<Code> ic(isolate->builtins()->builtin(Builtins::StoreIC_Miss)); | 2590 Handle<Code> ic = isolate->builtins()->StoreIC_Miss(); |
2591 __ jmp(ic, RelocInfo::CODE_TARGET); | 2591 __ jmp(ic, RelocInfo::CODE_TARGET); |
2592 | 2592 |
2593 // Return the generated code. | 2593 // Return the generated code. |
2594 return GetCode(INTERCEPTOR, name); | 2594 return GetCode(INTERCEPTOR, name); |
2595 } | 2595 } |
2596 | 2596 |
2597 | 2597 |
2598 MaybeObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, | 2598 MaybeObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, |
2599 JSGlobalPropertyCell* cell, | 2599 JSGlobalPropertyCell* cell, |
2600 String* name) { | 2600 String* name) { |
(...skipping 29 matching lines...) Expand all Loading... |
2630 __ mov(cell_operand, eax); | 2630 __ mov(cell_operand, eax); |
2631 | 2631 |
2632 // Return the value (register eax). | 2632 // Return the value (register eax). |
2633 Counters* counters = masm()->isolate()->counters(); | 2633 Counters* counters = masm()->isolate()->counters(); |
2634 __ IncrementCounter(counters->named_store_global_inline(), 1); | 2634 __ IncrementCounter(counters->named_store_global_inline(), 1); |
2635 __ ret(0); | 2635 __ ret(0); |
2636 | 2636 |
2637 // Handle store cache miss. | 2637 // Handle store cache miss. |
2638 __ bind(&miss); | 2638 __ bind(&miss); |
2639 __ IncrementCounter(counters->named_store_global_inline_miss(), 1); | 2639 __ IncrementCounter(counters->named_store_global_inline_miss(), 1); |
2640 Handle<Code> ic(Isolate::Current()->builtins()->builtin( | 2640 Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); |
2641 Builtins::StoreIC_Miss)); | |
2642 __ jmp(ic, RelocInfo::CODE_TARGET); | 2641 __ jmp(ic, RelocInfo::CODE_TARGET); |
2643 | 2642 |
2644 // Return the generated code. | 2643 // Return the generated code. |
2645 return GetCode(NORMAL, name); | 2644 return GetCode(NORMAL, name); |
2646 } | 2645 } |
2647 | 2646 |
2648 | 2647 |
2649 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, | 2648 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, |
2650 int index, | 2649 int index, |
2651 Map* transition, | 2650 Map* transition, |
(...skipping 17 matching lines...) Expand all Loading... |
2669 GenerateStoreField(masm(), | 2668 GenerateStoreField(masm(), |
2670 object, | 2669 object, |
2671 index, | 2670 index, |
2672 transition, | 2671 transition, |
2673 edx, ecx, ebx, | 2672 edx, ecx, ebx, |
2674 &miss); | 2673 &miss); |
2675 | 2674 |
2676 // Handle store cache miss. | 2675 // Handle store cache miss. |
2677 __ bind(&miss); | 2676 __ bind(&miss); |
2678 __ DecrementCounter(counters->keyed_store_field(), 1); | 2677 __ DecrementCounter(counters->keyed_store_field(), 1); |
2679 Handle<Code> ic(Isolate::Current()->builtins()->builtin( | 2678 Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss(); |
2680 Builtins::KeyedStoreIC_Miss)); | |
2681 __ jmp(ic, RelocInfo::CODE_TARGET); | 2679 __ jmp(ic, RelocInfo::CODE_TARGET); |
2682 | 2680 |
2683 // Return the generated code. | 2681 // Return the generated code. |
2684 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); | 2682 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); |
2685 } | 2683 } |
2686 | 2684 |
2687 | 2685 |
2688 MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized( | 2686 MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized( |
2689 JSObject* receiver) { | 2687 JSObject* receiver) { |
2690 // ----------- S t a t e ------------- | 2688 // ----------- S t a t e ------------- |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2727 // the value in register eax. | 2725 // the value in register eax. |
2728 __ mov(edx, Operand(eax)); | 2726 __ mov(edx, Operand(eax)); |
2729 __ mov(FieldOperand(edi, ecx, times_2, FixedArray::kHeaderSize), eax); | 2727 __ mov(FieldOperand(edi, ecx, times_2, FixedArray::kHeaderSize), eax); |
2730 __ RecordWrite(edi, 0, edx, ecx); | 2728 __ RecordWrite(edi, 0, edx, ecx); |
2731 | 2729 |
2732 // Done. | 2730 // Done. |
2733 __ ret(0); | 2731 __ ret(0); |
2734 | 2732 |
2735 // Handle store cache miss. | 2733 // Handle store cache miss. |
2736 __ bind(&miss); | 2734 __ bind(&miss); |
2737 Handle<Code> ic( | 2735 Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss(); |
2738 Isolate::Current()->builtins()->builtin(Builtins::KeyedStoreIC_Miss)); | |
2739 __ jmp(ic, RelocInfo::CODE_TARGET); | 2736 __ jmp(ic, RelocInfo::CODE_TARGET); |
2740 | 2737 |
2741 // Return the generated code. | 2738 // Return the generated code. |
2742 return GetCode(NORMAL, NULL); | 2739 return GetCode(NORMAL, NULL); |
2743 } | 2740 } |
2744 | 2741 |
2745 | 2742 |
2746 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, | 2743 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, |
2747 JSObject* object, | 2744 JSObject* object, |
2748 JSObject* last) { | 2745 JSObject* last) { |
(...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3277 // depending on the this.x = ...; assignment in the function. | 3274 // depending on the this.x = ...; assignment in the function. |
3278 SharedFunctionInfo* shared = function->shared(); | 3275 SharedFunctionInfo* shared = function->shared(); |
3279 for (int i = 0; i < shared->this_property_assignments_count(); i++) { | 3276 for (int i = 0; i < shared->this_property_assignments_count(); i++) { |
3280 if (shared->IsThisPropertyAssignmentArgument(i)) { | 3277 if (shared->IsThisPropertyAssignmentArgument(i)) { |
3281 // Check if the argument assigned to the property is actually passed. | 3278 // Check if the argument assigned to the property is actually passed. |
3282 // If argument is not passed the property is set to undefined, | 3279 // If argument is not passed the property is set to undefined, |
3283 // otherwise find it on the stack. | 3280 // otherwise find it on the stack. |
3284 int arg_number = shared->GetThisPropertyAssignmentArgument(i); | 3281 int arg_number = shared->GetThisPropertyAssignmentArgument(i); |
3285 __ mov(ebx, edi); | 3282 __ mov(ebx, edi); |
3286 __ cmp(eax, arg_number); | 3283 __ cmp(eax, arg_number); |
3287 if (Isolate::Current()->cpu_features()->IsSupported(CMOV)) { | 3284 if (masm()->isolate()->cpu_features()->IsSupported(CMOV)) { |
3288 CpuFeatures::Scope use_cmov(CMOV); | 3285 CpuFeatures::Scope use_cmov(CMOV); |
3289 __ cmov(above, ebx, Operand(ecx, arg_number * -kPointerSize)); | 3286 __ cmov(above, ebx, Operand(ecx, arg_number * -kPointerSize)); |
3290 } else { | 3287 } else { |
3291 Label not_passed; | 3288 Label not_passed; |
3292 __ j(below_equal, ¬_passed); | 3289 __ j(below_equal, ¬_passed); |
3293 __ mov(ebx, Operand(ecx, arg_number * -kPointerSize)); | 3290 __ mov(ebx, Operand(ecx, arg_number * -kPointerSize)); |
3294 __ bind(¬_passed); | 3291 __ bind(¬_passed); |
3295 } | 3292 } |
3296 // Store value in the property. | 3293 // Store value in the property. |
3297 __ mov(Operand(edx, i * kPointerSize), ebx); | 3294 __ mov(Operand(edx, i * kPointerSize), ebx); |
(...skipping 22 matching lines...) Expand all Loading... |
3320 __ lea(esp, Operand(esp, ebx, times_pointer_size, 1 * kPointerSize)); | 3317 __ lea(esp, Operand(esp, ebx, times_pointer_size, 1 * kPointerSize)); |
3321 __ push(ecx); | 3318 __ push(ecx); |
3322 Counters* counters = masm()->isolate()->counters(); | 3319 Counters* counters = masm()->isolate()->counters(); |
3323 __ IncrementCounter(counters->constructed_objects(), 1); | 3320 __ IncrementCounter(counters->constructed_objects(), 1); |
3324 __ IncrementCounter(counters->constructed_objects_stub(), 1); | 3321 __ IncrementCounter(counters->constructed_objects_stub(), 1); |
3325 __ ret(0); | 3322 __ ret(0); |
3326 | 3323 |
3327 // Jump to the generic stub in case the specialized code cannot handle the | 3324 // Jump to the generic stub in case the specialized code cannot handle the |
3328 // construction. | 3325 // construction. |
3329 __ bind(&generic_stub_call); | 3326 __ bind(&generic_stub_call); |
3330 Code* code = Isolate::Current()->builtins()->builtin( | 3327 Handle<Code> generic_construct_stub = |
3331 Builtins::JSConstructStubGeneric); | 3328 masm()->isolate()->builtins()->JSConstructStubGeneric(); |
3332 Handle<Code> generic_construct_stub(code); | |
3333 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); | 3329 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); |
3334 | 3330 |
3335 // Return the generated code. | 3331 // Return the generated code. |
3336 return GetCode(); | 3332 return GetCode(); |
3337 } | 3333 } |
3338 | 3334 |
3339 | 3335 |
3340 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( | 3336 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( |
3341 JSObject*receiver, ExternalArrayType array_type, Code::Flags flags) { | 3337 JSObject*receiver, ExternalArrayType array_type, Code::Flags flags) { |
3342 // ----------- S t a t e ------------- | 3338 // ----------- S t a t e ------------- |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3597 __ fstp_s(Operand(edi, ebx, times_4, 0)); | 3593 __ fstp_s(Operand(edi, ebx, times_4, 0)); |
3598 __ ret(0); | 3594 __ ret(0); |
3599 } else { | 3595 } else { |
3600 // Perform float-to-int conversion with truncation (round-to-zero) | 3596 // Perform float-to-int conversion with truncation (round-to-zero) |
3601 // behavior. | 3597 // behavior. |
3602 | 3598 |
3603 // For the moment we make the slow call to the runtime on | 3599 // For the moment we make the slow call to the runtime on |
3604 // processors that don't support SSE2. The code in IntegerConvert | 3600 // processors that don't support SSE2. The code in IntegerConvert |
3605 // (code-stubs-ia32.cc) is roughly what is needed here though the | 3601 // (code-stubs-ia32.cc) is roughly what is needed here though the |
3606 // conversion failure case does not need to be handled. | 3602 // conversion failure case does not need to be handled. |
3607 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) { | 3603 if (masm()->isolate()->cpu_features()->IsSupported(SSE2)) { |
3608 if (array_type != kExternalIntArray && | 3604 if (array_type != kExternalIntArray && |
3609 array_type != kExternalUnsignedIntArray) { | 3605 array_type != kExternalUnsignedIntArray) { |
3610 ASSERT(Isolate::Current()->cpu_features()->IsSupported(SSE2)); | 3606 ASSERT(masm()->isolate()->cpu_features()->IsSupported(SSE2)); |
3611 CpuFeatures::Scope scope(SSE2); | 3607 CpuFeatures::Scope scope(SSE2); |
3612 __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset)); | 3608 __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset)); |
3613 // ecx: untagged integer value | 3609 // ecx: untagged integer value |
3614 switch (array_type) { | 3610 switch (array_type) { |
3615 case kExternalPixelArray: | 3611 case kExternalPixelArray: |
3616 { // Clamp the value to [0..255]. | 3612 { // Clamp the value to [0..255]. |
3617 NearLabel done; | 3613 NearLabel done; |
3618 __ test(ecx, Immediate(0xFFFFFF00)); | 3614 __ test(ecx, Immediate(0xFFFFFF00)); |
3619 __ j(zero, &done); | 3615 __ j(zero, &done); |
3620 __ setcc(negative, ecx); // 1 if negative, 0 if positive. | 3616 __ setcc(negative, ecx); // 1 if negative, 0 if positive. |
3621 __ dec_b(ecx); // 0 if negative, 255 if positive. | 3617 __ dec_b(ecx); // 0 if negative, 255 if positive. |
3622 __ bind(&done); | 3618 __ bind(&done); |
3623 } | 3619 } |
3624 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); | 3620 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
3625 case kExternalByteArray: | 3621 case kExternalByteArray: |
3626 case kExternalUnsignedByteArray: | 3622 case kExternalUnsignedByteArray: |
3627 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); | 3623 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
3628 break; | 3624 break; |
3629 case kExternalShortArray: | 3625 case kExternalShortArray: |
3630 case kExternalUnsignedShortArray: | 3626 case kExternalUnsignedShortArray: |
3631 __ mov_w(Operand(edi, ebx, times_2, 0), ecx); | 3627 __ mov_w(Operand(edi, ebx, times_2, 0), ecx); |
3632 break; | 3628 break; |
3633 default: | 3629 default: |
3634 UNREACHABLE(); | 3630 UNREACHABLE(); |
3635 break; | 3631 break; |
3636 } | 3632 } |
3637 } else { | 3633 } else { |
3638 if (Isolate::Current()->cpu_features()->IsSupported(SSE3)) { | 3634 if (masm()->isolate()->cpu_features()->IsSupported(SSE3)) { |
3639 CpuFeatures::Scope scope(SSE3); | 3635 CpuFeatures::Scope scope(SSE3); |
3640 // fisttp stores values as signed integers. To represent the | 3636 // fisttp stores values as signed integers. To represent the |
3641 // entire range of int and unsigned int arrays, store as a | 3637 // entire range of int and unsigned int arrays, store as a |
3642 // 64-bit int and discard the high 32 bits. | 3638 // 64-bit int and discard the high 32 bits. |
3643 // If the value is NaN or +/-infinity, the result is 0x80000000, | 3639 // If the value is NaN or +/-infinity, the result is 0x80000000, |
3644 // which is automatically zero when taken mod 2^n, n < 32. | 3640 // which is automatically zero when taken mod 2^n, n < 32. |
3645 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 3641 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
3646 __ sub(Operand(esp), Immediate(2 * kPointerSize)); | 3642 __ sub(Operand(esp), Immediate(2 * kPointerSize)); |
3647 __ fisttp_d(Operand(esp, 0)); | 3643 __ fisttp_d(Operand(esp, 0)); |
3648 __ pop(ecx); | 3644 __ pop(ecx); |
3649 __ add(Operand(esp), Immediate(kPointerSize)); | 3645 __ add(Operand(esp), Immediate(kPointerSize)); |
3650 } else { | 3646 } else { |
3651 ASSERT(Isolate::Current()->cpu_features()->IsSupported(SSE2)); | 3647 ASSERT(masm()->isolate()->cpu_features()->IsSupported(SSE2)); |
3652 CpuFeatures::Scope scope(SSE2); | 3648 CpuFeatures::Scope scope(SSE2); |
3653 // We can easily implement the correct rounding behavior for the | 3649 // We can easily implement the correct rounding behavior for the |
3654 // range [0, 2^31-1]. For the time being, to keep this code simple, | 3650 // range [0, 2^31-1]. For the time being, to keep this code simple, |
3655 // make the slow runtime call for values outside this range. | 3651 // make the slow runtime call for values outside this range. |
3656 // Note: we could do better for signed int arrays. | 3652 // Note: we could do better for signed int arrays. |
3657 __ movd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); | 3653 __ movd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); |
3658 // We will need the key if we have to make the slow runtime call. | 3654 // We will need the key if we have to make the slow runtime call. |
3659 __ push(ecx); | 3655 __ push(ecx); |
3660 __ LoadPowerOf2(xmm1, ecx, 31); | 3656 __ LoadPowerOf2(xmm1, ecx, 31); |
3661 __ pop(ecx); | 3657 __ pop(ecx); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3694 | 3690 |
3695 return GetCode(flags); | 3691 return GetCode(flags); |
3696 } | 3692 } |
3697 | 3693 |
3698 | 3694 |
3699 #undef __ | 3695 #undef __ |
3700 | 3696 |
3701 } } // namespace v8::internal | 3697 } } // namespace v8::internal |
3702 | 3698 |
3703 #endif // V8_TARGET_ARCH_IA32 | 3699 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |