| 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 |