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 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 Register prototype) { | 267 Register prototype) { |
268 __ LoadGlobalFunction(index, prototype); | 268 __ LoadGlobalFunction(index, prototype); |
269 __ LoadGlobalFunctionInitialMap(prototype, prototype); | 269 __ LoadGlobalFunctionInitialMap(prototype, prototype); |
270 // Load the prototype from the initial map. | 270 // Load the prototype from the initial map. |
271 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); | 271 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); |
272 } | 272 } |
273 | 273 |
274 | 274 |
275 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( | 275 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( |
276 MacroAssembler* masm, int index, Register prototype, Label* miss) { | 276 MacroAssembler* masm, int index, Register prototype, Label* miss) { |
| 277 Isolate* isolate = masm->isolate(); |
277 // Check we're still in the same context. | 278 // Check we're still in the same context. |
278 __ cmp(Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)), | 279 __ cmp(Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)), |
279 Isolate::Current()->global()); | 280 isolate->global()); |
280 __ j(not_equal, miss); | 281 __ j(not_equal, miss); |
281 // Get the global function with the given index. | 282 // Get the global function with the given index. |
282 JSFunction* function = JSFunction::cast( | 283 JSFunction* function = |
283 Isolate::Current()->global_context()->get(index)); | 284 JSFunction::cast(isolate->global_context()->get(index)); |
284 // Load its initial map. The global functions all have initial maps. | 285 // Load its initial map. The global functions all have initial maps. |
285 __ Set(prototype, Immediate(Handle<Map>(function->initial_map()))); | 286 __ Set(prototype, Immediate(Handle<Map>(function->initial_map()))); |
286 // Load the prototype from the initial map. | 287 // Load the prototype from the initial map. |
287 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); | 288 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); |
288 } | 289 } |
289 | 290 |
290 | 291 |
291 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, | 292 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, |
292 Register receiver, | 293 Register receiver, |
293 Register scratch, | 294 Register scratch, |
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
739 StubCompiler* stub_compiler_; | 740 StubCompiler* stub_compiler_; |
740 const ParameterCount& arguments_; | 741 const ParameterCount& arguments_; |
741 Register name_; | 742 Register name_; |
742 }; | 743 }; |
743 | 744 |
744 | 745 |
745 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { | 746 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { |
746 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); | 747 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); |
747 Code* code = NULL; | 748 Code* code = NULL; |
748 if (kind == Code::LOAD_IC) { | 749 if (kind == Code::LOAD_IC) { |
749 code = Isolate::Current()->builtins()->builtin(Builtins::LoadIC_Miss); | 750 code = masm->isolate()->builtins()->builtin(Builtins::kLoadIC_Miss); |
750 } else { | 751 } else { |
751 code = Isolate::Current()->builtins()->builtin(Builtins::KeyedLoadIC_Miss); | 752 code = masm->isolate()->builtins()->builtin(Builtins::kKeyedLoadIC_Miss); |
752 } | 753 } |
753 | 754 |
754 Handle<Code> ic(code); | 755 Handle<Code> ic(code); |
755 __ jmp(ic, RelocInfo::CODE_TARGET); | 756 __ jmp(ic, RelocInfo::CODE_TARGET); |
756 } | 757 } |
757 | 758 |
758 | 759 |
759 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 760 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
760 // but may be destroyed if store is successful. | 761 // but may be destroyed if store is successful. |
761 void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 762 void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
(...skipping 589 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1351 __ j(not_equal, miss, not_taken); | 1352 __ j(not_equal, miss, not_taken); |
1352 } else { | 1353 } else { |
1353 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function))); | 1354 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function))); |
1354 __ j(not_equal, miss, not_taken); | 1355 __ j(not_equal, miss, not_taken); |
1355 } | 1356 } |
1356 } | 1357 } |
1357 | 1358 |
1358 | 1359 |
1359 MaybeObject* CallStubCompiler::GenerateMissBranch() { | 1360 MaybeObject* CallStubCompiler::GenerateMissBranch() { |
1360 MaybeObject* maybe_obj = | 1361 MaybeObject* maybe_obj = |
1361 Isolate::Current()->stub_cache()->ComputeCallMiss( | 1362 masm()->isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), |
1362 arguments().immediate(), kind_); | 1363 kind_); |
1363 Object* obj; | 1364 Object* obj; |
1364 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1365 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
1365 __ jmp(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); | 1366 __ jmp(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); |
1366 return obj; | 1367 return obj; |
1367 } | 1368 } |
1368 | 1369 |
1369 | 1370 |
1370 MUST_USE_RESULT MaybeObject* CallStubCompiler::CompileCallField( | 1371 MUST_USE_RESULT MaybeObject* CallStubCompiler::CompileCallField( |
1371 JSObject* object, | 1372 JSObject* object, |
1372 JSObject* holder, | 1373 JSObject* holder, |
(...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1904 JSFunction* function, | 1905 JSFunction* function, |
1905 String* name) { | 1906 String* name) { |
1906 // ----------- S t a t e ------------- | 1907 // ----------- S t a t e ------------- |
1907 // -- ecx : name | 1908 // -- ecx : name |
1908 // -- esp[0] : return address | 1909 // -- esp[0] : return address |
1909 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1910 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1910 // -- ... | 1911 // -- ... |
1911 // -- esp[(argc + 1) * 4] : receiver | 1912 // -- esp[(argc + 1) * 4] : receiver |
1912 // ----------------------------------- | 1913 // ----------------------------------- |
1913 | 1914 |
1914 if (!Isolate::Current()->cpu_features()->IsSupported(SSE2)) | 1915 if (masm()->isolate()->cpu_features()->IsSupported(SSE2)) |
1915 return HEAP->undefined_value(); | 1916 return HEAP->undefined_value(); |
1916 CpuFeatures::Scope use_sse2(SSE2); | 1917 CpuFeatures::Scope use_sse2(SSE2); |
1917 | 1918 |
1918 const int argc = arguments().immediate(); | 1919 const int argc = arguments().immediate(); |
1919 | 1920 |
1920 // If the object is not a JSObject or we got an unexpected number of | 1921 // If the object is not a JSObject or we got an unexpected number of |
1921 // arguments, bail out to the regular call. | 1922 // arguments, bail out to the regular call. |
1922 if (!object->IsJSObject() || argc != 1) return HEAP->undefined_value(); | 1923 if (!object->IsJSObject() || argc != 1) return HEAP->undefined_value(); |
1923 | 1924 |
1924 Label miss; | 1925 Label miss; |
(...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2472 GenerateStoreField(masm(), | 2473 GenerateStoreField(masm(), |
2473 object, | 2474 object, |
2474 index, | 2475 index, |
2475 transition, | 2476 transition, |
2476 edx, ecx, ebx, | 2477 edx, ecx, ebx, |
2477 &miss); | 2478 &miss); |
2478 | 2479 |
2479 // Handle store cache miss. | 2480 // Handle store cache miss. |
2480 __ bind(&miss); | 2481 __ bind(&miss); |
2481 __ mov(ecx, Immediate(Handle<String>(name))); // restore name | 2482 __ mov(ecx, Immediate(Handle<String>(name))); // restore name |
2482 Handle<Code> ic(Isolate::Current()->builtins()->builtin( | 2483 Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); |
2483 Builtins::StoreIC_Miss)); | |
2484 __ jmp(ic, RelocInfo::CODE_TARGET); | 2484 __ jmp(ic, RelocInfo::CODE_TARGET); |
2485 | 2485 |
2486 // Return the generated code. | 2486 // Return the generated code. |
2487 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); | 2487 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); |
2488 } | 2488 } |
2489 | 2489 |
2490 | 2490 |
2491 MaybeObject* StoreStubCompiler::CompileStoreCallback(JSObject* object, | 2491 MaybeObject* StoreStubCompiler::CompileStoreCallback(JSObject* object, |
2492 AccessorInfo* callback, | 2492 AccessorInfo* callback, |
2493 String* name) { | 2493 String* name) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2525 __ push(ebx); // restore return address | 2525 __ push(ebx); // restore return address |
2526 | 2526 |
2527 // Do tail-call to the runtime system. | 2527 // Do tail-call to the runtime system. |
2528 Isolate* isolate = masm()->isolate(); | 2528 Isolate* isolate = masm()->isolate(); |
2529 ExternalReference store_callback_property = | 2529 ExternalReference store_callback_property = |
2530 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate); | 2530 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate); |
2531 __ TailCallExternalReference(store_callback_property, 4, 1); | 2531 __ TailCallExternalReference(store_callback_property, 4, 1); |
2532 | 2532 |
2533 // Handle store cache miss. | 2533 // Handle store cache miss. |
2534 __ bind(&miss); | 2534 __ bind(&miss); |
2535 Handle<Code> ic(isolate->builtins()->builtin(Builtins::StoreIC_Miss)); | 2535 Handle<Code> ic = isolate->builtins()->StoreIC_Miss(); |
2536 __ jmp(ic, RelocInfo::CODE_TARGET); | 2536 __ jmp(ic, RelocInfo::CODE_TARGET); |
2537 | 2537 |
2538 // Return the generated code. | 2538 // Return the generated code. |
2539 return GetCode(CALLBACKS, name); | 2539 return GetCode(CALLBACKS, name); |
2540 } | 2540 } |
2541 | 2541 |
2542 | 2542 |
2543 MaybeObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, | 2543 MaybeObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, |
2544 String* name) { | 2544 String* name) { |
2545 // ----------- S t a t e ------------- | 2545 // ----------- S t a t e ------------- |
(...skipping 30 matching lines...) Expand all Loading... |
2576 __ push(ebx); // restore return address | 2576 __ push(ebx); // restore return address |
2577 | 2577 |
2578 // Do tail-call to the runtime system. | 2578 // Do tail-call to the runtime system. |
2579 Isolate* isolate = masm()->isolate(); | 2579 Isolate* isolate = masm()->isolate(); |
2580 ExternalReference store_ic_property = | 2580 ExternalReference store_ic_property = |
2581 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate); | 2581 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate); |
2582 __ TailCallExternalReference(store_ic_property, 4, 1); | 2582 __ TailCallExternalReference(store_ic_property, 4, 1); |
2583 | 2583 |
2584 // Handle store cache miss. | 2584 // Handle store cache miss. |
2585 __ bind(&miss); | 2585 __ bind(&miss); |
2586 Handle<Code> ic(isolate->builtins()->builtin(Builtins::StoreIC_Miss)); | 2586 Handle<Code> ic = isolate->builtins()->StoreIC_Miss(); |
2587 __ jmp(ic, RelocInfo::CODE_TARGET); | 2587 __ jmp(ic, RelocInfo::CODE_TARGET); |
2588 | 2588 |
2589 // Return the generated code. | 2589 // Return the generated code. |
2590 return GetCode(INTERCEPTOR, name); | 2590 return GetCode(INTERCEPTOR, name); |
2591 } | 2591 } |
2592 | 2592 |
2593 | 2593 |
2594 MaybeObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, | 2594 MaybeObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, |
2595 JSGlobalPropertyCell* cell, | 2595 JSGlobalPropertyCell* cell, |
2596 String* name) { | 2596 String* name) { |
(...skipping 28 matching lines...) Expand all Loading... |
2625 // Store the value in the cell. | 2625 // Store the value in the cell. |
2626 __ mov(cell_operand, eax); | 2626 __ mov(cell_operand, eax); |
2627 | 2627 |
2628 // Return the value (register eax). | 2628 // Return the value (register eax). |
2629 __ IncrementCounter(COUNTERS->named_store_global_inline(), 1); | 2629 __ IncrementCounter(COUNTERS->named_store_global_inline(), 1); |
2630 __ ret(0); | 2630 __ ret(0); |
2631 | 2631 |
2632 // Handle store cache miss. | 2632 // Handle store cache miss. |
2633 __ bind(&miss); | 2633 __ bind(&miss); |
2634 __ IncrementCounter(COUNTERS->named_store_global_inline_miss(), 1); | 2634 __ IncrementCounter(COUNTERS->named_store_global_inline_miss(), 1); |
2635 Handle<Code> ic(Isolate::Current()->builtins()->builtin( | 2635 Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); |
2636 Builtins::StoreIC_Miss)); | |
2637 __ jmp(ic, RelocInfo::CODE_TARGET); | 2636 __ jmp(ic, RelocInfo::CODE_TARGET); |
2638 | 2637 |
2639 // Return the generated code. | 2638 // Return the generated code. |
2640 return GetCode(NORMAL, name); | 2639 return GetCode(NORMAL, name); |
2641 } | 2640 } |
2642 | 2641 |
2643 | 2642 |
2644 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, | 2643 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, |
2645 int index, | 2644 int index, |
2646 Map* transition, | 2645 Map* transition, |
(...skipping 16 matching lines...) Expand all Loading... |
2663 GenerateStoreField(masm(), | 2662 GenerateStoreField(masm(), |
2664 object, | 2663 object, |
2665 index, | 2664 index, |
2666 transition, | 2665 transition, |
2667 edx, ecx, ebx, | 2666 edx, ecx, ebx, |
2668 &miss); | 2667 &miss); |
2669 | 2668 |
2670 // Handle store cache miss. | 2669 // Handle store cache miss. |
2671 __ bind(&miss); | 2670 __ bind(&miss); |
2672 __ DecrementCounter(COUNTERS->keyed_store_field(), 1); | 2671 __ DecrementCounter(COUNTERS->keyed_store_field(), 1); |
2673 Handle<Code> ic(Isolate::Current()->builtins()->builtin( | 2672 Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss(); |
2674 Builtins::KeyedStoreIC_Miss)); | |
2675 __ jmp(ic, RelocInfo::CODE_TARGET); | 2673 __ jmp(ic, RelocInfo::CODE_TARGET); |
2676 | 2674 |
2677 // Return the generated code. | 2675 // Return the generated code. |
2678 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); | 2676 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); |
2679 } | 2677 } |
2680 | 2678 |
2681 | 2679 |
2682 MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized( | 2680 MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized( |
2683 JSObject* receiver) { | 2681 JSObject* receiver) { |
2684 // ----------- S t a t e ------------- | 2682 // ----------- S t a t e ------------- |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2721 // the value in register eax. | 2719 // the value in register eax. |
2722 __ mov(edx, Operand(eax)); | 2720 __ mov(edx, Operand(eax)); |
2723 __ mov(FieldOperand(edi, ecx, times_2, FixedArray::kHeaderSize), eax); | 2721 __ mov(FieldOperand(edi, ecx, times_2, FixedArray::kHeaderSize), eax); |
2724 __ RecordWrite(edi, 0, edx, ecx); | 2722 __ RecordWrite(edi, 0, edx, ecx); |
2725 | 2723 |
2726 // Done. | 2724 // Done. |
2727 __ ret(0); | 2725 __ ret(0); |
2728 | 2726 |
2729 // Handle store cache miss. | 2727 // Handle store cache miss. |
2730 __ bind(&miss); | 2728 __ bind(&miss); |
2731 Handle<Code> ic( | 2729 Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss(); |
2732 Isolate::Current()->builtins()->builtin(Builtins::KeyedStoreIC_Miss)); | |
2733 __ jmp(ic, RelocInfo::CODE_TARGET); | 2730 __ jmp(ic, RelocInfo::CODE_TARGET); |
2734 | 2731 |
2735 // Return the generated code. | 2732 // Return the generated code. |
2736 return GetCode(NORMAL, NULL); | 2733 return GetCode(NORMAL, NULL); |
2737 } | 2734 } |
2738 | 2735 |
2739 | 2736 |
2740 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, | 2737 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, |
2741 JSObject* object, | 2738 JSObject* object, |
2742 JSObject* last) { | 2739 JSObject* last) { |
(...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3263 // depending on the this.x = ...; assignment in the function. | 3260 // depending on the this.x = ...; assignment in the function. |
3264 SharedFunctionInfo* shared = function->shared(); | 3261 SharedFunctionInfo* shared = function->shared(); |
3265 for (int i = 0; i < shared->this_property_assignments_count(); i++) { | 3262 for (int i = 0; i < shared->this_property_assignments_count(); i++) { |
3266 if (shared->IsThisPropertyAssignmentArgument(i)) { | 3263 if (shared->IsThisPropertyAssignmentArgument(i)) { |
3267 // Check if the argument assigned to the property is actually passed. | 3264 // Check if the argument assigned to the property is actually passed. |
3268 // If argument is not passed the property is set to undefined, | 3265 // If argument is not passed the property is set to undefined, |
3269 // otherwise find it on the stack. | 3266 // otherwise find it on the stack. |
3270 int arg_number = shared->GetThisPropertyAssignmentArgument(i); | 3267 int arg_number = shared->GetThisPropertyAssignmentArgument(i); |
3271 __ mov(ebx, edi); | 3268 __ mov(ebx, edi); |
3272 __ cmp(eax, arg_number); | 3269 __ cmp(eax, arg_number); |
3273 if (Isolate::Current()->cpu_features()->IsSupported(CMOV)) { | 3270 if (masm()->isolate()->cpu_features()->IsSupported(CMOV)) { |
3274 CpuFeatures::Scope use_cmov(CMOV); | 3271 CpuFeatures::Scope use_cmov(CMOV); |
3275 __ cmov(above, ebx, Operand(ecx, arg_number * -kPointerSize)); | 3272 __ cmov(above, ebx, Operand(ecx, arg_number * -kPointerSize)); |
3276 } else { | 3273 } else { |
3277 Label not_passed; | 3274 Label not_passed; |
3278 __ j(below_equal, ¬_passed); | 3275 __ j(below_equal, ¬_passed); |
3279 __ mov(ebx, Operand(ecx, arg_number * -kPointerSize)); | 3276 __ mov(ebx, Operand(ecx, arg_number * -kPointerSize)); |
3280 __ bind(¬_passed); | 3277 __ bind(¬_passed); |
3281 } | 3278 } |
3282 // Store value in the property. | 3279 // Store value in the property. |
3283 __ mov(Operand(edx, i * kPointerSize), ebx); | 3280 __ mov(Operand(edx, i * kPointerSize), ebx); |
(...skipping 21 matching lines...) Expand all Loading... |
3305 __ pop(ecx); | 3302 __ pop(ecx); |
3306 __ lea(esp, Operand(esp, ebx, times_pointer_size, 1 * kPointerSize)); | 3303 __ lea(esp, Operand(esp, ebx, times_pointer_size, 1 * kPointerSize)); |
3307 __ push(ecx); | 3304 __ push(ecx); |
3308 __ IncrementCounter(COUNTERS->constructed_objects(), 1); | 3305 __ IncrementCounter(COUNTERS->constructed_objects(), 1); |
3309 __ IncrementCounter(COUNTERS->constructed_objects_stub(), 1); | 3306 __ IncrementCounter(COUNTERS->constructed_objects_stub(), 1); |
3310 __ ret(0); | 3307 __ ret(0); |
3311 | 3308 |
3312 // Jump to the generic stub in case the specialized code cannot handle the | 3309 // Jump to the generic stub in case the specialized code cannot handle the |
3313 // construction. | 3310 // construction. |
3314 __ bind(&generic_stub_call); | 3311 __ bind(&generic_stub_call); |
3315 Code* code = Isolate::Current()->builtins()->builtin( | 3312 Handle<Code> generic_construct_stub = |
3316 Builtins::JSConstructStubGeneric); | 3313 masm()->isolate()->builtins()->JSConstructStubGeneric(); |
3317 Handle<Code> generic_construct_stub(code); | |
3318 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); | 3314 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); |
3319 | 3315 |
3320 // Return the generated code. | 3316 // Return the generated code. |
3321 return GetCode(); | 3317 return GetCode(); |
3322 } | 3318 } |
3323 | 3319 |
3324 | 3320 |
3325 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( | 3321 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( |
3326 JSObject*receiver, ExternalArrayType array_type, Code::Flags flags) { | 3322 JSObject*receiver, ExternalArrayType array_type, Code::Flags flags) { |
3327 // ----------- S t a t e ------------- | 3323 // ----------- S t a t e ------------- |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3581 __ fstp_s(Operand(edi, ebx, times_4, 0)); | 3577 __ fstp_s(Operand(edi, ebx, times_4, 0)); |
3582 __ ret(0); | 3578 __ ret(0); |
3583 } else { | 3579 } else { |
3584 // Perform float-to-int conversion with truncation (round-to-zero) | 3580 // Perform float-to-int conversion with truncation (round-to-zero) |
3585 // behavior. | 3581 // behavior. |
3586 | 3582 |
3587 // For the moment we make the slow call to the runtime on | 3583 // For the moment we make the slow call to the runtime on |
3588 // processors that don't support SSE2. The code in IntegerConvert | 3584 // processors that don't support SSE2. The code in IntegerConvert |
3589 // (code-stubs-ia32.cc) is roughly what is needed here though the | 3585 // (code-stubs-ia32.cc) is roughly what is needed here though the |
3590 // conversion failure case does not need to be handled. | 3586 // conversion failure case does not need to be handled. |
3591 if (Isolate::Current()->cpu_features()->IsSupported(SSE2)) { | 3587 if (masm()->isolate()->cpu_features()->IsSupported(SSE2)) { |
3592 if (array_type != kExternalIntArray && | 3588 if (array_type != kExternalIntArray && |
3593 array_type != kExternalUnsignedIntArray) { | 3589 array_type != kExternalUnsignedIntArray) { |
3594 ASSERT(Isolate::Current()->cpu_features()->IsSupported(SSE2)); | 3590 ASSERT(masm()->isolate()->cpu_features()->IsSupported(SSE2)); |
3595 CpuFeatures::Scope scope(SSE2); | 3591 CpuFeatures::Scope scope(SSE2); |
3596 __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset)); | 3592 __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset)); |
3597 // ecx: untagged integer value | 3593 // ecx: untagged integer value |
3598 switch (array_type) { | 3594 switch (array_type) { |
3599 case kExternalPixelArray: | 3595 case kExternalPixelArray: |
3600 { // Clamp the value to [0..255]. | 3596 { // Clamp the value to [0..255]. |
3601 NearLabel done; | 3597 NearLabel done; |
3602 __ test(ecx, Immediate(0xFFFFFF00)); | 3598 __ test(ecx, Immediate(0xFFFFFF00)); |
3603 __ j(zero, &done); | 3599 __ j(zero, &done); |
3604 __ setcc(negative, ecx); // 1 if negative, 0 if positive. | 3600 __ setcc(negative, ecx); // 1 if negative, 0 if positive. |
3605 __ dec_b(ecx); // 0 if negative, 255 if positive. | 3601 __ dec_b(ecx); // 0 if negative, 255 if positive. |
3606 __ bind(&done); | 3602 __ bind(&done); |
3607 } | 3603 } |
3608 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); | 3604 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
3609 case kExternalByteArray: | 3605 case kExternalByteArray: |
3610 case kExternalUnsignedByteArray: | 3606 case kExternalUnsignedByteArray: |
3611 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); | 3607 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
3612 break; | 3608 break; |
3613 case kExternalShortArray: | 3609 case kExternalShortArray: |
3614 case kExternalUnsignedShortArray: | 3610 case kExternalUnsignedShortArray: |
3615 __ mov_w(Operand(edi, ebx, times_2, 0), ecx); | 3611 __ mov_w(Operand(edi, ebx, times_2, 0), ecx); |
3616 break; | 3612 break; |
3617 default: | 3613 default: |
3618 UNREACHABLE(); | 3614 UNREACHABLE(); |
3619 break; | 3615 break; |
3620 } | 3616 } |
3621 } else { | 3617 } else { |
3622 if (Isolate::Current()->cpu_features()->IsSupported(SSE3)) { | 3618 if (masm()->isolate()->cpu_features()->IsSupported(SSE3)) { |
3623 CpuFeatures::Scope scope(SSE3); | 3619 CpuFeatures::Scope scope(SSE3); |
3624 // fisttp stores values as signed integers. To represent the | 3620 // fisttp stores values as signed integers. To represent the |
3625 // entire range of int and unsigned int arrays, store as a | 3621 // entire range of int and unsigned int arrays, store as a |
3626 // 64-bit int and discard the high 32 bits. | 3622 // 64-bit int and discard the high 32 bits. |
3627 // If the value is NaN or +/-infinity, the result is 0x80000000, | 3623 // If the value is NaN or +/-infinity, the result is 0x80000000, |
3628 // which is automatically zero when taken mod 2^n, n < 32. | 3624 // which is automatically zero when taken mod 2^n, n < 32. |
3629 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 3625 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
3630 __ sub(Operand(esp), Immediate(2 * kPointerSize)); | 3626 __ sub(Operand(esp), Immediate(2 * kPointerSize)); |
3631 __ fisttp_d(Operand(esp, 0)); | 3627 __ fisttp_d(Operand(esp, 0)); |
3632 __ pop(ecx); | 3628 __ pop(ecx); |
3633 __ add(Operand(esp), Immediate(kPointerSize)); | 3629 __ add(Operand(esp), Immediate(kPointerSize)); |
3634 } else { | 3630 } else { |
3635 ASSERT(Isolate::Current()->cpu_features()->IsSupported(SSE2)); | 3631 ASSERT(masm()->isolate()->cpu_features()->IsSupported(SSE2)); |
3636 CpuFeatures::Scope scope(SSE2); | 3632 CpuFeatures::Scope scope(SSE2); |
3637 // We can easily implement the correct rounding behavior for the | 3633 // We can easily implement the correct rounding behavior for the |
3638 // range [0, 2^31-1]. For the time being, to keep this code simple, | 3634 // range [0, 2^31-1]. For the time being, to keep this code simple, |
3639 // make the slow runtime call for values outside this range. | 3635 // make the slow runtime call for values outside this range. |
3640 // Note: we could do better for signed int arrays. | 3636 // Note: we could do better for signed int arrays. |
3641 __ movd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); | 3637 __ movd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); |
3642 // We will need the key if we have to make the slow runtime call. | 3638 // We will need the key if we have to make the slow runtime call. |
3643 __ push(ecx); | 3639 __ push(ecx); |
3644 __ LoadPowerOf2(xmm1, ecx, 31); | 3640 __ LoadPowerOf2(xmm1, ecx, 31); |
3645 __ pop(ecx); | 3641 __ pop(ecx); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3678 | 3674 |
3679 return GetCode(flags); | 3675 return GetCode(flags); |
3680 } | 3676 } |
3681 | 3677 |
3682 | 3678 |
3683 #undef __ | 3679 #undef __ |
3684 | 3680 |
3685 } } // namespace v8::internal | 3681 } } // namespace v8::internal |
3686 | 3682 |
3687 #endif // V8_TARGET_ARCH_IA32 | 3683 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |