OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 Isolate* isolate, | 100 Isolate* isolate, |
101 CodeStubInterfaceDescriptor* descriptor) { | 101 CodeStubInterfaceDescriptor* descriptor) { |
102 static Register registers[] = { eax, ebx, ecx, edx }; | 102 static Register registers[] = { eax, ebx, ecx, edx }; |
103 descriptor->register_param_count_ = 4; | 103 descriptor->register_param_count_ = 4; |
104 descriptor->register_params_ = registers; | 104 descriptor->register_params_ = registers; |
105 descriptor->deoptimization_handler_ = | 105 descriptor->deoptimization_handler_ = |
106 Runtime::FunctionForId(Runtime::kCreateObjectLiteral)->entry; | 106 Runtime::FunctionForId(Runtime::kCreateObjectLiteral)->entry; |
107 } | 107 } |
108 | 108 |
109 | 109 |
110 void CreateAllocationSiteStub::InitializeInterfaceDescriptor( | |
111 Isolate* isolate, | |
112 CodeStubInterfaceDescriptor* descriptor) { | |
113 static Register registers[] = { ebx, edx }; | |
114 descriptor->register_param_count_ = 2; | |
115 descriptor->register_params_ = registers; | |
116 descriptor->deoptimization_handler_ = NULL; | |
117 } | |
118 | |
119 | |
120 void KeyedLoadFastElementStub::InitializeInterfaceDescriptor( | 110 void KeyedLoadFastElementStub::InitializeInterfaceDescriptor( |
121 Isolate* isolate, | 111 Isolate* isolate, |
122 CodeStubInterfaceDescriptor* descriptor) { | 112 CodeStubInterfaceDescriptor* descriptor) { |
123 static Register registers[] = { edx, ecx }; | 113 static Register registers[] = { edx, ecx }; |
124 descriptor->register_param_count_ = 2; | 114 descriptor->register_param_count_ = 2; |
125 descriptor->register_params_ = registers; | 115 descriptor->register_params_ = registers; |
126 descriptor->deoptimization_handler_ = | 116 descriptor->deoptimization_handler_ = |
127 FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure); | 117 FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure); |
128 } | 118 } |
129 | 119 |
(...skipping 2206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2336 __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size, | 2326 __ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size, |
2337 FixedArray::kHeaderSize)); | 2327 FixedArray::kHeaderSize)); |
2338 | 2328 |
2339 // A monomorphic cache hit or an already megamorphic state: invoke the | 2329 // A monomorphic cache hit or an already megamorphic state: invoke the |
2340 // function without changing the state. | 2330 // function without changing the state. |
2341 __ cmp(ecx, edi); | 2331 __ cmp(ecx, edi); |
2342 __ j(equal, &done, Label::kFar); | 2332 __ j(equal, &done, Label::kFar); |
2343 __ cmp(ecx, Immediate(TypeFeedbackInfo::MegamorphicSentinel(isolate))); | 2333 __ cmp(ecx, Immediate(TypeFeedbackInfo::MegamorphicSentinel(isolate))); |
2344 __ j(equal, &done, Label::kFar); | 2334 __ j(equal, &done, Label::kFar); |
2345 | 2335 |
2346 // If we came here, we need to see if we are the array function. | |
2347 // If we didn't have a matching function, and we didn't find the megamorph | |
2348 // sentinel, then we have in the slot either some other function or an | |
2349 // AllocationSite. Do a map check on the object in ecx. | |
2350 Handle<Map> allocation_site_map = | |
2351 masm->isolate()->factory()->allocation_site_map(); | |
2352 __ cmp(FieldOperand(ecx, 0), Immediate(allocation_site_map)); | |
2353 __ j(not_equal, &miss); | |
2354 | |
2355 // Load the global or builtins object from the current context | |
2356 __ LoadGlobalContext(ecx); | |
2357 // Make sure the function is the Array() function | |
2358 __ cmp(edi, Operand(ecx, | |
2359 Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); | |
2360 __ j(not_equal, &megamorphic); | |
2361 __ jmp(&done, Label::kFar); | |
2362 | |
2363 __ bind(&miss); | 2336 __ bind(&miss); |
2364 | 2337 |
2365 // A monomorphic miss (i.e, here the cache is not uninitialized) goes | 2338 // A monomorphic miss (i.e, here the cache is not uninitialized) goes |
2366 // megamorphic. | 2339 // megamorphic. |
2367 __ cmp(ecx, Immediate(TypeFeedbackInfo::UninitializedSentinel(isolate))); | 2340 __ cmp(ecx, Immediate(TypeFeedbackInfo::UninitializedSentinel(isolate))); |
2368 __ j(equal, &initialize); | 2341 __ j(equal, &initialize); |
2369 // MegamorphicSentinel is an immortal immovable object (undefined) so no | 2342 // MegamorphicSentinel is an immortal immovable object (undefined) so no |
2370 // write-barrier is needed. | 2343 // write-barrier is needed. |
2371 __ bind(&megamorphic); | 2344 __ bind(&megamorphic); |
2372 __ mov(FieldOperand(ebx, edx, times_half_pointer_size, | 2345 __ mov(FieldOperand(ebx, edx, times_half_pointer_size, |
2373 FixedArray::kHeaderSize), | 2346 FixedArray::kHeaderSize), |
2374 Immediate(TypeFeedbackInfo::MegamorphicSentinel(isolate))); | 2347 Immediate(TypeFeedbackInfo::MegamorphicSentinel(isolate))); |
2375 __ jmp(&done, Label::kFar); | 2348 __ jmp(&done, Label::kFar); |
2376 | 2349 |
2377 // An uninitialized cache is patched with the function or sentinel to | 2350 // An uninitialized cache is patched with the function or sentinel to |
2378 // indicate the ElementsKind if function is the Array constructor. | 2351 // indicate the ElementsKind if function is the Array constructor. |
2379 __ bind(&initialize); | 2352 __ bind(&initialize); |
2380 __ LoadGlobalContext(ecx); | |
2381 // Make sure the function is the Array() function | |
2382 __ cmp(edi, Operand(ecx, | |
2383 Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); | |
2384 __ j(not_equal, ¬_array_function); | |
2385 | |
2386 // The target function is the Array constructor, | |
2387 // Create an AllocationSite if we don't already have it, store it in the slot. | |
2388 { | |
2389 FrameScope scope(masm, StackFrame::INTERNAL); | |
2390 | |
2391 // Arguments register must be smi-tagged to call out. | |
2392 __ SmiTag(eax); | |
2393 __ push(eax); | |
2394 __ push(edi); | |
2395 __ push(edx); | |
2396 __ push(ebx); | |
2397 | |
2398 CreateAllocationSiteStub create_stub; | |
2399 __ CallStub(&create_stub); | |
2400 | |
2401 __ pop(ebx); | |
2402 __ pop(edx); | |
2403 __ pop(edi); | |
2404 __ pop(eax); | |
2405 __ SmiUntag(eax); | |
2406 } | |
2407 __ jmp(&done); | |
2408 | |
2409 __ bind(¬_array_function); | |
2410 __ mov(FieldOperand(ebx, edx, times_half_pointer_size, | 2353 __ mov(FieldOperand(ebx, edx, times_half_pointer_size, |
2411 FixedArray::kHeaderSize), | 2354 FixedArray::kHeaderSize), |
2412 edi); | 2355 edi); |
2413 // We won't need edx or ebx anymore, just save edi | 2356 // We won't need edx or ebx anymore, just save edi |
2414 __ push(edi); | 2357 __ push(edi); |
2415 __ push(ebx); | 2358 __ push(ebx); |
2416 __ push(edx); | 2359 __ push(edx); |
2417 __ RecordWriteArray(ebx, edi, edx, kDontSaveFPRegs, | 2360 __ RecordWriteArray(ebx, edi, edx, kDontSaveFPRegs, |
2418 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | 2361 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
2419 __ pop(edx); | 2362 __ pop(edx); |
(...skipping 14 matching lines...) Expand all Loading... |
2434 if (NeedsChecks()) { | 2377 if (NeedsChecks()) { |
2435 // Check that the function really is a JavaScript function. | 2378 // Check that the function really is a JavaScript function. |
2436 __ JumpIfSmi(edi, &non_function); | 2379 __ JumpIfSmi(edi, &non_function); |
2437 | 2380 |
2438 // Goto slow case if we do not have a function. | 2381 // Goto slow case if we do not have a function. |
2439 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 2382 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
2440 __ j(not_equal, &slow); | 2383 __ j(not_equal, &slow); |
2441 | 2384 |
2442 if (RecordCallTarget()) { | 2385 if (RecordCallTarget()) { |
2443 GenerateRecordCallTarget(masm); | 2386 GenerateRecordCallTarget(masm); |
| 2387 // Type information was updated. Because we may call Array, which |
| 2388 // expects either undefined or an AllocationSite in ebx we need |
| 2389 // to set ebx to undefined. |
| 2390 __ mov(ebx, Immediate(isolate->factory()->undefined_value())); |
2444 } | 2391 } |
2445 } | 2392 } |
2446 | 2393 |
2447 // Fast-case: Just invoke the function. | 2394 // Fast-case: Just invoke the function. |
2448 ParameterCount actual(argc_); | 2395 ParameterCount actual(argc_); |
2449 | 2396 |
2450 if (CallAsMethod()) { | 2397 if (CallAsMethod()) { |
2451 if (NeedsChecks()) { | 2398 if (NeedsChecks()) { |
2452 // Do not transform the receiver for strict mode functions. | 2399 // Do not transform the receiver for strict mode functions. |
2453 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 2400 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2537 Label slow, non_function_call; | 2484 Label slow, non_function_call; |
2538 | 2485 |
2539 // Check that function is not a smi. | 2486 // Check that function is not a smi. |
2540 __ JumpIfSmi(edi, &non_function_call); | 2487 __ JumpIfSmi(edi, &non_function_call); |
2541 // Check that function is a JSFunction. | 2488 // Check that function is a JSFunction. |
2542 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | 2489 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
2543 __ j(not_equal, &slow); | 2490 __ j(not_equal, &slow); |
2544 | 2491 |
2545 if (RecordCallTarget()) { | 2492 if (RecordCallTarget()) { |
2546 GenerateRecordCallTarget(masm); | 2493 GenerateRecordCallTarget(masm); |
| 2494 // Put the AllocationSite from the feedback vector into ebx. |
| 2495 // By adding kPointerSize we encode that we know the AllocationSite |
| 2496 // entry is at the feedback vector slot given by edx + 1. |
| 2497 __ mov(ebx, FieldOperand(ebx, edx, times_half_pointer_size, |
| 2498 FixedArray::kHeaderSize + kPointerSize)); |
| 2499 __ AssertUndefinedOrAllocationSite(ebx); |
2547 } | 2500 } |
2548 | 2501 |
2549 // Jump to the function-specific construct stub. | 2502 // Jump to the function-specific construct stub. |
2550 Register jmp_reg = ecx; | 2503 Register jmp_reg = ecx; |
2551 __ mov(jmp_reg, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 2504 __ mov(jmp_reg, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
2552 __ mov(jmp_reg, FieldOperand(jmp_reg, | 2505 __ mov(jmp_reg, FieldOperand(jmp_reg, |
2553 SharedFunctionInfo::kConstructStubOffset)); | 2506 SharedFunctionInfo::kConstructStubOffset)); |
2554 __ lea(jmp_reg, FieldOperand(jmp_reg, Code::kHeaderSize)); | 2507 __ lea(jmp_reg, FieldOperand(jmp_reg, Code::kHeaderSize)); |
2555 __ jmp(jmp_reg); | 2508 __ jmp(jmp_reg); |
2556 | 2509 |
(...skipping 22 matching lines...) Expand all Loading... |
2579 return false; | 2532 return false; |
2580 } | 2533 } |
2581 | 2534 |
2582 | 2535 |
2583 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { | 2536 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { |
2584 CEntryStub::GenerateAheadOfTime(isolate); | 2537 CEntryStub::GenerateAheadOfTime(isolate); |
2585 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); | 2538 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); |
2586 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); | 2539 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); |
2587 // It is important that the store buffer overflow stubs are generated first. | 2540 // It is important that the store buffer overflow stubs are generated first. |
2588 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); | 2541 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); |
2589 CreateAllocationSiteStub::GenerateAheadOfTime(isolate); | |
2590 if (Serializer::enabled()) { | 2542 if (Serializer::enabled()) { |
2591 PlatformFeatureScope sse2(SSE2); | 2543 PlatformFeatureScope sse2(SSE2); |
2592 BinaryOpICStub::GenerateAheadOfTime(isolate); | 2544 BinaryOpICStub::GenerateAheadOfTime(isolate); |
2593 BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate); | 2545 BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate); |
2594 } else { | 2546 } else { |
2595 BinaryOpICStub::GenerateAheadOfTime(isolate); | 2547 BinaryOpICStub::GenerateAheadOfTime(isolate); |
2596 BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate); | 2548 BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime(isolate); |
2597 } | 2549 } |
2598 } | 2550 } |
2599 | 2551 |
(...skipping 2548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5148 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); | 5100 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); |
5149 } else { | 5101 } else { |
5150 UNREACHABLE(); | 5102 UNREACHABLE(); |
5151 } | 5103 } |
5152 } | 5104 } |
5153 | 5105 |
5154 | 5106 |
5155 void ArrayConstructorStub::Generate(MacroAssembler* masm) { | 5107 void ArrayConstructorStub::Generate(MacroAssembler* masm) { |
5156 // ----------- S t a t e ------------- | 5108 // ----------- S t a t e ------------- |
5157 // -- eax : argc (only if argument_count_ == ANY) | 5109 // -- eax : argc (only if argument_count_ == ANY) |
5158 // -- ebx : feedback vector (fixed array or undefined) | 5110 // -- ebx : AllocationSite or undefined |
5159 // -- edx : slot index (if ebx is fixed array) | |
5160 // -- edi : constructor | 5111 // -- edi : constructor |
5161 // -- esp[0] : return address | 5112 // -- esp[0] : return address |
5162 // -- esp[4] : last argument | 5113 // -- esp[4] : last argument |
5163 // ----------------------------------- | 5114 // ----------------------------------- |
5164 Handle<Object> undefined_sentinel( | 5115 Handle<Object> undefined_sentinel( |
5165 masm->isolate()->heap()->undefined_value(), | 5116 masm->isolate()->heap()->undefined_value(), |
5166 masm->isolate()); | 5117 masm->isolate()); |
5167 | 5118 |
5168 if (FLAG_debug_code) { | 5119 if (FLAG_debug_code) { |
5169 // The array construct code is only set for the global and natives | 5120 // The array construct code is only set for the global and natives |
5170 // builtin Array functions which always have maps. | 5121 // builtin Array functions which always have maps. |
5171 | 5122 |
5172 // Initial map for the builtin Array function should be a map. | 5123 // Initial map for the builtin Array function should be a map. |
5173 __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); | 5124 __ mov(ecx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); |
5174 // Will both indicate a NULL and a Smi. | 5125 // Will both indicate a NULL and a Smi. |
5175 __ test(ecx, Immediate(kSmiTagMask)); | 5126 __ test(ecx, Immediate(kSmiTagMask)); |
5176 __ Assert(not_zero, kUnexpectedInitialMapForArrayFunction); | 5127 __ Assert(not_zero, kUnexpectedInitialMapForArrayFunction); |
5177 __ CmpObjectType(ecx, MAP_TYPE, ecx); | 5128 __ CmpObjectType(ecx, MAP_TYPE, ecx); |
5178 __ Assert(equal, kUnexpectedInitialMapForArrayFunction); | 5129 __ Assert(equal, kUnexpectedInitialMapForArrayFunction); |
5179 | 5130 |
5180 // We should either have undefined in ebx or a valid fixed array. | 5131 // We should either have undefined in ebx or a valid AllocationSite |
5181 Label okay_here; | 5132 __ AssertUndefinedOrAllocationSite(ebx); |
5182 Handle<Map> fixed_array_map = masm->isolate()->factory()->fixed_array_map(); | |
5183 __ cmp(ebx, Immediate(undefined_sentinel)); | |
5184 __ j(equal, &okay_here); | |
5185 __ cmp(FieldOperand(ebx, 0), Immediate(fixed_array_map)); | |
5186 __ Assert(equal, kExpectedFixedArrayInRegisterEbx); | |
5187 | |
5188 // edx should be a smi if we don't have undefined in ebx. | |
5189 __ AssertSmi(edx); | |
5190 | |
5191 __ bind(&okay_here); | |
5192 } | 5133 } |
5193 | 5134 |
5194 Label no_info; | 5135 Label no_info; |
5195 // If the feedback vector is undefined, or contains anything other than an | 5136 // If the feedback vector is undefined, or contains anything other than an |
5196 // AllocationSite, call an array constructor that doesn't use AllocationSites. | 5137 // AllocationSite, call an array constructor that doesn't use AllocationSites. |
5197 __ cmp(ebx, Immediate(undefined_sentinel)); | 5138 __ cmp(ebx, Immediate(undefined_sentinel)); |
5198 __ j(equal, &no_info); | 5139 __ j(equal, &no_info); |
5199 __ mov(ebx, FieldOperand(ebx, edx, times_half_pointer_size, | |
5200 FixedArray::kHeaderSize)); | |
5201 __ cmp(FieldOperand(ebx, 0), Immediate( | |
5202 masm->isolate()->factory()->allocation_site_map())); | |
5203 __ j(not_equal, &no_info); | |
5204 | 5140 |
5205 // Only look at the lower 16 bits of the transition info. | 5141 // Only look at the lower 16 bits of the transition info. |
5206 __ mov(edx, FieldOperand(ebx, AllocationSite::kTransitionInfoOffset)); | 5142 __ mov(edx, FieldOperand(ebx, AllocationSite::kTransitionInfoOffset)); |
5207 __ SmiUntag(edx); | 5143 __ SmiUntag(edx); |
5208 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); | 5144 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); |
5209 __ and_(edx, Immediate(AllocationSite::ElementsKindBits::kMask)); | 5145 __ and_(edx, Immediate(AllocationSite::ElementsKindBits::kMask)); |
5210 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); | 5146 GenerateDispatchToArrayStub(masm, DONT_OVERRIDE); |
5211 | 5147 |
5212 __ bind(&no_info); | 5148 __ bind(&no_info); |
5213 GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES); | 5149 GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES); |
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5453 Operand(ebp, 7 * kPointerSize), | 5389 Operand(ebp, 7 * kPointerSize), |
5454 NULL); | 5390 NULL); |
5455 } | 5391 } |
5456 | 5392 |
5457 | 5393 |
5458 #undef __ | 5394 #undef __ |
5459 | 5395 |
5460 } } // namespace v8::internal | 5396 } } // namespace v8::internal |
5461 | 5397 |
5462 #endif // V8_TARGET_ARCH_IA32 | 5398 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |