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