| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_IA32 | 7 #if V8_TARGET_ARCH_IA32 |
| 8 | 8 |
| 9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
| 10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
| 11 #include "src/code-stubs.h" | 11 #include "src/code-stubs.h" |
| 12 #include "src/codegen.h" | 12 #include "src/codegen.h" |
| 13 #include "src/ic/handler-compiler.h" | 13 #include "src/ic/handler-compiler.h" |
| 14 #include "src/ic/ic.h" | 14 #include "src/ic/ic.h" |
| 15 #include "src/ic/stub-cache.h" |
| 15 #include "src/isolate.h" | 16 #include "src/isolate.h" |
| 16 #include "src/jsregexp.h" | 17 #include "src/jsregexp.h" |
| 17 #include "src/regexp-macro-assembler.h" | 18 #include "src/regexp-macro-assembler.h" |
| 18 #include "src/runtime/runtime.h" | 19 #include "src/runtime/runtime.h" |
| 19 | 20 |
| 20 namespace v8 { | 21 namespace v8 { |
| 21 namespace internal { | 22 namespace internal { |
| 22 | 23 |
| 23 | 24 |
| 24 static void InitializeArrayConstructorDescriptor( | 25 static void InitializeArrayConstructorDescriptor( |
| (...skipping 620 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 645 __ bind(&done); | 646 __ bind(&done); |
| 646 __ IncrementCounter(counters->math_pow(), 1); | 647 __ IncrementCounter(counters->math_pow(), 1); |
| 647 __ ret(0); | 648 __ ret(0); |
| 648 } | 649 } |
| 649 } | 650 } |
| 650 | 651 |
| 651 | 652 |
| 652 void FunctionPrototypeStub::Generate(MacroAssembler* masm) { | 653 void FunctionPrototypeStub::Generate(MacroAssembler* masm) { |
| 653 Label miss; | 654 Label miss; |
| 654 Register receiver = LoadDescriptor::ReceiverRegister(); | 655 Register receiver = LoadDescriptor::ReceiverRegister(); |
| 656 if (FLAG_vector_ics) { |
| 657 // With careful management, we won't have to save slot and vector on |
| 658 // the stack. Simply handle the possibly missing case first. |
| 659 // TODO(mvstanton): this code can be more efficient. |
| 660 __ cmp(FieldOperand(receiver, JSFunction::kPrototypeOrInitialMapOffset), |
| 661 Immediate(isolate()->factory()->the_hole_value())); |
| 662 __ j(equal, &miss); |
| 663 __ TryGetFunctionPrototype(receiver, eax, ebx, &miss); |
| 664 __ ret(0); |
| 665 } else { |
| 666 NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, eax, |
| 667 ebx, &miss); |
| 668 } |
| 655 | 669 |
| 656 NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(masm, receiver, eax, | |
| 657 ebx, &miss); | |
| 658 __ bind(&miss); | 670 __ bind(&miss); |
| 659 PropertyAccessCompiler::TailCallBuiltin( | 671 PropertyAccessCompiler::TailCallBuiltin( |
| 660 masm, PropertyAccessCompiler::MissBuiltin(Code::LOAD_IC)); | 672 masm, PropertyAccessCompiler::MissBuiltin(Code::LOAD_IC)); |
| 661 } | 673 } |
| 662 | 674 |
| 663 | 675 |
| 664 void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) { | 676 void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) { |
| 665 // Return address is on the stack. | 677 // Return address is on the stack. |
| 666 Label slow; | 678 Label slow; |
| 667 | 679 |
| (...skipping 3603 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4271 __ pop(ecx); | 4283 __ pop(ecx); |
| 4272 int additional_offset = | 4284 int additional_offset = |
| 4273 function_mode() == JS_FUNCTION_STUB_MODE ? kPointerSize : 0; | 4285 function_mode() == JS_FUNCTION_STUB_MODE ? kPointerSize : 0; |
| 4274 __ lea(esp, MemOperand(esp, ebx, times_pointer_size, additional_offset)); | 4286 __ lea(esp, MemOperand(esp, ebx, times_pointer_size, additional_offset)); |
| 4275 __ jmp(ecx); // Return to IC Miss stub, continuation still on stack. | 4287 __ jmp(ecx); // Return to IC Miss stub, continuation still on stack. |
| 4276 } | 4288 } |
| 4277 | 4289 |
| 4278 | 4290 |
| 4279 void LoadICTrampolineStub::Generate(MacroAssembler* masm) { | 4291 void LoadICTrampolineStub::Generate(MacroAssembler* masm) { |
| 4280 EmitLoadTypeFeedbackVector(masm, VectorLoadICDescriptor::VectorRegister()); | 4292 EmitLoadTypeFeedbackVector(masm, VectorLoadICDescriptor::VectorRegister()); |
| 4281 VectorLoadStub stub(isolate(), state()); | 4293 if (FLAG_hydrogen_vector_dispatcher) { |
| 4282 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); | 4294 VectorLoadStub stub(isolate(), state()); |
| 4295 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); |
| 4296 } else { |
| 4297 VectorRawLoadStub stub(isolate(), state()); |
| 4298 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); |
| 4299 } |
| 4283 } | 4300 } |
| 4284 | 4301 |
| 4285 | 4302 |
| 4286 void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) { | 4303 void KeyedLoadICTrampolineStub::Generate(MacroAssembler* masm) { |
| 4287 EmitLoadTypeFeedbackVector(masm, VectorLoadICDescriptor::VectorRegister()); | 4304 EmitLoadTypeFeedbackVector(masm, VectorLoadICDescriptor::VectorRegister()); |
| 4288 VectorKeyedLoadStub stub(isolate()); | 4305 if (FLAG_hydrogen_vector_dispatcher) { |
| 4289 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); | 4306 VectorKeyedLoadStub stub(isolate()); |
| 4307 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); |
| 4308 } else { |
| 4309 VectorRawKeyedLoadStub stub(isolate()); |
| 4310 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); |
| 4311 } |
| 4290 } | 4312 } |
| 4291 | 4313 |
| 4292 | 4314 |
| 4315 static void HandleArrayCases(MacroAssembler* masm, Register receiver, |
| 4316 Register key, Register vector, Register slot, |
| 4317 Register feedback, Label* miss, bool keyed_load) { |
| 4318 int initial_element = keyed_load ? 1 : 0; |
| 4319 // feedback initially contains the feedback array |
| 4320 Label next, next_loop, prepare_next; |
| 4321 __ push(receiver); |
| 4322 Register receiver_map = receiver; |
| 4323 __ mov(receiver_map, FieldOperand(receiver, 0)); |
| 4324 __ cmp( |
| 4325 receiver_map, |
| 4326 FieldOperand(feedback, FixedArray::OffsetOfElementAt(initial_element))); |
| 4327 __ j(not_equal, &next); |
| 4328 // found, now call handler. |
| 4329 __ mov(feedback, FieldOperand(feedback, FixedArray::OffsetOfElementAt( |
| 4330 initial_element + 1))); |
| 4331 __ pop(receiver); |
| 4332 __ lea(feedback, FieldOperand(feedback, Code::kHeaderSize)); |
| 4333 __ jmp(feedback); |
| 4334 |
| 4335 __ bind(&next); |
| 4336 __ cmp(FieldOperand(feedback, FixedArray::kLengthOffset), |
| 4337 Immediate(Smi::FromInt(initial_element + 2))); |
| 4338 Label start_polymorphic; |
| 4339 __ j(not_equal, &start_polymorphic); |
| 4340 __ pop(receiver); |
| 4341 __ jmp(miss); |
| 4342 |
| 4343 // Polymorphic, we have to loop from (initial_element + 2) to N |
| 4344 __ bind(&start_polymorphic); |
| 4345 __ push(key); |
| 4346 Register counter = key; |
| 4347 __ mov(counter, Immediate(Smi::FromInt(initial_element + 2))); |
| 4348 __ bind(&next_loop); |
| 4349 __ cmp(receiver_map, FieldOperand(feedback, counter, times_half_pointer_size, |
| 4350 FixedArray::kHeaderSize)); |
| 4351 __ j(not_equal, &prepare_next); |
| 4352 __ mov(feedback, FieldOperand(feedback, counter, times_half_pointer_size, |
| 4353 FixedArray::kHeaderSize + kPointerSize)); |
| 4354 __ pop(key); |
| 4355 __ pop(receiver); |
| 4356 __ lea(feedback, FieldOperand(feedback, Code::kHeaderSize)); |
| 4357 __ jmp(feedback); |
| 4358 |
| 4359 __ bind(&prepare_next); |
| 4360 __ add(counter, Immediate(Smi::FromInt(2))); |
| 4361 __ cmp(counter, FieldOperand(feedback, FixedArray::kLengthOffset)); |
| 4362 __ j(less, &next_loop); |
| 4363 |
| 4364 // We exhausted our array of map handler pairs. |
| 4365 __ pop(key); |
| 4366 __ pop(receiver); |
| 4367 __ jmp(miss); |
| 4368 } |
| 4369 |
| 4370 |
| 4371 void VectorRawLoadStub::Generate(MacroAssembler* masm) { |
| 4372 Register receiver = VectorLoadICDescriptor::ReceiverRegister(); // edx |
| 4373 Register name = VectorLoadICDescriptor::NameRegister(); // ecx |
| 4374 Register vector = VectorLoadICDescriptor::VectorRegister(); // ebx |
| 4375 Register slot = VectorLoadICDescriptor::SlotRegister(); // eax |
| 4376 Factory* factory = masm->isolate()->factory(); |
| 4377 Register scratch = edi; |
| 4378 __ mov(scratch, FieldOperand(vector, slot, times_half_pointer_size, |
| 4379 FixedArray::kHeaderSize)); |
| 4380 // Is it a fixed array? |
| 4381 __ cmp(FieldOperand(scratch, 0), factory->fixed_array_map()); |
| 4382 Label not_array, miss; |
| 4383 __ j(not_equal, ¬_array); |
| 4384 __ JumpIfSmi(receiver, &miss); |
| 4385 HandleArrayCases(masm, receiver, name, vector, slot, scratch, &miss, false); |
| 4386 __ int3(); // We shouldn't get here. |
| 4387 |
| 4388 __ bind(¬_array); |
| 4389 __ cmp(scratch, factory->megamorphic_symbol()); |
| 4390 __ j(not_equal, &miss); |
| 4391 __ push(slot); |
| 4392 __ push(vector); |
| 4393 Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags( |
| 4394 Code::ComputeHandlerFlags(Code::LOAD_IC)); |
| 4395 masm->isolate()->stub_cache()->GenerateProbe(masm, code_flags, false, |
| 4396 receiver, name, vector, scratch); |
| 4397 __ pop(vector); |
| 4398 __ pop(slot); |
| 4399 |
| 4400 __ bind(&miss); |
| 4401 LoadIC::GenerateMiss(masm); |
| 4402 } |
| 4403 |
| 4404 |
| 4405 void VectorRawKeyedLoadStub::Generate(MacroAssembler* masm) { |
| 4406 Register receiver = VectorLoadICDescriptor::ReceiverRegister(); // edx |
| 4407 Register key = VectorLoadICDescriptor::NameRegister(); // ecx |
| 4408 Register vector = VectorLoadICDescriptor::VectorRegister(); // ebx |
| 4409 Register slot = VectorLoadICDescriptor::SlotRegister(); // eax |
| 4410 Factory* factory = masm->isolate()->factory(); |
| 4411 Register scratch = edi; |
| 4412 __ mov(scratch, FieldOperand(vector, slot, times_half_pointer_size, |
| 4413 FixedArray::kHeaderSize)); |
| 4414 // Is it a fixed array? |
| 4415 __ cmp(FieldOperand(scratch, 0), factory->fixed_array_map()); |
| 4416 Label not_array, smi_key, key_okay, miss; |
| 4417 __ j(not_equal, ¬_array); |
| 4418 // Do we have an element handler or a string handler? |
| 4419 const int name_offset = FixedArray::OffsetOfElementAt(0); |
| 4420 __ cmp(FieldOperand(scratch, name_offset), Immediate(Smi::FromInt(0))); |
| 4421 __ j(equal, &smi_key); |
| 4422 __ cmp(key, FieldOperand(scratch, name_offset)); |
| 4423 __ j(not_equal, &miss); |
| 4424 __ jmp(&key_okay); |
| 4425 __ bind(&smi_key); |
| 4426 __ JumpIfNotSmi(key, &miss); |
| 4427 __ bind(&key_okay); |
| 4428 __ JumpIfSmi(receiver, &miss); |
| 4429 HandleArrayCases(masm, receiver, key, vector, slot, scratch, &miss, true); |
| 4430 __ int3(); // We shouldn't get here. |
| 4431 |
| 4432 __ bind(¬_array); |
| 4433 // Is it generic? |
| 4434 __ cmp(scratch, factory->generic_symbol()); |
| 4435 Label megamorphic_check; |
| 4436 __ j(not_equal, &megamorphic_check); |
| 4437 Handle<Code> generic_stub = KeyedLoadIC::generic_stub(masm->isolate()); |
| 4438 __ jmp(generic_stub, RelocInfo::CODE_TARGET); |
| 4439 |
| 4440 __ bind(&megamorphic_check); |
| 4441 __ cmp(scratch, factory->megamorphic_symbol()); |
| 4442 __ j(not_equal, &miss); |
| 4443 __ JumpIfSmi(key, &miss); |
| 4444 __ push(slot); |
| 4445 __ push(vector); |
| 4446 Code::Flags code_flags = Code::RemoveTypeAndHolderFromFlags( |
| 4447 Code::ComputeHandlerFlags(Code::LOAD_IC)); |
| 4448 masm->isolate()->stub_cache()->GenerateProbe(masm, code_flags, false, |
| 4449 receiver, key, vector, scratch); |
| 4450 __ pop(vector); |
| 4451 __ pop(slot); |
| 4452 |
| 4453 __ bind(&miss); |
| 4454 KeyedLoadIC::GenerateMiss(masm); |
| 4455 } |
| 4456 |
| 4457 |
| 4293 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { | 4458 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { |
| 4294 if (masm->isolate()->function_entry_hook() != NULL) { | 4459 if (masm->isolate()->function_entry_hook() != NULL) { |
| 4295 ProfileEntryHookStub stub(masm->isolate()); | 4460 ProfileEntryHookStub stub(masm->isolate()); |
| 4296 masm->CallStub(&stub); | 4461 masm->CallStub(&stub); |
| 4297 } | 4462 } |
| 4298 } | 4463 } |
| 4299 | 4464 |
| 4300 | 4465 |
| 4301 void ProfileEntryHookStub::Generate(MacroAssembler* masm) { | 4466 void ProfileEntryHookStub::Generate(MacroAssembler* masm) { |
| 4302 // Save volatile registers. | 4467 // Save volatile registers. |
| (...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4795 Operand(ebp, 7 * kPointerSize), | 4960 Operand(ebp, 7 * kPointerSize), |
| 4796 NULL); | 4961 NULL); |
| 4797 } | 4962 } |
| 4798 | 4963 |
| 4799 | 4964 |
| 4800 #undef __ | 4965 #undef __ |
| 4801 | 4966 |
| 4802 } } // namespace v8::internal | 4967 } } // namespace v8::internal |
| 4803 | 4968 |
| 4804 #endif // V8_TARGET_ARCH_IA32 | 4969 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |