| 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 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 107 // must always call a backup property check that is complete. | 107 // must always call a backup property check that is complete. |
| 108 // This function is safe to call if the receiver has fast properties. | 108 // This function is safe to call if the receiver has fast properties. |
| 109 // Name must be a symbol and receiver must be a heap object. | 109 // Name must be a symbol and receiver must be a heap object. |
| 110 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, | 110 static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, |
| 111 Label* miss_label, | 111 Label* miss_label, |
| 112 Register receiver, | 112 Register receiver, |
| 113 String* name, | 113 String* name, |
| 114 Register r0, | 114 Register r0, |
| 115 Register r1) { | 115 Register r1) { |
| 116 ASSERT(name->IsSymbol()); | 116 ASSERT(name->IsSymbol()); |
| 117 __ IncrementCounter(COUNTERS->negative_lookups(), 1); | 117 Counters* counters = masm->isolate()->counters(); |
| 118 __ IncrementCounter(COUNTERS->negative_lookups_miss(), 1); | 118 __ IncrementCounter(counters->negative_lookups(), 1); |
| 119 __ IncrementCounter(counters->negative_lookups_miss(), 1); |
| 119 | 120 |
| 120 Label done; | 121 Label done; |
| 121 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); | 122 __ mov(r0, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 122 | 123 |
| 123 const int kInterceptorOrAccessCheckNeededMask = | 124 const int kInterceptorOrAccessCheckNeededMask = |
| 124 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 125 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
| 125 | 126 |
| 126 // Bail out if the receiver has a named interceptor or requires access checks. | 127 // Bail out if the receiver has a named interceptor or requires access checks. |
| 127 __ test_b(FieldOperand(r0, Map::kBitFieldOffset), | 128 __ test_b(FieldOperand(r0, Map::kBitFieldOffset), |
| 128 kInterceptorOrAccessCheckNeededMask); | 129 kInterceptorOrAccessCheckNeededMask); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 191 __ test_b(FieldOperand(entity_name, Map::kInstanceTypeOffset), | 192 __ test_b(FieldOperand(entity_name, Map::kInstanceTypeOffset), |
| 192 kIsSymbolMask); | 193 kIsSymbolMask); |
| 193 __ j(zero, miss_label, not_taken); | 194 __ j(zero, miss_label, not_taken); |
| 194 } else { | 195 } else { |
| 195 // Give up probing if still not found the undefined value. | 196 // Give up probing if still not found the undefined value. |
| 196 __ j(not_equal, miss_label, not_taken); | 197 __ j(not_equal, miss_label, not_taken); |
| 197 } | 198 } |
| 198 } | 199 } |
| 199 | 200 |
| 200 __ bind(&done); | 201 __ bind(&done); |
| 201 __ DecrementCounter(COUNTERS->negative_lookups_miss(), 1); | 202 __ DecrementCounter(counters->negative_lookups_miss(), 1); |
| 202 } | 203 } |
| 203 | 204 |
| 204 | 205 |
| 205 void StubCache::GenerateProbe(MacroAssembler* masm, | 206 void StubCache::GenerateProbe(MacroAssembler* masm, |
| 206 Code::Flags flags, | 207 Code::Flags flags, |
| 207 Register receiver, | 208 Register receiver, |
| 208 Register name, | 209 Register name, |
| 209 Register scratch, | 210 Register scratch, |
| 210 Register extra, | 211 Register extra, |
| 211 Register extra2) { | 212 Register extra2) { |
| (...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 607 interceptor_holder); | 608 interceptor_holder); |
| 608 if (depth1 == kInvalidProtoDepth) { | 609 if (depth1 == kInvalidProtoDepth) { |
| 609 depth2 = | 610 depth2 = |
| 610 optimization.GetPrototypeDepthOfExpectedType(interceptor_holder, | 611 optimization.GetPrototypeDepthOfExpectedType(interceptor_holder, |
| 611 lookup->holder()); | 612 lookup->holder()); |
| 612 } | 613 } |
| 613 can_do_fast_api_call = (depth1 != kInvalidProtoDepth) || | 614 can_do_fast_api_call = (depth1 != kInvalidProtoDepth) || |
| 614 (depth2 != kInvalidProtoDepth); | 615 (depth2 != kInvalidProtoDepth); |
| 615 } | 616 } |
| 616 | 617 |
| 617 __ IncrementCounter(COUNTERS->call_const_interceptor(), 1); | 618 Counters* counters = masm->isolate()->counters(); |
| 619 __ IncrementCounter(counters->call_const_interceptor(), 1); |
| 618 | 620 |
| 619 if (can_do_fast_api_call) { | 621 if (can_do_fast_api_call) { |
| 620 __ IncrementCounter(COUNTERS->call_const_interceptor_fast_api(), 1); | 622 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1); |
| 621 ReserveSpaceForFastApiCall(masm, scratch1); | 623 ReserveSpaceForFastApiCall(masm, scratch1); |
| 622 } | 624 } |
| 623 | 625 |
| 624 // Check that the maps from receiver to interceptor's holder | 626 // Check that the maps from receiver to interceptor's holder |
| 625 // haven't changed and thus we can invoke interceptor. | 627 // haven't changed and thus we can invoke interceptor. |
| 626 Label miss_cleanup; | 628 Label miss_cleanup; |
| 627 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; | 629 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; |
| 628 Register holder = | 630 Register holder = |
| 629 stub_compiler_->CheckPrototypes(object, receiver, | 631 stub_compiler_->CheckPrototypes(object, receiver, |
| 630 interceptor_holder, scratch1, | 632 interceptor_holder, scratch1, |
| (...skipping 1517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2148 GenerateNameCheck(name, &miss_before_stack_reserved); | 2150 GenerateNameCheck(name, &miss_before_stack_reserved); |
| 2149 | 2151 |
| 2150 // Get the receiver from the stack. | 2152 // Get the receiver from the stack. |
| 2151 const int argc = arguments().immediate(); | 2153 const int argc = arguments().immediate(); |
| 2152 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2154 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 2153 | 2155 |
| 2154 // Check that the receiver isn't a smi. | 2156 // Check that the receiver isn't a smi. |
| 2155 __ test(edx, Immediate(kSmiTagMask)); | 2157 __ test(edx, Immediate(kSmiTagMask)); |
| 2156 __ j(zero, &miss_before_stack_reserved, not_taken); | 2158 __ j(zero, &miss_before_stack_reserved, not_taken); |
| 2157 | 2159 |
| 2158 __ IncrementCounter(COUNTERS->call_const(), 1); | 2160 Counters* counters = masm()->isolate()->counters(); |
| 2159 __ IncrementCounter(COUNTERS->call_const_fast_api(), 1); | 2161 __ IncrementCounter(counters->call_const(), 1); |
| 2162 __ IncrementCounter(counters->call_const_fast_api(), 1); |
| 2160 | 2163 |
| 2161 // Allocate space for v8::Arguments implicit values. Must be initialized | 2164 // Allocate space for v8::Arguments implicit values. Must be initialized |
| 2162 // before calling any runtime function. | 2165 // before calling any runtime function. |
| 2163 __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); | 2166 __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); |
| 2164 | 2167 |
| 2165 // Check that the maps haven't changed and find a Holder as a side effect. | 2168 // Check that the maps haven't changed and find a Holder as a side effect. |
| 2166 CheckPrototypes(JSObject::cast(object), edx, holder, | 2169 CheckPrototypes(JSObject::cast(object), edx, holder, |
| 2167 ebx, eax, edi, name, depth, &miss); | 2170 ebx, eax, edi, name, depth, &miss); |
| 2168 | 2171 |
| 2169 // Move the return address on top of the stack. | 2172 // Move the return address on top of the stack. |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2223 __ j(zero, &miss, not_taken); | 2226 __ j(zero, &miss, not_taken); |
| 2224 } | 2227 } |
| 2225 | 2228 |
| 2226 // Make sure that it's okay not to patch the on stack receiver | 2229 // Make sure that it's okay not to patch the on stack receiver |
| 2227 // unless we're doing a receiver map check. | 2230 // unless we're doing a receiver map check. |
| 2228 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2231 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
| 2229 | 2232 |
| 2230 SharedFunctionInfo* function_info = function->shared(); | 2233 SharedFunctionInfo* function_info = function->shared(); |
| 2231 switch (check) { | 2234 switch (check) { |
| 2232 case RECEIVER_MAP_CHECK: | 2235 case RECEIVER_MAP_CHECK: |
| 2233 __ IncrementCounter(COUNTERS->call_const(), 1); | 2236 __ IncrementCounter(masm()->isolate()->counters()->call_const(), 1); |
| 2234 | 2237 |
| 2235 // Check that the maps haven't changed. | 2238 // Check that the maps haven't changed. |
| 2236 CheckPrototypes(JSObject::cast(object), edx, holder, | 2239 CheckPrototypes(JSObject::cast(object), edx, holder, |
| 2237 ebx, eax, edi, name, &miss); | 2240 ebx, eax, edi, name, &miss); |
| 2238 | 2241 |
| 2239 // Patch the receiver on the stack with the global proxy if | 2242 // Patch the receiver on the stack with the global proxy if |
| 2240 // necessary. | 2243 // necessary. |
| 2241 if (object->IsGlobalObject()) { | 2244 if (object->IsGlobalObject()) { |
| 2242 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 2245 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
| 2243 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 2246 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2423 // Patch the receiver on the stack with the global proxy. | 2426 // Patch the receiver on the stack with the global proxy. |
| 2424 if (object->IsGlobalObject()) { | 2427 if (object->IsGlobalObject()) { |
| 2425 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 2428 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
| 2426 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 2429 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
| 2427 } | 2430 } |
| 2428 | 2431 |
| 2429 // Setup the context (function already in edi). | 2432 // Setup the context (function already in edi). |
| 2430 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 2433 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
| 2431 | 2434 |
| 2432 // Jump to the cached code (tail call). | 2435 // Jump to the cached code (tail call). |
| 2433 __ IncrementCounter(COUNTERS->call_global_inline(), 1); | 2436 Counters* counters = masm()->isolate()->counters(); |
| 2437 __ IncrementCounter(counters->call_global_inline(), 1); |
| 2434 ASSERT(function->is_compiled()); | 2438 ASSERT(function->is_compiled()); |
| 2435 ParameterCount expected(function->shared()->formal_parameter_count()); | 2439 ParameterCount expected(function->shared()->formal_parameter_count()); |
| 2436 if (V8::UseCrankshaft()) { | 2440 if (V8::UseCrankshaft()) { |
| 2437 // TODO(kasperl): For now, we always call indirectly through the | 2441 // TODO(kasperl): For now, we always call indirectly through the |
| 2438 // code field in the function to allow recompilation to take effect | 2442 // code field in the function to allow recompilation to take effect |
| 2439 // without changing any of the call sites. | 2443 // without changing any of the call sites. |
| 2440 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), | 2444 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), |
| 2441 expected, arguments(), JUMP_FUNCTION); | 2445 expected, arguments(), JUMP_FUNCTION); |
| 2442 } else { | 2446 } else { |
| 2443 Handle<Code> code(function->code()); | 2447 Handle<Code> code(function->code()); |
| 2444 __ InvokeCode(code, expected, arguments(), | 2448 __ InvokeCode(code, expected, arguments(), |
| 2445 RelocInfo::CODE_TARGET, JUMP_FUNCTION); | 2449 RelocInfo::CODE_TARGET, JUMP_FUNCTION); |
| 2446 } | 2450 } |
| 2447 | 2451 |
| 2448 // Handle call cache miss. | 2452 // Handle call cache miss. |
| 2449 __ bind(&miss); | 2453 __ bind(&miss); |
| 2450 __ IncrementCounter(COUNTERS->call_global_inline_miss(), 1); | 2454 __ IncrementCounter(counters->call_global_inline_miss(), 1); |
| 2451 MaybeObject* maybe_result = GenerateMissBranch(); | 2455 MaybeObject* maybe_result = GenerateMissBranch(); |
| 2452 if (maybe_result->IsFailure()) return maybe_result; | 2456 if (maybe_result->IsFailure()) return maybe_result; |
| 2453 | 2457 |
| 2454 // Return the generated code. | 2458 // Return the generated code. |
| 2455 return GetCode(NORMAL, name); | 2459 return GetCode(NORMAL, name); |
| 2456 } | 2460 } |
| 2457 | 2461 |
| 2458 | 2462 |
| 2459 MaybeObject* StoreStubCompiler::CompileStoreField(JSObject* object, | 2463 MaybeObject* StoreStubCompiler::CompileStoreField(JSObject* object, |
| 2460 int index, | 2464 int index, |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2619 // cell could have been deleted and reintroducing the global needs | 2623 // cell could have been deleted and reintroducing the global needs |
| 2620 // to update the property details in the property dictionary of the | 2624 // to update the property details in the property dictionary of the |
| 2621 // global object. We bail out to the runtime system to do that. | 2625 // global object. We bail out to the runtime system to do that. |
| 2622 __ cmp(cell_operand, FACTORY->the_hole_value()); | 2626 __ cmp(cell_operand, FACTORY->the_hole_value()); |
| 2623 __ j(equal, &miss); | 2627 __ j(equal, &miss); |
| 2624 | 2628 |
| 2625 // Store the value in the cell. | 2629 // Store the value in the cell. |
| 2626 __ mov(cell_operand, eax); | 2630 __ mov(cell_operand, eax); |
| 2627 | 2631 |
| 2628 // Return the value (register eax). | 2632 // Return the value (register eax). |
| 2629 __ IncrementCounter(COUNTERS->named_store_global_inline(), 1); | 2633 Counters* counters = masm()->isolate()->counters(); |
| 2634 __ IncrementCounter(counters->named_store_global_inline(), 1); |
| 2630 __ ret(0); | 2635 __ ret(0); |
| 2631 | 2636 |
| 2632 // Handle store cache miss. | 2637 // Handle store cache miss. |
| 2633 __ bind(&miss); | 2638 __ bind(&miss); |
| 2634 __ IncrementCounter(COUNTERS->named_store_global_inline_miss(), 1); | 2639 __ IncrementCounter(counters->named_store_global_inline_miss(), 1); |
| 2635 Handle<Code> ic(Isolate::Current()->builtins()->builtin( | 2640 Handle<Code> ic(Isolate::Current()->builtins()->builtin( |
| 2636 Builtins::StoreIC_Miss)); | 2641 Builtins::StoreIC_Miss)); |
| 2637 __ jmp(ic, RelocInfo::CODE_TARGET); | 2642 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 2638 | 2643 |
| 2639 // Return the generated code. | 2644 // Return the generated code. |
| 2640 return GetCode(NORMAL, name); | 2645 return GetCode(NORMAL, name); |
| 2641 } | 2646 } |
| 2642 | 2647 |
| 2643 | 2648 |
| 2644 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, | 2649 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, |
| 2645 int index, | 2650 int index, |
| 2646 Map* transition, | 2651 Map* transition, |
| 2647 String* name) { | 2652 String* name) { |
| 2648 // ----------- S t a t e ------------- | 2653 // ----------- S t a t e ------------- |
| 2649 // -- eax : value | 2654 // -- eax : value |
| 2650 // -- ecx : key | 2655 // -- ecx : key |
| 2651 // -- edx : receiver | 2656 // -- edx : receiver |
| 2652 // -- esp[0] : return address | 2657 // -- esp[0] : return address |
| 2653 // ----------------------------------- | 2658 // ----------------------------------- |
| 2654 Label miss; | 2659 Label miss; |
| 2655 | 2660 |
| 2656 __ IncrementCounter(COUNTERS->keyed_store_field(), 1); | 2661 Counters* counters = masm()->isolate()->counters(); |
| 2662 __ IncrementCounter(counters->keyed_store_field(), 1); |
| 2657 | 2663 |
| 2658 // Check that the name has not changed. | 2664 // Check that the name has not changed. |
| 2659 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); | 2665 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); |
| 2660 __ j(not_equal, &miss, not_taken); | 2666 __ j(not_equal, &miss, not_taken); |
| 2661 | 2667 |
| 2662 // Generate store field code. Trashes the name register. | 2668 // Generate store field code. Trashes the name register. |
| 2663 GenerateStoreField(masm(), | 2669 GenerateStoreField(masm(), |
| 2664 object, | 2670 object, |
| 2665 index, | 2671 index, |
| 2666 transition, | 2672 transition, |
| 2667 edx, ecx, ebx, | 2673 edx, ecx, ebx, |
| 2668 &miss); | 2674 &miss); |
| 2669 | 2675 |
| 2670 // Handle store cache miss. | 2676 // Handle store cache miss. |
| 2671 __ bind(&miss); | 2677 __ bind(&miss); |
| 2672 __ DecrementCounter(COUNTERS->keyed_store_field(), 1); | 2678 __ DecrementCounter(counters->keyed_store_field(), 1); |
| 2673 Handle<Code> ic(Isolate::Current()->builtins()->builtin( | 2679 Handle<Code> ic(Isolate::Current()->builtins()->builtin( |
| 2674 Builtins::KeyedStoreIC_Miss)); | 2680 Builtins::KeyedStoreIC_Miss)); |
| 2675 __ jmp(ic, RelocInfo::CODE_TARGET); | 2681 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 2676 | 2682 |
| 2677 // Return the generated code. | 2683 // Return the generated code. |
| 2678 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); | 2684 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); |
| 2679 } | 2685 } |
| 2680 | 2686 |
| 2681 | 2687 |
| 2682 MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized( | 2688 MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized( |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2918 | 2924 |
| 2919 // Check for deleted property if property can actually be deleted. | 2925 // Check for deleted property if property can actually be deleted. |
| 2920 if (!is_dont_delete) { | 2926 if (!is_dont_delete) { |
| 2921 __ cmp(ebx, FACTORY->the_hole_value()); | 2927 __ cmp(ebx, FACTORY->the_hole_value()); |
| 2922 __ j(equal, &miss, not_taken); | 2928 __ j(equal, &miss, not_taken); |
| 2923 } else if (FLAG_debug_code) { | 2929 } else if (FLAG_debug_code) { |
| 2924 __ cmp(ebx, FACTORY->the_hole_value()); | 2930 __ cmp(ebx, FACTORY->the_hole_value()); |
| 2925 __ Check(not_equal, "DontDelete cells can't contain the hole"); | 2931 __ Check(not_equal, "DontDelete cells can't contain the hole"); |
| 2926 } | 2932 } |
| 2927 | 2933 |
| 2928 __ IncrementCounter(COUNTERS->named_load_global_stub(), 1); | 2934 Counters* counters = masm()->isolate()->counters(); |
| 2935 __ IncrementCounter(counters->named_load_global_stub(), 1); |
| 2929 __ mov(eax, ebx); | 2936 __ mov(eax, ebx); |
| 2930 __ ret(0); | 2937 __ ret(0); |
| 2931 | 2938 |
| 2932 __ bind(&miss); | 2939 __ bind(&miss); |
| 2933 __ IncrementCounter(COUNTERS->named_load_global_stub_miss(), 1); | 2940 __ IncrementCounter(counters->named_load_global_stub_miss(), 1); |
| 2934 GenerateLoadMiss(masm(), Code::LOAD_IC); | 2941 GenerateLoadMiss(masm(), Code::LOAD_IC); |
| 2935 | 2942 |
| 2936 // Return the generated code. | 2943 // Return the generated code. |
| 2937 return GetCode(NORMAL, name); | 2944 return GetCode(NORMAL, name); |
| 2938 } | 2945 } |
| 2939 | 2946 |
| 2940 | 2947 |
| 2941 MaybeObject* KeyedLoadStubCompiler::CompileLoadField(String* name, | 2948 MaybeObject* KeyedLoadStubCompiler::CompileLoadField(String* name, |
| 2942 JSObject* receiver, | 2949 JSObject* receiver, |
| 2943 JSObject* holder, | 2950 JSObject* holder, |
| 2944 int index) { | 2951 int index) { |
| 2945 // ----------- S t a t e ------------- | 2952 // ----------- S t a t e ------------- |
| 2946 // -- eax : key | 2953 // -- eax : key |
| 2947 // -- edx : receiver | 2954 // -- edx : receiver |
| 2948 // -- esp[0] : return address | 2955 // -- esp[0] : return address |
| 2949 // ----------------------------------- | 2956 // ----------------------------------- |
| 2950 Label miss; | 2957 Label miss; |
| 2951 | 2958 |
| 2952 __ IncrementCounter(COUNTERS->keyed_load_field(), 1); | 2959 Counters* counters = masm()->isolate()->counters(); |
| 2960 __ IncrementCounter(counters->keyed_load_field(), 1); |
| 2953 | 2961 |
| 2954 // Check that the name has not changed. | 2962 // Check that the name has not changed. |
| 2955 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 2963 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 2956 __ j(not_equal, &miss, not_taken); | 2964 __ j(not_equal, &miss, not_taken); |
| 2957 | 2965 |
| 2958 GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss); | 2966 GenerateLoadField(receiver, holder, edx, ebx, ecx, edi, index, name, &miss); |
| 2959 | 2967 |
| 2960 __ bind(&miss); | 2968 __ bind(&miss); |
| 2961 __ DecrementCounter(COUNTERS->keyed_load_field(), 1); | 2969 __ DecrementCounter(counters->keyed_load_field(), 1); |
| 2962 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2970 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 2963 | 2971 |
| 2964 // Return the generated code. | 2972 // Return the generated code. |
| 2965 return GetCode(FIELD, name); | 2973 return GetCode(FIELD, name); |
| 2966 } | 2974 } |
| 2967 | 2975 |
| 2968 | 2976 |
| 2969 MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback( | 2977 MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback( |
| 2970 String* name, | 2978 String* name, |
| 2971 JSObject* receiver, | 2979 JSObject* receiver, |
| 2972 JSObject* holder, | 2980 JSObject* holder, |
| 2973 AccessorInfo* callback) { | 2981 AccessorInfo* callback) { |
| 2974 // ----------- S t a t e ------------- | 2982 // ----------- S t a t e ------------- |
| 2975 // -- eax : key | 2983 // -- eax : key |
| 2976 // -- edx : receiver | 2984 // -- edx : receiver |
| 2977 // -- esp[0] : return address | 2985 // -- esp[0] : return address |
| 2978 // ----------------------------------- | 2986 // ----------------------------------- |
| 2979 Label miss; | 2987 Label miss; |
| 2980 | 2988 |
| 2981 __ IncrementCounter(COUNTERS->keyed_load_callback(), 1); | 2989 Counters* counters = masm()->isolate()->counters(); |
| 2990 __ IncrementCounter(counters->keyed_load_callback(), 1); |
| 2982 | 2991 |
| 2983 // Check that the name has not changed. | 2992 // Check that the name has not changed. |
| 2984 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 2993 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 2985 __ j(not_equal, &miss, not_taken); | 2994 __ j(not_equal, &miss, not_taken); |
| 2986 | 2995 |
| 2987 MaybeObject* result = GenerateLoadCallback(receiver, holder, edx, eax, ebx, | 2996 MaybeObject* result = GenerateLoadCallback(receiver, holder, edx, eax, ebx, |
| 2988 ecx, edi, callback, name, &miss); | 2997 ecx, edi, callback, name, &miss); |
| 2989 if (result->IsFailure()) { | 2998 if (result->IsFailure()) { |
| 2990 miss.Unuse(); | 2999 miss.Unuse(); |
| 2991 return result; | 3000 return result; |
| 2992 } | 3001 } |
| 2993 | 3002 |
| 2994 __ bind(&miss); | 3003 __ bind(&miss); |
| 2995 | 3004 |
| 2996 __ DecrementCounter(COUNTERS->keyed_load_callback(), 1); | 3005 __ DecrementCounter(counters->keyed_load_callback(), 1); |
| 2997 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3006 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 2998 | 3007 |
| 2999 // Return the generated code. | 3008 // Return the generated code. |
| 3000 return GetCode(CALLBACKS, name); | 3009 return GetCode(CALLBACKS, name); |
| 3001 } | 3010 } |
| 3002 | 3011 |
| 3003 | 3012 |
| 3004 MaybeObject* KeyedLoadStubCompiler::CompileLoadConstant(String* name, | 3013 MaybeObject* KeyedLoadStubCompiler::CompileLoadConstant(String* name, |
| 3005 JSObject* receiver, | 3014 JSObject* receiver, |
| 3006 JSObject* holder, | 3015 JSObject* holder, |
| 3007 Object* value) { | 3016 Object* value) { |
| 3008 // ----------- S t a t e ------------- | 3017 // ----------- S t a t e ------------- |
| 3009 // -- eax : key | 3018 // -- eax : key |
| 3010 // -- edx : receiver | 3019 // -- edx : receiver |
| 3011 // -- esp[0] : return address | 3020 // -- esp[0] : return address |
| 3012 // ----------------------------------- | 3021 // ----------------------------------- |
| 3013 Label miss; | 3022 Label miss; |
| 3014 | 3023 |
| 3015 __ IncrementCounter(COUNTERS->keyed_load_constant_function(), 1); | 3024 Counters* counters = masm()->isolate()->counters(); |
| 3025 __ IncrementCounter(counters->keyed_load_constant_function(), 1); |
| 3016 | 3026 |
| 3017 // Check that the name has not changed. | 3027 // Check that the name has not changed. |
| 3018 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3028 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 3019 __ j(not_equal, &miss, not_taken); | 3029 __ j(not_equal, &miss, not_taken); |
| 3020 | 3030 |
| 3021 GenerateLoadConstant(receiver, holder, edx, ebx, ecx, edi, | 3031 GenerateLoadConstant(receiver, holder, edx, ebx, ecx, edi, |
| 3022 value, name, &miss); | 3032 value, name, &miss); |
| 3023 __ bind(&miss); | 3033 __ bind(&miss); |
| 3024 __ DecrementCounter(COUNTERS->keyed_load_constant_function(), 1); | 3034 __ DecrementCounter(counters->keyed_load_constant_function(), 1); |
| 3025 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3035 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3026 | 3036 |
| 3027 // Return the generated code. | 3037 // Return the generated code. |
| 3028 return GetCode(CONSTANT_FUNCTION, name); | 3038 return GetCode(CONSTANT_FUNCTION, name); |
| 3029 } | 3039 } |
| 3030 | 3040 |
| 3031 | 3041 |
| 3032 MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, | 3042 MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, |
| 3033 JSObject* holder, | 3043 JSObject* holder, |
| 3034 String* name) { | 3044 String* name) { |
| 3035 // ----------- S t a t e ------------- | 3045 // ----------- S t a t e ------------- |
| 3036 // -- eax : key | 3046 // -- eax : key |
| 3037 // -- edx : receiver | 3047 // -- edx : receiver |
| 3038 // -- esp[0] : return address | 3048 // -- esp[0] : return address |
| 3039 // ----------------------------------- | 3049 // ----------------------------------- |
| 3040 Label miss; | 3050 Label miss; |
| 3041 | 3051 |
| 3042 __ IncrementCounter(COUNTERS->keyed_load_interceptor(), 1); | 3052 Counters* counters = masm()->isolate()->counters(); |
| 3053 __ IncrementCounter(counters->keyed_load_interceptor(), 1); |
| 3043 | 3054 |
| 3044 // Check that the name has not changed. | 3055 // Check that the name has not changed. |
| 3045 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3056 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 3046 __ j(not_equal, &miss, not_taken); | 3057 __ j(not_equal, &miss, not_taken); |
| 3047 | 3058 |
| 3048 LookupResult lookup; | 3059 LookupResult lookup; |
| 3049 LookupPostInterceptor(holder, name, &lookup); | 3060 LookupPostInterceptor(holder, name, &lookup); |
| 3050 GenerateLoadInterceptor(receiver, | 3061 GenerateLoadInterceptor(receiver, |
| 3051 holder, | 3062 holder, |
| 3052 &lookup, | 3063 &lookup, |
| 3053 edx, | 3064 edx, |
| 3054 eax, | 3065 eax, |
| 3055 ecx, | 3066 ecx, |
| 3056 ebx, | 3067 ebx, |
| 3057 edi, | 3068 edi, |
| 3058 name, | 3069 name, |
| 3059 &miss); | 3070 &miss); |
| 3060 __ bind(&miss); | 3071 __ bind(&miss); |
| 3061 __ DecrementCounter(COUNTERS->keyed_load_interceptor(), 1); | 3072 __ DecrementCounter(counters->keyed_load_interceptor(), 1); |
| 3062 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3073 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3063 | 3074 |
| 3064 // Return the generated code. | 3075 // Return the generated code. |
| 3065 return GetCode(INTERCEPTOR, name); | 3076 return GetCode(INTERCEPTOR, name); |
| 3066 } | 3077 } |
| 3067 | 3078 |
| 3068 | 3079 |
| 3069 MaybeObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) { | 3080 MaybeObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) { |
| 3070 // ----------- S t a t e ------------- | 3081 // ----------- S t a t e ------------- |
| 3071 // -- eax : key | 3082 // -- eax : key |
| 3072 // -- edx : receiver | 3083 // -- edx : receiver |
| 3073 // -- esp[0] : return address | 3084 // -- esp[0] : return address |
| 3074 // ----------------------------------- | 3085 // ----------------------------------- |
| 3075 Label miss; | 3086 Label miss; |
| 3076 | 3087 |
| 3077 __ IncrementCounter(COUNTERS->keyed_load_array_length(), 1); | 3088 Counters* counters = masm()->isolate()->counters(); |
| 3089 __ IncrementCounter(counters->keyed_load_array_length(), 1); |
| 3078 | 3090 |
| 3079 // Check that the name has not changed. | 3091 // Check that the name has not changed. |
| 3080 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3092 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 3081 __ j(not_equal, &miss, not_taken); | 3093 __ j(not_equal, &miss, not_taken); |
| 3082 | 3094 |
| 3083 GenerateLoadArrayLength(masm(), edx, ecx, &miss); | 3095 GenerateLoadArrayLength(masm(), edx, ecx, &miss); |
| 3084 __ bind(&miss); | 3096 __ bind(&miss); |
| 3085 __ DecrementCounter(COUNTERS->keyed_load_array_length(), 1); | 3097 __ DecrementCounter(counters->keyed_load_array_length(), 1); |
| 3086 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3098 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3087 | 3099 |
| 3088 // Return the generated code. | 3100 // Return the generated code. |
| 3089 return GetCode(CALLBACKS, name); | 3101 return GetCode(CALLBACKS, name); |
| 3090 } | 3102 } |
| 3091 | 3103 |
| 3092 | 3104 |
| 3093 MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { | 3105 MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { |
| 3094 // ----------- S t a t e ------------- | 3106 // ----------- S t a t e ------------- |
| 3095 // -- eax : key | 3107 // -- eax : key |
| 3096 // -- edx : receiver | 3108 // -- edx : receiver |
| 3097 // -- esp[0] : return address | 3109 // -- esp[0] : return address |
| 3098 // ----------------------------------- | 3110 // ----------------------------------- |
| 3099 Label miss; | 3111 Label miss; |
| 3100 | 3112 |
| 3101 __ IncrementCounter(COUNTERS->keyed_load_string_length(), 1); | 3113 Counters* counters = masm()->isolate()->counters(); |
| 3114 __ IncrementCounter(counters->keyed_load_string_length(), 1); |
| 3102 | 3115 |
| 3103 // Check that the name has not changed. | 3116 // Check that the name has not changed. |
| 3104 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3117 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 3105 __ j(not_equal, &miss, not_taken); | 3118 __ j(not_equal, &miss, not_taken); |
| 3106 | 3119 |
| 3107 GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true); | 3120 GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true); |
| 3108 __ bind(&miss); | 3121 __ bind(&miss); |
| 3109 __ DecrementCounter(COUNTERS->keyed_load_string_length(), 1); | 3122 __ DecrementCounter(counters->keyed_load_string_length(), 1); |
| 3110 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3123 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3111 | 3124 |
| 3112 // Return the generated code. | 3125 // Return the generated code. |
| 3113 return GetCode(CALLBACKS, name); | 3126 return GetCode(CALLBACKS, name); |
| 3114 } | 3127 } |
| 3115 | 3128 |
| 3116 | 3129 |
| 3117 MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { | 3130 MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { |
| 3118 // ----------- S t a t e ------------- | 3131 // ----------- S t a t e ------------- |
| 3119 // -- eax : key | 3132 // -- eax : key |
| 3120 // -- edx : receiver | 3133 // -- edx : receiver |
| 3121 // -- esp[0] : return address | 3134 // -- esp[0] : return address |
| 3122 // ----------------------------------- | 3135 // ----------------------------------- |
| 3123 Label miss; | 3136 Label miss; |
| 3124 | 3137 |
| 3125 __ IncrementCounter(COUNTERS->keyed_load_function_prototype(), 1); | 3138 Counters* counters = masm()->isolate()->counters(); |
| 3139 __ IncrementCounter(counters->keyed_load_function_prototype(), 1); |
| 3126 | 3140 |
| 3127 // Check that the name has not changed. | 3141 // Check that the name has not changed. |
| 3128 __ cmp(Operand(eax), Immediate(Handle<String>(name))); | 3142 __ cmp(Operand(eax), Immediate(Handle<String>(name))); |
| 3129 __ j(not_equal, &miss, not_taken); | 3143 __ j(not_equal, &miss, not_taken); |
| 3130 | 3144 |
| 3131 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); | 3145 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); |
| 3132 __ bind(&miss); | 3146 __ bind(&miss); |
| 3133 __ DecrementCounter(COUNTERS->keyed_load_function_prototype(), 1); | 3147 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); |
| 3134 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3148 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3135 | 3149 |
| 3136 // Return the generated code. | 3150 // Return the generated code. |
| 3137 return GetCode(CALLBACKS, name); | 3151 return GetCode(CALLBACKS, name); |
| 3138 } | 3152 } |
| 3139 | 3153 |
| 3140 | 3154 |
| 3141 MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { | 3155 MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { |
| 3142 // ----------- S t a t e ------------- | 3156 // ----------- S t a t e ------------- |
| 3143 // -- eax : key | 3157 // -- eax : key |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3298 | 3312 |
| 3299 // Move argc to ebx and retrieve and tag the JSObject to return. | 3313 // Move argc to ebx and retrieve and tag the JSObject to return. |
| 3300 __ mov(ebx, eax); | 3314 __ mov(ebx, eax); |
| 3301 __ pop(eax); | 3315 __ pop(eax); |
| 3302 __ or_(Operand(eax), Immediate(kHeapObjectTag)); | 3316 __ or_(Operand(eax), Immediate(kHeapObjectTag)); |
| 3303 | 3317 |
| 3304 // Remove caller arguments and receiver from the stack and return. | 3318 // Remove caller arguments and receiver from the stack and return. |
| 3305 __ pop(ecx); | 3319 __ pop(ecx); |
| 3306 __ lea(esp, Operand(esp, ebx, times_pointer_size, 1 * kPointerSize)); | 3320 __ lea(esp, Operand(esp, ebx, times_pointer_size, 1 * kPointerSize)); |
| 3307 __ push(ecx); | 3321 __ push(ecx); |
| 3308 __ IncrementCounter(COUNTERS->constructed_objects(), 1); | 3322 Counters* counters = masm()->isolate()->counters(); |
| 3309 __ IncrementCounter(COUNTERS->constructed_objects_stub(), 1); | 3323 __ IncrementCounter(counters->constructed_objects(), 1); |
| 3324 __ IncrementCounter(counters->constructed_objects_stub(), 1); |
| 3310 __ ret(0); | 3325 __ ret(0); |
| 3311 | 3326 |
| 3312 // Jump to the generic stub in case the specialized code cannot handle the | 3327 // Jump to the generic stub in case the specialized code cannot handle the |
| 3313 // construction. | 3328 // construction. |
| 3314 __ bind(&generic_stub_call); | 3329 __ bind(&generic_stub_call); |
| 3315 Code* code = Isolate::Current()->builtins()->builtin( | 3330 Code* code = Isolate::Current()->builtins()->builtin( |
| 3316 Builtins::JSConstructStubGeneric); | 3331 Builtins::JSConstructStubGeneric); |
| 3317 Handle<Code> generic_construct_stub(code); | 3332 Handle<Code> generic_construct_stub(code); |
| 3318 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); | 3333 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); |
| 3319 | 3334 |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3447 | 3462 |
| 3448 // If we fail allocation of the HeapNumber, we still have a value on | 3463 // If we fail allocation of the HeapNumber, we still have a value on |
| 3449 // top of the FPU stack. Remove it. | 3464 // top of the FPU stack. Remove it. |
| 3450 __ bind(&failed_allocation); | 3465 __ bind(&failed_allocation); |
| 3451 __ ffree(); | 3466 __ ffree(); |
| 3452 __ fincstp(); | 3467 __ fincstp(); |
| 3453 // Fall through to slow case. | 3468 // Fall through to slow case. |
| 3454 | 3469 |
| 3455 // Slow case: Jump to runtime. | 3470 // Slow case: Jump to runtime. |
| 3456 __ bind(&slow); | 3471 __ bind(&slow); |
| 3457 __ IncrementCounter(COUNTERS->keyed_load_external_array_slow(), 1); | 3472 Counters* counters = masm()->isolate()->counters(); |
| 3473 __ IncrementCounter(counters->keyed_load_external_array_slow(), 1); |
| 3458 // ----------- S t a t e ------------- | 3474 // ----------- S t a t e ------------- |
| 3459 // -- eax : key | 3475 // -- eax : key |
| 3460 // -- edx : receiver | 3476 // -- edx : receiver |
| 3461 // -- esp[0] : return address | 3477 // -- esp[0] : return address |
| 3462 // ----------------------------------- | 3478 // ----------------------------------- |
| 3463 | 3479 |
| 3464 __ pop(ebx); | 3480 __ pop(ebx); |
| 3465 __ push(edx); // receiver | 3481 __ push(edx); // receiver |
| 3466 __ push(eax); // name | 3482 __ push(eax); // name |
| 3467 __ push(ebx); // return address | 3483 __ push(ebx); // return address |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3678 | 3694 |
| 3679 return GetCode(flags); | 3695 return GetCode(flags); |
| 3680 } | 3696 } |
| 3681 | 3697 |
| 3682 | 3698 |
| 3683 #undef __ | 3699 #undef __ |
| 3684 | 3700 |
| 3685 } } // namespace v8::internal | 3701 } } // namespace v8::internal |
| 3686 | 3702 |
| 3687 #endif // V8_TARGET_ARCH_IA32 | 3703 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |