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 #if V8_TARGET_ARCH_X87 | 5 #if V8_TARGET_ARCH_X87 |
6 | 6 |
7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 | 422 |
423 StubRuntimeCallHelper call_helper; | 423 StubRuntimeCallHelper call_helper; |
424 char_at_generator.GenerateSlow(masm, PART_OF_IC_HANDLER, call_helper); | 424 char_at_generator.GenerateSlow(masm, PART_OF_IC_HANDLER, call_helper); |
425 | 425 |
426 __ bind(&miss); | 426 __ bind(&miss); |
427 PropertyAccessCompiler::TailCallBuiltin( | 427 PropertyAccessCompiler::TailCallBuiltin( |
428 masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); | 428 masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); |
429 } | 429 } |
430 | 430 |
431 | 431 |
432 void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) { | |
433 // ecx : number of parameters (tagged) | |
434 // edx : parameters pointer | |
435 // edi : function | |
436 // esp[0] : return address | |
437 | |
438 DCHECK(edi.is(ArgumentsAccessNewDescriptor::function())); | |
439 DCHECK(ecx.is(ArgumentsAccessNewDescriptor::parameter_count())); | |
440 DCHECK(edx.is(ArgumentsAccessNewDescriptor::parameter_pointer())); | |
441 | |
442 // Check if the calling frame is an arguments adaptor frame. | |
443 Label runtime; | |
444 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | |
445 __ mov(eax, Operand(ebx, StandardFrameConstants::kContextOffset)); | |
446 __ cmp(eax, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | |
447 __ j(not_equal, &runtime, Label::kNear); | |
448 | |
449 // Patch the arguments.length and the parameters pointer. | |
450 __ mov(ecx, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | |
451 __ lea(edx, | |
452 Operand(ebx, ecx, times_2, StandardFrameConstants::kCallerSPOffset)); | |
453 | |
454 __ bind(&runtime); | |
455 __ pop(eax); // Pop return address. | |
456 __ push(edi); // Push function. | |
457 __ push(edx); // Push parameters pointer. | |
458 __ push(ecx); // Push parameter count. | |
459 __ push(eax); // Push return address. | |
460 __ TailCallRuntime(Runtime::kNewSloppyArguments); | |
461 } | |
462 | |
463 | |
464 void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { | |
465 // ecx : number of parameters (tagged) | |
466 // edx : parameters pointer | |
467 // edi : function | |
468 // esp[0] : return address | |
469 | |
470 DCHECK(edi.is(ArgumentsAccessNewDescriptor::function())); | |
471 DCHECK(ecx.is(ArgumentsAccessNewDescriptor::parameter_count())); | |
472 DCHECK(edx.is(ArgumentsAccessNewDescriptor::parameter_pointer())); | |
473 | |
474 // Check if the calling frame is an arguments adaptor frame. | |
475 Label adaptor_frame, try_allocate, runtime; | |
476 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | |
477 __ mov(eax, Operand(ebx, StandardFrameConstants::kContextOffset)); | |
478 __ cmp(eax, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | |
479 __ j(equal, &adaptor_frame, Label::kNear); | |
480 | |
481 // No adaptor, parameter count = argument count. | |
482 __ mov(ebx, ecx); | |
483 __ push(ecx); | |
484 __ jmp(&try_allocate, Label::kNear); | |
485 | |
486 // We have an adaptor frame. Patch the parameters pointer. | |
487 __ bind(&adaptor_frame); | |
488 __ mov(ebx, ecx); | |
489 __ push(ecx); | |
490 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | |
491 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | |
492 __ lea(edx, Operand(edx, ecx, times_2, | |
493 StandardFrameConstants::kCallerSPOffset)); | |
494 | |
495 // ebx = parameter count (tagged) | |
496 // ecx = argument count (smi-tagged) | |
497 // Compute the mapped parameter count = min(ebx, ecx) in ebx. | |
498 __ cmp(ebx, ecx); | |
499 __ j(less_equal, &try_allocate, Label::kNear); | |
500 __ mov(ebx, ecx); | |
501 | |
502 // Save mapped parameter count and function. | |
503 __ bind(&try_allocate); | |
504 __ push(edi); | |
505 __ push(ebx); | |
506 | |
507 // Compute the sizes of backing store, parameter map, and arguments object. | |
508 // 1. Parameter map, has 2 extra words containing context and backing store. | |
509 const int kParameterMapHeaderSize = | |
510 FixedArray::kHeaderSize + 2 * kPointerSize; | |
511 Label no_parameter_map; | |
512 __ test(ebx, ebx); | |
513 __ j(zero, &no_parameter_map, Label::kNear); | |
514 __ lea(ebx, Operand(ebx, times_2, kParameterMapHeaderSize)); | |
515 __ bind(&no_parameter_map); | |
516 | |
517 // 2. Backing store. | |
518 __ lea(ebx, Operand(ebx, ecx, times_2, FixedArray::kHeaderSize)); | |
519 | |
520 // 3. Arguments object. | |
521 __ add(ebx, Immediate(JSSloppyArgumentsObject::kSize)); | |
522 | |
523 // Do the allocation of all three objects in one go. | |
524 __ Allocate(ebx, eax, edi, no_reg, &runtime, TAG_OBJECT); | |
525 | |
526 // eax = address of new object(s) (tagged) | |
527 // ecx = argument count (smi-tagged) | |
528 // esp[0] = mapped parameter count (tagged) | |
529 // esp[4] = function | |
530 // esp[8] = parameter count (tagged) | |
531 // Get the arguments map from the current native context into edi. | |
532 Label has_mapped_parameters, instantiate; | |
533 __ mov(edi, NativeContextOperand()); | |
534 __ mov(ebx, Operand(esp, 0 * kPointerSize)); | |
535 __ test(ebx, ebx); | |
536 __ j(not_zero, &has_mapped_parameters, Label::kNear); | |
537 __ mov( | |
538 edi, | |
539 Operand(edi, Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX))); | |
540 __ jmp(&instantiate, Label::kNear); | |
541 | |
542 __ bind(&has_mapped_parameters); | |
543 __ mov(edi, Operand(edi, Context::SlotOffset( | |
544 Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX))); | |
545 __ bind(&instantiate); | |
546 | |
547 // eax = address of new object (tagged) | |
548 // ebx = mapped parameter count (tagged) | |
549 // ecx = argument count (smi-tagged) | |
550 // edi = address of arguments map (tagged) | |
551 // esp[0] = mapped parameter count (tagged) | |
552 // esp[4] = function | |
553 // esp[8] = parameter count (tagged) | |
554 // Copy the JS object part. | |
555 __ mov(FieldOperand(eax, JSObject::kMapOffset), edi); | |
556 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), | |
557 masm->isolate()->factory()->empty_fixed_array()); | |
558 __ mov(FieldOperand(eax, JSObject::kElementsOffset), | |
559 masm->isolate()->factory()->empty_fixed_array()); | |
560 | |
561 // Set up the callee in-object property. | |
562 STATIC_ASSERT(JSSloppyArgumentsObject::kCalleeIndex == 1); | |
563 __ mov(edi, Operand(esp, 1 * kPointerSize)); | |
564 __ AssertNotSmi(edi); | |
565 __ mov(FieldOperand(eax, JSSloppyArgumentsObject::kCalleeOffset), edi); | |
566 | |
567 // Use the length (smi tagged) and set that as an in-object property too. | |
568 __ AssertSmi(ecx); | |
569 __ mov(FieldOperand(eax, JSSloppyArgumentsObject::kLengthOffset), ecx); | |
570 | |
571 // Set up the elements pointer in the allocated arguments object. | |
572 // If we allocated a parameter map, edi will point there, otherwise to the | |
573 // backing store. | |
574 __ lea(edi, Operand(eax, JSSloppyArgumentsObject::kSize)); | |
575 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); | |
576 | |
577 // eax = address of new object (tagged) | |
578 // ebx = mapped parameter count (tagged) | |
579 // ecx = argument count (tagged) | |
580 // edx = address of receiver argument | |
581 // edi = address of parameter map or backing store (tagged) | |
582 // esp[0] = mapped parameter count (tagged) | |
583 // esp[4] = function | |
584 // esp[8] = parameter count (tagged) | |
585 // Free two registers. | |
586 __ push(edx); | |
587 __ push(eax); | |
588 | |
589 // Initialize parameter map. If there are no mapped arguments, we're done. | |
590 Label skip_parameter_map; | |
591 __ test(ebx, ebx); | |
592 __ j(zero, &skip_parameter_map); | |
593 | |
594 __ mov(FieldOperand(edi, FixedArray::kMapOffset), | |
595 Immediate(isolate()->factory()->sloppy_arguments_elements_map())); | |
596 __ lea(eax, Operand(ebx, reinterpret_cast<intptr_t>(Smi::FromInt(2)))); | |
597 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), eax); | |
598 __ mov(FieldOperand(edi, FixedArray::kHeaderSize + 0 * kPointerSize), esi); | |
599 __ lea(eax, Operand(edi, ebx, times_2, kParameterMapHeaderSize)); | |
600 __ mov(FieldOperand(edi, FixedArray::kHeaderSize + 1 * kPointerSize), eax); | |
601 | |
602 // Copy the parameter slots and the holes in the arguments. | |
603 // We need to fill in mapped_parameter_count slots. They index the context, | |
604 // where parameters are stored in reverse order, at | |
605 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 | |
606 // The mapped parameter thus need to get indices | |
607 // MIN_CONTEXT_SLOTS+parameter_count-1 .. | |
608 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count | |
609 // We loop from right to left. | |
610 Label parameters_loop, parameters_test; | |
611 __ push(ecx); | |
612 __ mov(eax, Operand(esp, 3 * kPointerSize)); | |
613 __ mov(ebx, Immediate(Smi::FromInt(Context::MIN_CONTEXT_SLOTS))); | |
614 __ add(ebx, Operand(esp, 5 * kPointerSize)); | |
615 __ sub(ebx, eax); | |
616 __ mov(ecx, isolate()->factory()->the_hole_value()); | |
617 __ mov(edx, edi); | |
618 __ lea(edi, Operand(edi, eax, times_2, kParameterMapHeaderSize)); | |
619 // eax = loop variable (tagged) | |
620 // ebx = mapping index (tagged) | |
621 // ecx = the hole value | |
622 // edx = address of parameter map (tagged) | |
623 // edi = address of backing store (tagged) | |
624 // esp[0] = argument count (tagged) | |
625 // esp[4] = address of new object (tagged) | |
626 // esp[8] = address of receiver argument | |
627 // esp[12] = mapped parameter count (tagged) | |
628 // esp[16] = function | |
629 // esp[20] = parameter count (tagged) | |
630 __ jmp(¶meters_test, Label::kNear); | |
631 | |
632 __ bind(¶meters_loop); | |
633 __ sub(eax, Immediate(Smi::FromInt(1))); | |
634 __ mov(FieldOperand(edx, eax, times_2, kParameterMapHeaderSize), ebx); | |
635 __ mov(FieldOperand(edi, eax, times_2, FixedArray::kHeaderSize), ecx); | |
636 __ add(ebx, Immediate(Smi::FromInt(1))); | |
637 __ bind(¶meters_test); | |
638 __ test(eax, eax); | |
639 __ j(not_zero, ¶meters_loop, Label::kNear); | |
640 __ pop(ecx); | |
641 | |
642 __ bind(&skip_parameter_map); | |
643 | |
644 // ecx = argument count (tagged) | |
645 // edi = address of backing store (tagged) | |
646 // esp[0] = address of new object (tagged) | |
647 // esp[4] = address of receiver argument | |
648 // esp[8] = mapped parameter count (tagged) | |
649 // esp[12] = function | |
650 // esp[16] = parameter count (tagged) | |
651 // Copy arguments header and remaining slots (if there are any). | |
652 __ mov(FieldOperand(edi, FixedArray::kMapOffset), | |
653 Immediate(isolate()->factory()->fixed_array_map())); | |
654 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx); | |
655 | |
656 Label arguments_loop, arguments_test; | |
657 __ mov(ebx, Operand(esp, 2 * kPointerSize)); | |
658 __ mov(edx, Operand(esp, 1 * kPointerSize)); | |
659 __ sub(edx, ebx); // Is there a smarter way to do negative scaling? | |
660 __ sub(edx, ebx); | |
661 __ jmp(&arguments_test, Label::kNear); | |
662 | |
663 __ bind(&arguments_loop); | |
664 __ sub(edx, Immediate(kPointerSize)); | |
665 __ mov(eax, Operand(edx, 0)); | |
666 __ mov(FieldOperand(edi, ebx, times_2, FixedArray::kHeaderSize), eax); | |
667 __ add(ebx, Immediate(Smi::FromInt(1))); | |
668 | |
669 __ bind(&arguments_test); | |
670 __ cmp(ebx, ecx); | |
671 __ j(less, &arguments_loop, Label::kNear); | |
672 | |
673 // Restore. | |
674 __ pop(eax); // Address of arguments object. | |
675 __ Drop(4); | |
676 | |
677 // Return. | |
678 __ ret(0); | |
679 | |
680 // Do the runtime call to allocate the arguments object. | |
681 __ bind(&runtime); | |
682 __ pop(eax); // Remove saved mapped parameter count. | |
683 __ pop(edi); // Pop saved function. | |
684 __ pop(eax); // Remove saved parameter count. | |
685 __ pop(eax); // Pop return address. | |
686 __ push(edi); // Push function. | |
687 __ push(edx); // Push parameters pointer. | |
688 __ push(ecx); // Push parameter count. | |
689 __ push(eax); // Push return address. | |
690 __ TailCallRuntime(Runtime::kNewSloppyArguments); | |
691 } | |
692 | |
693 | |
694 void RegExpExecStub::Generate(MacroAssembler* masm) { | 432 void RegExpExecStub::Generate(MacroAssembler* masm) { |
695 // Just jump directly to runtime if native RegExp is not selected at compile | 433 // Just jump directly to runtime if native RegExp is not selected at compile |
696 // time or if regexp entry in generated code is turned off runtime switch or | 434 // time or if regexp entry in generated code is turned off runtime switch or |
697 // at compilation. | 435 // at compilation. |
698 #ifdef V8_INTERPRETED_REGEXP | 436 #ifdef V8_INTERPRETED_REGEXP |
699 __ TailCallRuntime(Runtime::kRegExpExec); | 437 __ TailCallRuntime(Runtime::kRegExpExec); |
700 #else // V8_INTERPRETED_REGEXP | 438 #else // V8_INTERPRETED_REGEXP |
701 | 439 |
702 // Stack frame on entry. | 440 // Stack frame on entry. |
703 // esp[0]: return address | 441 // esp[0]: return address |
(...skipping 3519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4223 __ pop(key); | 3961 __ pop(key); |
4224 __ pop(vector); | 3962 __ pop(vector); |
4225 __ pop(receiver); | 3963 __ pop(receiver); |
4226 __ jmp(miss); | 3964 __ jmp(miss); |
4227 | 3965 |
4228 __ bind(&load_smi_map); | 3966 __ bind(&load_smi_map); |
4229 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); | 3967 __ LoadRoot(receiver_map, Heap::kHeapNumberMapRootIndex); |
4230 __ jmp(&compare_map); | 3968 __ jmp(&compare_map); |
4231 } | 3969 } |
4232 | 3970 |
4233 | |
4234 void VectorKeyedStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { | 3971 void VectorKeyedStoreICStub::GenerateImpl(MacroAssembler* masm, bool in_frame) { |
4235 Register receiver = VectorStoreICDescriptor::ReceiverRegister(); // edx | 3972 Register receiver = VectorStoreICDescriptor::ReceiverRegister(); // edx |
4236 Register key = VectorStoreICDescriptor::NameRegister(); // ecx | 3973 Register key = VectorStoreICDescriptor::NameRegister(); // ecx |
4237 Register value = VectorStoreICDescriptor::ValueRegister(); // eax | 3974 Register value = VectorStoreICDescriptor::ValueRegister(); // eax |
4238 Register vector = VectorStoreICDescriptor::VectorRegister(); // ebx | 3975 Register vector = VectorStoreICDescriptor::VectorRegister(); // ebx |
4239 Register slot = VectorStoreICDescriptor::SlotRegister(); // edi | 3976 Register slot = VectorStoreICDescriptor::SlotRegister(); // edi |
4240 Label miss; | 3977 Label miss; |
4241 | 3978 |
4242 __ push(value); | 3979 __ push(value); |
4243 | 3980 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4279 __ mov(scratch, FieldOperand(vector, slot, times_half_pointer_size, | 4016 __ mov(scratch, FieldOperand(vector, slot, times_half_pointer_size, |
4280 FixedArray::kHeaderSize + kPointerSize)); | 4017 FixedArray::kHeaderSize + kPointerSize)); |
4281 HandlePolymorphicStoreCase(masm, receiver, key, vector, slot, scratch, false, | 4018 HandlePolymorphicStoreCase(masm, receiver, key, vector, slot, scratch, false, |
4282 &miss); | 4019 &miss); |
4283 | 4020 |
4284 __ bind(&miss); | 4021 __ bind(&miss); |
4285 __ pop(value); | 4022 __ pop(value); |
4286 KeyedStoreIC::GenerateMiss(masm); | 4023 KeyedStoreIC::GenerateMiss(masm); |
4287 } | 4024 } |
4288 | 4025 |
4289 | |
4290 void CallICTrampolineStub::Generate(MacroAssembler* masm) { | 4026 void CallICTrampolineStub::Generate(MacroAssembler* masm) { |
4291 __ EmitLoadTypeFeedbackVector(ebx); | 4027 __ EmitLoadTypeFeedbackVector(ebx); |
4292 CallICStub stub(isolate(), state()); | 4028 CallICStub stub(isolate(), state()); |
4293 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); | 4029 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET); |
4294 } | 4030 } |
4295 | 4031 |
4296 | |
4297 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { | 4032 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { |
4298 if (masm->isolate()->function_entry_hook() != NULL) { | 4033 if (masm->isolate()->function_entry_hook() != NULL) { |
4299 ProfileEntryHookStub stub(masm->isolate()); | 4034 ProfileEntryHookStub stub(masm->isolate()); |
4300 masm->CallStub(&stub); | 4035 masm->CallStub(&stub); |
4301 } | 4036 } |
4302 } | 4037 } |
4303 | 4038 |
4304 | |
4305 void ProfileEntryHookStub::Generate(MacroAssembler* masm) { | 4039 void ProfileEntryHookStub::Generate(MacroAssembler* masm) { |
4306 // Save volatile registers. | 4040 // Save volatile registers. |
4307 const int kNumSavedRegisters = 3; | 4041 const int kNumSavedRegisters = 3; |
4308 __ push(eax); | 4042 __ push(eax); |
4309 __ push(ecx); | 4043 __ push(ecx); |
4310 __ push(edx); | 4044 __ push(edx); |
4311 | 4045 |
4312 // Calculate and push the original stack pointer. | 4046 // Calculate and push the original stack pointer. |
4313 __ lea(eax, Operand(esp, (kNumSavedRegisters + 1) * kPointerSize)); | 4047 __ lea(eax, Operand(esp, (kNumSavedRegisters + 1) * kPointerSize)); |
4314 __ push(eax); | 4048 __ push(eax); |
(...skipping 11 matching lines...) Expand all Loading... |
4326 __ add(esp, Immediate(2 * kPointerSize)); | 4060 __ add(esp, Immediate(2 * kPointerSize)); |
4327 | 4061 |
4328 // Restore ecx. | 4062 // Restore ecx. |
4329 __ pop(edx); | 4063 __ pop(edx); |
4330 __ pop(ecx); | 4064 __ pop(ecx); |
4331 __ pop(eax); | 4065 __ pop(eax); |
4332 | 4066 |
4333 __ ret(0); | 4067 __ ret(0); |
4334 } | 4068 } |
4335 | 4069 |
4336 | 4070 template <class T> |
4337 template<class T> | |
4338 static void CreateArrayDispatch(MacroAssembler* masm, | 4071 static void CreateArrayDispatch(MacroAssembler* masm, |
4339 AllocationSiteOverrideMode mode) { | 4072 AllocationSiteOverrideMode mode) { |
4340 if (mode == DISABLE_ALLOCATION_SITES) { | 4073 if (mode == DISABLE_ALLOCATION_SITES) { |
4341 T stub(masm->isolate(), | 4074 T stub(masm->isolate(), GetInitialFastElementsKind(), mode); |
4342 GetInitialFastElementsKind(), | |
4343 mode); | |
4344 __ TailCallStub(&stub); | 4075 __ TailCallStub(&stub); |
4345 } else if (mode == DONT_OVERRIDE) { | 4076 } else if (mode == DONT_OVERRIDE) { |
4346 int last_index = GetSequenceIndexFromFastElementsKind( | 4077 int last_index = |
4347 TERMINAL_FAST_ELEMENTS_KIND); | 4078 GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND); |
4348 for (int i = 0; i <= last_index; ++i) { | 4079 for (int i = 0; i <= last_index; ++i) { |
4349 Label next; | 4080 Label next; |
4350 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 4081 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
4351 __ cmp(edx, kind); | 4082 __ cmp(edx, kind); |
4352 __ j(not_equal, &next); | 4083 __ j(not_equal, &next); |
4353 T stub(masm->isolate(), kind); | 4084 T stub(masm->isolate(), kind); |
4354 __ TailCallStub(&stub); | 4085 __ TailCallStub(&stub); |
4355 __ bind(&next); | 4086 __ bind(&next); |
4356 } | 4087 } |
4357 | 4088 |
4358 // If we reached this point there is a problem. | 4089 // If we reached this point there is a problem. |
4359 __ Abort(kUnexpectedElementsKindInArrayConstructor); | 4090 __ Abort(kUnexpectedElementsKindInArrayConstructor); |
4360 } else { | 4091 } else { |
4361 UNREACHABLE(); | 4092 UNREACHABLE(); |
4362 } | 4093 } |
4363 } | 4094 } |
4364 | 4095 |
4365 | |
4366 static void CreateArrayDispatchOneArgument(MacroAssembler* masm, | 4096 static void CreateArrayDispatchOneArgument(MacroAssembler* masm, |
4367 AllocationSiteOverrideMode mode) { | 4097 AllocationSiteOverrideMode mode) { |
4368 // ebx - allocation site (if mode != DISABLE_ALLOCATION_SITES) | 4098 // ebx - allocation site (if mode != DISABLE_ALLOCATION_SITES) |
4369 // edx - kind (if mode != DISABLE_ALLOCATION_SITES) | 4099 // edx - kind (if mode != DISABLE_ALLOCATION_SITES) |
4370 // eax - number of arguments | 4100 // eax - number of arguments |
4371 // edi - constructor? | 4101 // edi - constructor? |
4372 // esp[0] - return address | 4102 // esp[0] - return address |
4373 // esp[4] - last argument | 4103 // esp[4] - last argument |
4374 Label normal_sequence; | 4104 Label normal_sequence; |
4375 if (mode == DONT_OVERRIDE) { | 4105 if (mode == DONT_OVERRIDE) { |
(...skipping 11 matching lines...) Expand all Loading... |
4387 | 4117 |
4388 // look at the first argument | 4118 // look at the first argument |
4389 __ mov(ecx, Operand(esp, kPointerSize)); | 4119 __ mov(ecx, Operand(esp, kPointerSize)); |
4390 __ test(ecx, ecx); | 4120 __ test(ecx, ecx); |
4391 __ j(zero, &normal_sequence); | 4121 __ j(zero, &normal_sequence); |
4392 | 4122 |
4393 if (mode == DISABLE_ALLOCATION_SITES) { | 4123 if (mode == DISABLE_ALLOCATION_SITES) { |
4394 ElementsKind initial = GetInitialFastElementsKind(); | 4124 ElementsKind initial = GetInitialFastElementsKind(); |
4395 ElementsKind holey_initial = GetHoleyElementsKind(initial); | 4125 ElementsKind holey_initial = GetHoleyElementsKind(initial); |
4396 | 4126 |
4397 ArraySingleArgumentConstructorStub stub_holey(masm->isolate(), | 4127 ArraySingleArgumentConstructorStub stub_holey( |
4398 holey_initial, | 4128 masm->isolate(), holey_initial, DISABLE_ALLOCATION_SITES); |
4399 DISABLE_ALLOCATION_SITES); | |
4400 __ TailCallStub(&stub_holey); | 4129 __ TailCallStub(&stub_holey); |
4401 | 4130 |
4402 __ bind(&normal_sequence); | 4131 __ bind(&normal_sequence); |
4403 ArraySingleArgumentConstructorStub stub(masm->isolate(), | 4132 ArraySingleArgumentConstructorStub stub(masm->isolate(), initial, |
4404 initial, | |
4405 DISABLE_ALLOCATION_SITES); | 4133 DISABLE_ALLOCATION_SITES); |
4406 __ TailCallStub(&stub); | 4134 __ TailCallStub(&stub); |
4407 } else if (mode == DONT_OVERRIDE) { | 4135 } else if (mode == DONT_OVERRIDE) { |
4408 // We are going to create a holey array, but our kind is non-holey. | 4136 // We are going to create a holey array, but our kind is non-holey. |
4409 // Fix kind and retry. | 4137 // Fix kind and retry. |
4410 __ inc(edx); | 4138 __ inc(edx); |
4411 | 4139 |
4412 if (FLAG_debug_code) { | 4140 if (FLAG_debug_code) { |
4413 Handle<Map> allocation_site_map = | 4141 Handle<Map> allocation_site_map = |
4414 masm->isolate()->factory()->allocation_site_map(); | 4142 masm->isolate()->factory()->allocation_site_map(); |
4415 __ cmp(FieldOperand(ebx, 0), Immediate(allocation_site_map)); | 4143 __ cmp(FieldOperand(ebx, 0), Immediate(allocation_site_map)); |
4416 __ Assert(equal, kExpectedAllocationSite); | 4144 __ Assert(equal, kExpectedAllocationSite); |
4417 } | 4145 } |
4418 | 4146 |
4419 // Save the resulting elements kind in type info. We can't just store r3 | 4147 // Save the resulting elements kind in type info. We can't just store r3 |
4420 // in the AllocationSite::transition_info field because elements kind is | 4148 // in the AllocationSite::transition_info field because elements kind is |
4421 // restricted to a portion of the field...upper bits need to be left alone. | 4149 // restricted to a portion of the field...upper bits need to be left alone. |
4422 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); | 4150 STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0); |
4423 __ add(FieldOperand(ebx, AllocationSite::kTransitionInfoOffset), | 4151 __ add(FieldOperand(ebx, AllocationSite::kTransitionInfoOffset), |
4424 Immediate(Smi::FromInt(kFastElementsKindPackedToHoley))); | 4152 Immediate(Smi::FromInt(kFastElementsKindPackedToHoley))); |
4425 | 4153 |
4426 __ bind(&normal_sequence); | 4154 __ bind(&normal_sequence); |
4427 int last_index = GetSequenceIndexFromFastElementsKind( | 4155 int last_index = |
4428 TERMINAL_FAST_ELEMENTS_KIND); | 4156 GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND); |
4429 for (int i = 0; i <= last_index; ++i) { | 4157 for (int i = 0; i <= last_index; ++i) { |
4430 Label next; | 4158 Label next; |
4431 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 4159 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
4432 __ cmp(edx, kind); | 4160 __ cmp(edx, kind); |
4433 __ j(not_equal, &next); | 4161 __ j(not_equal, &next); |
4434 ArraySingleArgumentConstructorStub stub(masm->isolate(), kind); | 4162 ArraySingleArgumentConstructorStub stub(masm->isolate(), kind); |
4435 __ TailCallStub(&stub); | 4163 __ TailCallStub(&stub); |
4436 __ bind(&next); | 4164 __ bind(&next); |
4437 } | 4165 } |
4438 | 4166 |
4439 // If we reached this point there is a problem. | 4167 // If we reached this point there is a problem. |
4440 __ Abort(kUnexpectedElementsKindInArrayConstructor); | 4168 __ Abort(kUnexpectedElementsKindInArrayConstructor); |
4441 } else { | 4169 } else { |
4442 UNREACHABLE(); | 4170 UNREACHABLE(); |
4443 } | 4171 } |
4444 } | 4172 } |
4445 | 4173 |
4446 | 4174 template <class T> |
4447 template<class T> | |
4448 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { | 4175 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { |
4449 int to_index = GetSequenceIndexFromFastElementsKind( | 4176 int to_index = |
4450 TERMINAL_FAST_ELEMENTS_KIND); | 4177 GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND); |
4451 for (int i = 0; i <= to_index; ++i) { | 4178 for (int i = 0; i <= to_index; ++i) { |
4452 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 4179 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
4453 T stub(isolate, kind); | 4180 T stub(isolate, kind); |
4454 stub.GetCode(); | 4181 stub.GetCode(); |
4455 if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) { | 4182 if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) { |
4456 T stub1(isolate, kind, DISABLE_ALLOCATION_SITES); | 4183 T stub1(isolate, kind, DISABLE_ALLOCATION_SITES); |
4457 stub1.GetCode(); | 4184 stub1.GetCode(); |
4458 } | 4185 } |
4459 } | 4186 } |
4460 } | 4187 } |
4461 | 4188 |
4462 | |
4463 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { | 4189 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { |
4464 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( | 4190 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( |
4465 isolate); | 4191 isolate); |
4466 ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>( | 4192 ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>( |
4467 isolate); | 4193 isolate); |
4468 ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>( | 4194 ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>( |
4469 isolate); | 4195 isolate); |
4470 } | 4196 } |
4471 | 4197 |
4472 | |
4473 void InternalArrayConstructorStubBase::GenerateStubsAheadOfTime( | 4198 void InternalArrayConstructorStubBase::GenerateStubsAheadOfTime( |
4474 Isolate* isolate) { | 4199 Isolate* isolate) { |
4475 ElementsKind kinds[2] = { FAST_ELEMENTS, FAST_HOLEY_ELEMENTS }; | 4200 ElementsKind kinds[2] = {FAST_ELEMENTS, FAST_HOLEY_ELEMENTS}; |
4476 for (int i = 0; i < 2; i++) { | 4201 for (int i = 0; i < 2; i++) { |
4477 // For internal arrays we only need a few things | 4202 // For internal arrays we only need a few things |
4478 InternalArrayNoArgumentConstructorStub stubh1(isolate, kinds[i]); | 4203 InternalArrayNoArgumentConstructorStub stubh1(isolate, kinds[i]); |
4479 stubh1.GetCode(); | 4204 stubh1.GetCode(); |
4480 InternalArraySingleArgumentConstructorStub stubh2(isolate, kinds[i]); | 4205 InternalArraySingleArgumentConstructorStub stubh2(isolate, kinds[i]); |
4481 stubh2.GetCode(); | 4206 stubh2.GetCode(); |
4482 InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]); | 4207 InternalArrayNArgumentsConstructorStub stubh3(isolate, kinds[i]); |
4483 stubh3.GetCode(); | 4208 stubh3.GetCode(); |
4484 } | 4209 } |
4485 } | 4210 } |
4486 | 4211 |
4487 | |
4488 void ArrayConstructorStub::GenerateDispatchToArrayStub( | 4212 void ArrayConstructorStub::GenerateDispatchToArrayStub( |
4489 MacroAssembler* masm, | 4213 MacroAssembler* masm, AllocationSiteOverrideMode mode) { |
4490 AllocationSiteOverrideMode mode) { | |
4491 if (argument_count() == ANY) { | 4214 if (argument_count() == ANY) { |
4492 Label not_zero_case, not_one_case; | 4215 Label not_zero_case, not_one_case; |
4493 __ test(eax, eax); | 4216 __ test(eax, eax); |
4494 __ j(not_zero, ¬_zero_case); | 4217 __ j(not_zero, ¬_zero_case); |
4495 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); | 4218 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); |
4496 | 4219 |
4497 __ bind(¬_zero_case); | 4220 __ bind(¬_zero_case); |
4498 __ cmp(eax, 1); | 4221 __ cmp(eax, 1); |
4499 __ j(greater, ¬_one_case); | 4222 __ j(greater, ¬_one_case); |
4500 CreateArrayDispatchOneArgument(masm, mode); | 4223 CreateArrayDispatchOneArgument(masm, mode); |
4501 | 4224 |
4502 __ bind(¬_one_case); | 4225 __ bind(¬_one_case); |
4503 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); | 4226 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); |
4504 } else if (argument_count() == NONE) { | 4227 } else if (argument_count() == NONE) { |
4505 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); | 4228 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm, mode); |
4506 } else if (argument_count() == ONE) { | 4229 } else if (argument_count() == ONE) { |
4507 CreateArrayDispatchOneArgument(masm, mode); | 4230 CreateArrayDispatchOneArgument(masm, mode); |
4508 } else if (argument_count() == MORE_THAN_ONE) { | 4231 } else if (argument_count() == MORE_THAN_ONE) { |
4509 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); | 4232 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm, mode); |
4510 } else { | 4233 } else { |
4511 UNREACHABLE(); | 4234 UNREACHABLE(); |
4512 } | 4235 } |
4513 } | 4236 } |
4514 | 4237 |
4515 | |
4516 void ArrayConstructorStub::Generate(MacroAssembler* masm) { | 4238 void ArrayConstructorStub::Generate(MacroAssembler* masm) { |
4517 // ----------- S t a t e ------------- | 4239 // ----------- S t a t e ------------- |
4518 // -- eax : argc (only if argument_count() is ANY or MORE_THAN_ONE) | 4240 // -- eax : argc (only if argument_count() is ANY or MORE_THAN_ONE) |
4519 // -- ebx : AllocationSite or undefined | 4241 // -- ebx : AllocationSite or undefined |
4520 // -- edi : constructor | 4242 // -- edi : constructor |
4521 // -- edx : Original constructor | 4243 // -- edx : Original constructor |
4522 // -- esp[0] : return address | 4244 // -- esp[0] : return address |
4523 // -- esp[4] : last argument | 4245 // -- esp[4] : last argument |
4524 // ----------------------------------- | 4246 // ----------------------------------- |
4525 if (FLAG_debug_code) { | 4247 if (FLAG_debug_code) { |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4579 __ mov(eax, Immediate(4)); | 4301 __ mov(eax, Immediate(4)); |
4580 break; | 4302 break; |
4581 } | 4303 } |
4582 __ PopReturnAddressTo(ecx); | 4304 __ PopReturnAddressTo(ecx); |
4583 __ Push(edx); | 4305 __ Push(edx); |
4584 __ Push(ebx); | 4306 __ Push(ebx); |
4585 __ PushReturnAddressFrom(ecx); | 4307 __ PushReturnAddressFrom(ecx); |
4586 __ JumpToExternalReference(ExternalReference(Runtime::kNewArray, isolate())); | 4308 __ JumpToExternalReference(ExternalReference(Runtime::kNewArray, isolate())); |
4587 } | 4309 } |
4588 | 4310 |
4589 | 4311 void InternalArrayConstructorStub::GenerateCase(MacroAssembler* masm, |
4590 void InternalArrayConstructorStub::GenerateCase( | 4312 ElementsKind kind) { |
4591 MacroAssembler* masm, ElementsKind kind) { | |
4592 Label not_zero_case, not_one_case; | 4313 Label not_zero_case, not_one_case; |
4593 Label normal_sequence; | 4314 Label normal_sequence; |
4594 | 4315 |
4595 __ test(eax, eax); | 4316 __ test(eax, eax); |
4596 __ j(not_zero, ¬_zero_case); | 4317 __ j(not_zero, ¬_zero_case); |
4597 InternalArrayNoArgumentConstructorStub stub0(isolate(), kind); | 4318 InternalArrayNoArgumentConstructorStub stub0(isolate(), kind); |
4598 __ TailCallStub(&stub0); | 4319 __ TailCallStub(&stub0); |
4599 | 4320 |
4600 __ bind(¬_zero_case); | 4321 __ bind(¬_zero_case); |
4601 __ cmp(eax, 1); | 4322 __ cmp(eax, 1); |
4602 __ j(greater, ¬_one_case); | 4323 __ j(greater, ¬_one_case); |
4603 | 4324 |
4604 if (IsFastPackedElementsKind(kind)) { | 4325 if (IsFastPackedElementsKind(kind)) { |
4605 // We might need to create a holey array | 4326 // We might need to create a holey array |
4606 // look at the first argument | 4327 // look at the first argument |
4607 __ mov(ecx, Operand(esp, kPointerSize)); | 4328 __ mov(ecx, Operand(esp, kPointerSize)); |
4608 __ test(ecx, ecx); | 4329 __ test(ecx, ecx); |
4609 __ j(zero, &normal_sequence); | 4330 __ j(zero, &normal_sequence); |
4610 | 4331 |
4611 InternalArraySingleArgumentConstructorStub | 4332 InternalArraySingleArgumentConstructorStub stub1_holey( |
4612 stub1_holey(isolate(), GetHoleyElementsKind(kind)); | 4333 isolate(), GetHoleyElementsKind(kind)); |
4613 __ TailCallStub(&stub1_holey); | 4334 __ TailCallStub(&stub1_holey); |
4614 } | 4335 } |
4615 | 4336 |
4616 __ bind(&normal_sequence); | 4337 __ bind(&normal_sequence); |
4617 InternalArraySingleArgumentConstructorStub stub1(isolate(), kind); | 4338 InternalArraySingleArgumentConstructorStub stub1(isolate(), kind); |
4618 __ TailCallStub(&stub1); | 4339 __ TailCallStub(&stub1); |
4619 | 4340 |
4620 __ bind(¬_one_case); | 4341 __ bind(¬_one_case); |
4621 InternalArrayNArgumentsConstructorStub stubN(isolate(), kind); | 4342 InternalArrayNArgumentsConstructorStub stubN(isolate(), kind); |
4622 __ TailCallStub(&stubN); | 4343 __ TailCallStub(&stubN); |
4623 } | 4344 } |
4624 | 4345 |
4625 | |
4626 void InternalArrayConstructorStub::Generate(MacroAssembler* masm) { | 4346 void InternalArrayConstructorStub::Generate(MacroAssembler* masm) { |
4627 // ----------- S t a t e ------------- | 4347 // ----------- S t a t e ------------- |
4628 // -- eax : argc | 4348 // -- eax : argc |
4629 // -- edi : constructor | 4349 // -- edi : constructor |
4630 // -- esp[0] : return address | 4350 // -- esp[0] : return address |
4631 // -- esp[4] : last argument | 4351 // -- esp[4] : last argument |
4632 // ----------------------------------- | 4352 // ----------------------------------- |
4633 | 4353 |
4634 if (FLAG_debug_code) { | 4354 if (FLAG_debug_code) { |
4635 // The array construct code is only set for the global and natives | 4355 // The array construct code is only set for the global and natives |
(...skipping 15 matching lines...) Expand all Loading... |
4651 // but the following masking takes care of that anyway. | 4371 // but the following masking takes care of that anyway. |
4652 __ mov(ecx, FieldOperand(ecx, Map::kBitField2Offset)); | 4372 __ mov(ecx, FieldOperand(ecx, Map::kBitField2Offset)); |
4653 // Retrieve elements_kind from bit field 2. | 4373 // Retrieve elements_kind from bit field 2. |
4654 __ DecodeField<Map::ElementsKindBits>(ecx); | 4374 __ DecodeField<Map::ElementsKindBits>(ecx); |
4655 | 4375 |
4656 if (FLAG_debug_code) { | 4376 if (FLAG_debug_code) { |
4657 Label done; | 4377 Label done; |
4658 __ cmp(ecx, Immediate(FAST_ELEMENTS)); | 4378 __ cmp(ecx, Immediate(FAST_ELEMENTS)); |
4659 __ j(equal, &done); | 4379 __ j(equal, &done); |
4660 __ cmp(ecx, Immediate(FAST_HOLEY_ELEMENTS)); | 4380 __ cmp(ecx, Immediate(FAST_HOLEY_ELEMENTS)); |
4661 __ Assert(equal, | 4381 __ Assert(equal, kInvalidElementsKindForInternalArrayOrInternalPackedArray); |
4662 kInvalidElementsKindForInternalArrayOrInternalPackedArray); | |
4663 __ bind(&done); | 4382 __ bind(&done); |
4664 } | 4383 } |
4665 | 4384 |
4666 Label fast_elements_case; | 4385 Label fast_elements_case; |
4667 __ cmp(ecx, Immediate(FAST_ELEMENTS)); | 4386 __ cmp(ecx, Immediate(FAST_ELEMENTS)); |
4668 __ j(equal, &fast_elements_case); | 4387 __ j(equal, &fast_elements_case); |
4669 GenerateCase(masm, FAST_HOLEY_ELEMENTS); | 4388 GenerateCase(masm, FAST_HOLEY_ELEMENTS); |
4670 | 4389 |
4671 __ bind(&fast_elements_case); | 4390 __ bind(&fast_elements_case); |
4672 GenerateCase(masm, FAST_ELEMENTS); | 4391 GenerateCase(masm, FAST_ELEMENTS); |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4811 __ Push(ecx); | 4530 __ Push(ecx); |
4812 __ CallRuntime(Runtime::kAllocateInNewSpace); | 4531 __ CallRuntime(Runtime::kAllocateInNewSpace); |
4813 __ mov(edx, eax); | 4532 __ mov(edx, eax); |
4814 __ Pop(ebx); | 4533 __ Pop(ebx); |
4815 __ Pop(eax); | 4534 __ Pop(eax); |
4816 } | 4535 } |
4817 __ jmp(&done_allocate); | 4536 __ jmp(&done_allocate); |
4818 } | 4537 } |
4819 } | 4538 } |
4820 | 4539 |
| 4540 void FastNewSloppyArgumentsStub::Generate(MacroAssembler* masm) { |
| 4541 // ----------- S t a t e ------------- |
| 4542 // -- edi : function |
| 4543 // -- esi : context |
| 4544 // -- ebp : frame pointer |
| 4545 // -- esp[0] : return address |
| 4546 // ----------------------------------- |
| 4547 __ AssertFunction(edi); |
| 4548 |
| 4549 // TODO(bmeurer): Cleanup to match the FastNewStrictArgumentsStub. |
| 4550 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
| 4551 __ mov(ecx, |
| 4552 FieldOperand(ecx, SharedFunctionInfo::kFormalParameterCountOffset)); |
| 4553 __ lea(edx, Operand(ebp, ecx, times_half_pointer_size, |
| 4554 StandardFrameConstants::kCallerSPOffset)); |
| 4555 |
| 4556 // ecx : number of parameters (tagged) |
| 4557 // edx : parameters pointer |
| 4558 // edi : function |
| 4559 // esp[0] : return address |
| 4560 |
| 4561 // Check if the calling frame is an arguments adaptor frame. |
| 4562 Label adaptor_frame, try_allocate, runtime; |
| 4563 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
| 4564 __ mov(eax, Operand(ebx, StandardFrameConstants::kContextOffset)); |
| 4565 __ cmp(eax, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 4566 __ j(equal, &adaptor_frame, Label::kNear); |
| 4567 |
| 4568 // No adaptor, parameter count = argument count. |
| 4569 __ mov(ebx, ecx); |
| 4570 __ push(ecx); |
| 4571 __ jmp(&try_allocate, Label::kNear); |
| 4572 |
| 4573 // We have an adaptor frame. Patch the parameters pointer. |
| 4574 __ bind(&adaptor_frame); |
| 4575 __ mov(ebx, ecx); |
| 4576 __ push(ecx); |
| 4577 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
| 4578 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 4579 __ lea(edx, |
| 4580 Operand(edx, ecx, times_2, StandardFrameConstants::kCallerSPOffset)); |
| 4581 |
| 4582 // ebx = parameter count (tagged) |
| 4583 // ecx = argument count (smi-tagged) |
| 4584 // Compute the mapped parameter count = min(ebx, ecx) in ebx. |
| 4585 __ cmp(ebx, ecx); |
| 4586 __ j(less_equal, &try_allocate, Label::kNear); |
| 4587 __ mov(ebx, ecx); |
| 4588 |
| 4589 // Save mapped parameter count and function. |
| 4590 __ bind(&try_allocate); |
| 4591 __ push(edi); |
| 4592 __ push(ebx); |
| 4593 |
| 4594 // Compute the sizes of backing store, parameter map, and arguments object. |
| 4595 // 1. Parameter map, has 2 extra words containing context and backing store. |
| 4596 const int kParameterMapHeaderSize = |
| 4597 FixedArray::kHeaderSize + 2 * kPointerSize; |
| 4598 Label no_parameter_map; |
| 4599 __ test(ebx, ebx); |
| 4600 __ j(zero, &no_parameter_map, Label::kNear); |
| 4601 __ lea(ebx, Operand(ebx, times_2, kParameterMapHeaderSize)); |
| 4602 __ bind(&no_parameter_map); |
| 4603 |
| 4604 // 2. Backing store. |
| 4605 __ lea(ebx, Operand(ebx, ecx, times_2, FixedArray::kHeaderSize)); |
| 4606 |
| 4607 // 3. Arguments object. |
| 4608 __ add(ebx, Immediate(JSSloppyArgumentsObject::kSize)); |
| 4609 |
| 4610 // Do the allocation of all three objects in one go. |
| 4611 __ Allocate(ebx, eax, edi, no_reg, &runtime, TAG_OBJECT); |
| 4612 |
| 4613 // eax = address of new object(s) (tagged) |
| 4614 // ecx = argument count (smi-tagged) |
| 4615 // esp[0] = mapped parameter count (tagged) |
| 4616 // esp[4] = function |
| 4617 // esp[8] = parameter count (tagged) |
| 4618 // Get the arguments map from the current native context into edi. |
| 4619 Label has_mapped_parameters, instantiate; |
| 4620 __ mov(edi, NativeContextOperand()); |
| 4621 __ mov(ebx, Operand(esp, 0 * kPointerSize)); |
| 4622 __ test(ebx, ebx); |
| 4623 __ j(not_zero, &has_mapped_parameters, Label::kNear); |
| 4624 __ mov( |
| 4625 edi, |
| 4626 Operand(edi, Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX))); |
| 4627 __ jmp(&instantiate, Label::kNear); |
| 4628 |
| 4629 __ bind(&has_mapped_parameters); |
| 4630 __ mov(edi, Operand(edi, Context::SlotOffset( |
| 4631 Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX))); |
| 4632 __ bind(&instantiate); |
| 4633 |
| 4634 // eax = address of new object (tagged) |
| 4635 // ebx = mapped parameter count (tagged) |
| 4636 // ecx = argument count (smi-tagged) |
| 4637 // edi = address of arguments map (tagged) |
| 4638 // esp[0] = mapped parameter count (tagged) |
| 4639 // esp[4] = function |
| 4640 // esp[8] = parameter count (tagged) |
| 4641 // Copy the JS object part. |
| 4642 __ mov(FieldOperand(eax, JSObject::kMapOffset), edi); |
| 4643 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), |
| 4644 masm->isolate()->factory()->empty_fixed_array()); |
| 4645 __ mov(FieldOperand(eax, JSObject::kElementsOffset), |
| 4646 masm->isolate()->factory()->empty_fixed_array()); |
| 4647 |
| 4648 // Set up the callee in-object property. |
| 4649 STATIC_ASSERT(JSSloppyArgumentsObject::kCalleeIndex == 1); |
| 4650 __ mov(edi, Operand(esp, 1 * kPointerSize)); |
| 4651 __ AssertNotSmi(edi); |
| 4652 __ mov(FieldOperand(eax, JSSloppyArgumentsObject::kCalleeOffset), edi); |
| 4653 |
| 4654 // Use the length (smi tagged) and set that as an in-object property too. |
| 4655 __ AssertSmi(ecx); |
| 4656 __ mov(FieldOperand(eax, JSSloppyArgumentsObject::kLengthOffset), ecx); |
| 4657 |
| 4658 // Set up the elements pointer in the allocated arguments object. |
| 4659 // If we allocated a parameter map, edi will point there, otherwise to the |
| 4660 // backing store. |
| 4661 __ lea(edi, Operand(eax, JSSloppyArgumentsObject::kSize)); |
| 4662 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); |
| 4663 |
| 4664 // eax = address of new object (tagged) |
| 4665 // ebx = mapped parameter count (tagged) |
| 4666 // ecx = argument count (tagged) |
| 4667 // edx = address of receiver argument |
| 4668 // edi = address of parameter map or backing store (tagged) |
| 4669 // esp[0] = mapped parameter count (tagged) |
| 4670 // esp[4] = function |
| 4671 // esp[8] = parameter count (tagged) |
| 4672 // Free two registers. |
| 4673 __ push(edx); |
| 4674 __ push(eax); |
| 4675 |
| 4676 // Initialize parameter map. If there are no mapped arguments, we're done. |
| 4677 Label skip_parameter_map; |
| 4678 __ test(ebx, ebx); |
| 4679 __ j(zero, &skip_parameter_map); |
| 4680 |
| 4681 __ mov(FieldOperand(edi, FixedArray::kMapOffset), |
| 4682 Immediate(isolate()->factory()->sloppy_arguments_elements_map())); |
| 4683 __ lea(eax, Operand(ebx, reinterpret_cast<intptr_t>(Smi::FromInt(2)))); |
| 4684 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), eax); |
| 4685 __ mov(FieldOperand(edi, FixedArray::kHeaderSize + 0 * kPointerSize), esi); |
| 4686 __ lea(eax, Operand(edi, ebx, times_2, kParameterMapHeaderSize)); |
| 4687 __ mov(FieldOperand(edi, FixedArray::kHeaderSize + 1 * kPointerSize), eax); |
| 4688 |
| 4689 // Copy the parameter slots and the holes in the arguments. |
| 4690 // We need to fill in mapped_parameter_count slots. They index the context, |
| 4691 // where parameters are stored in reverse order, at |
| 4692 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 |
| 4693 // The mapped parameter thus need to get indices |
| 4694 // MIN_CONTEXT_SLOTS+parameter_count-1 .. |
| 4695 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count |
| 4696 // We loop from right to left. |
| 4697 Label parameters_loop, parameters_test; |
| 4698 __ push(ecx); |
| 4699 __ mov(eax, Operand(esp, 3 * kPointerSize)); |
| 4700 __ mov(ebx, Immediate(Smi::FromInt(Context::MIN_CONTEXT_SLOTS))); |
| 4701 __ add(ebx, Operand(esp, 5 * kPointerSize)); |
| 4702 __ sub(ebx, eax); |
| 4703 __ mov(ecx, isolate()->factory()->the_hole_value()); |
| 4704 __ mov(edx, edi); |
| 4705 __ lea(edi, Operand(edi, eax, times_2, kParameterMapHeaderSize)); |
| 4706 // eax = loop variable (tagged) |
| 4707 // ebx = mapping index (tagged) |
| 4708 // ecx = the hole value |
| 4709 // edx = address of parameter map (tagged) |
| 4710 // edi = address of backing store (tagged) |
| 4711 // esp[0] = argument count (tagged) |
| 4712 // esp[4] = address of new object (tagged) |
| 4713 // esp[8] = address of receiver argument |
| 4714 // esp[12] = mapped parameter count (tagged) |
| 4715 // esp[16] = function |
| 4716 // esp[20] = parameter count (tagged) |
| 4717 __ jmp(¶meters_test, Label::kNear); |
| 4718 |
| 4719 __ bind(¶meters_loop); |
| 4720 __ sub(eax, Immediate(Smi::FromInt(1))); |
| 4721 __ mov(FieldOperand(edx, eax, times_2, kParameterMapHeaderSize), ebx); |
| 4722 __ mov(FieldOperand(edi, eax, times_2, FixedArray::kHeaderSize), ecx); |
| 4723 __ add(ebx, Immediate(Smi::FromInt(1))); |
| 4724 __ bind(¶meters_test); |
| 4725 __ test(eax, eax); |
| 4726 __ j(not_zero, ¶meters_loop, Label::kNear); |
| 4727 __ pop(ecx); |
| 4728 |
| 4729 __ bind(&skip_parameter_map); |
| 4730 |
| 4731 // ecx = argument count (tagged) |
| 4732 // edi = address of backing store (tagged) |
| 4733 // esp[0] = address of new object (tagged) |
| 4734 // esp[4] = address of receiver argument |
| 4735 // esp[8] = mapped parameter count (tagged) |
| 4736 // esp[12] = function |
| 4737 // esp[16] = parameter count (tagged) |
| 4738 // Copy arguments header and remaining slots (if there are any). |
| 4739 __ mov(FieldOperand(edi, FixedArray::kMapOffset), |
| 4740 Immediate(isolate()->factory()->fixed_array_map())); |
| 4741 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx); |
| 4742 |
| 4743 Label arguments_loop, arguments_test; |
| 4744 __ mov(ebx, Operand(esp, 2 * kPointerSize)); |
| 4745 __ mov(edx, Operand(esp, 1 * kPointerSize)); |
| 4746 __ sub(edx, ebx); // Is there a smarter way to do negative scaling? |
| 4747 __ sub(edx, ebx); |
| 4748 __ jmp(&arguments_test, Label::kNear); |
| 4749 |
| 4750 __ bind(&arguments_loop); |
| 4751 __ sub(edx, Immediate(kPointerSize)); |
| 4752 __ mov(eax, Operand(edx, 0)); |
| 4753 __ mov(FieldOperand(edi, ebx, times_2, FixedArray::kHeaderSize), eax); |
| 4754 __ add(ebx, Immediate(Smi::FromInt(1))); |
| 4755 |
| 4756 __ bind(&arguments_test); |
| 4757 __ cmp(ebx, ecx); |
| 4758 __ j(less, &arguments_loop, Label::kNear); |
| 4759 |
| 4760 // Restore. |
| 4761 __ pop(eax); // Address of arguments object. |
| 4762 __ Drop(4); |
| 4763 |
| 4764 // Return. |
| 4765 __ ret(0); |
| 4766 |
| 4767 // Do the runtime call to allocate the arguments object. |
| 4768 __ bind(&runtime); |
| 4769 __ pop(eax); // Remove saved mapped parameter count. |
| 4770 __ pop(edi); // Pop saved function. |
| 4771 __ pop(eax); // Remove saved parameter count. |
| 4772 __ pop(eax); // Pop return address. |
| 4773 __ push(edi); // Push function. |
| 4774 __ push(edx); // Push parameters pointer. |
| 4775 __ push(ecx); // Push parameter count. |
| 4776 __ push(eax); // Push return address. |
| 4777 __ TailCallRuntime(Runtime::kNewSloppyArguments); |
| 4778 } |
| 4779 |
4821 void FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) { | 4780 void FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) { |
4822 // ----------- S t a t e ------------- | 4781 // ----------- S t a t e ------------- |
4823 // -- edi : function | 4782 // -- edi : function |
4824 // -- esi : context | 4783 // -- esi : context |
4825 // -- ebp : frame pointer | 4784 // -- ebp : frame pointer |
4826 // -- esp[0] : return address | 4785 // -- esp[0] : return address |
4827 // ----------------------------------- | 4786 // ----------------------------------- |
4828 __ AssertFunction(edi); | 4787 __ AssertFunction(edi); |
4829 | 4788 |
4830 // For Ignition we need to skip all possible handler/stub frames until | 4789 // For Ignition we need to skip all possible handler/stub frames until |
(...skipping 650 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5481 return_value_operand, NULL); | 5440 return_value_operand, NULL); |
5482 } | 5441 } |
5483 | 5442 |
5484 | 5443 |
5485 #undef __ | 5444 #undef __ |
5486 | 5445 |
5487 } // namespace internal | 5446 } // namespace internal |
5488 } // namespace v8 | 5447 } // namespace v8 |
5489 | 5448 |
5490 #endif // V8_TARGET_ARCH_X87 | 5449 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |