30 #if defined(V8_TARGET_ARCH_IA32)
40 #define __ ACCESS_MASM(masm)
43 void Builtins::Generate_Adaptor(MacroAssembler* masm,
59 int num_extra_args = 0;
62 Register scratch =
ebx;
72 __ add(
eax, Immediate(num_extra_args + 1));
73 __ JumpToExternalReference(ExternalReference(
id, masm->isolate()));
77 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
79 bool count_constructions) {
86 ASSERT(!is_api_function || !count_constructions);
90 FrameScope scope(masm, StackFrame::CONSTRUCT);
101 Label rt_call, allocated;
102 if (FLAG_inline_new) {
103 Label undo_allocation;
104 #ifdef ENABLE_DEBUGGER_SUPPORT
105 ExternalReference debug_step_in_fp =
106 ExternalReference::debug_step_in_fp_address(masm->isolate());
107 __ cmp(Operand::StaticVariable(debug_step_in_fp), Immediate(0));
116 __ JumpIfSmi(
eax, &rt_call);
130 if (count_constructions) {
143 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
156 __ AllocateInNewSpace(
163 Factory* factory = masm->isolate()->factory();
164 __ mov(
ecx, factory->empty_fixed_array());
172 __ mov(
edx, factory->undefined_value());
173 if (count_constructions) {
179 if (FLAG_debug_code) {
182 "Unexpected number of pre-allocated property fields.");
185 __ mov(
edx, factory->one_pointer_filler_map());
213 __ Assert(
positive,
"Property allocation count failed.");
234 __ mov(
eax, factory->fixed_array_map());
244 __ mov(
edx, factory->undefined_value());
271 __ bind(&undo_allocation);
272 __ UndoAllocationInNewSpace(
ebx);
281 __ CallRuntime(Runtime::kNewObject, 1);
314 if (is_api_function) {
317 masm->isolate()->builtins()->HandleApiCallConstruct();
318 ParameterCount expected(0);
319 __ InvokeCode(code, expected, expected, RelocInfo::CODE_TARGET,
322 ParameterCount actual(
eax);
328 if (!is_api_function && !count_constructions) {
329 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
338 Label use_receiver, exit;
341 __ JumpIfSmi(
eax, &use_receiver);
350 __ bind(&use_receiver);
365 __ IncrementCounter(masm->isolate()->counters()->constructed_objects(), 1);
370 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) {
371 Generate_JSConstructStubHelper(masm,
false,
true);
375 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
376 Generate_JSConstructStubHelper(masm,
false,
false);
380 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
381 Generate_JSConstructStubHelper(masm,
true,
false);
385 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
388 __ Set(
esi, Immediate(0));
410 __ Set(
ecx, Immediate(0));
414 __ push(Operand(
edx, 0));
429 ParameterCount actual(
eax);
442 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
443 Generate_JSEntryTrampolineHelper(masm,
false);
447 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
448 Generate_JSEntryTrampolineHelper(masm,
true);
452 void Builtins::Generate_LazyCompile(MacroAssembler* masm) {
462 __ CallRuntime(Runtime::kLazyCompile, 1);
478 void Builtins::Generate_LazyRecompile(MacroAssembler* masm) {
488 __ CallRuntime(Runtime::kLazyRecompile, 1);
504 static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
511 __ CallRuntime(Runtime::kNotifyDeoptimized, 1);
521 Label not_no_registers, not_tos_eax;
526 __ bind(¬_no_registers);
532 __ bind(¬_tos_eax);
533 __ Abort(
"no cases left");
537 void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) {
542 void Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) {
547 void Builtins::Generate_NotifyOSR(MacroAssembler* masm) {
557 __ CallRuntime(Runtime::kNotifyOSR, 0);
564 void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
565 Factory* factory = masm->isolate()->factory();
572 __ push(Immediate(factory->undefined_value()));
580 Label slow, non_function;
583 __ JumpIfSmi(
edi, &non_function);
589 Label shift_arguments;
590 __ Set(
edx, Immediate(0));
591 { Label convert_to_object, use_global_receiver, patch_receiver;
611 __ JumpIfSmi(
ebx, &convert_to_object);
612 __ cmp(
ebx, factory->null_value());
613 __ j(
equal, &use_global_receiver);
614 __ cmp(
ebx, factory->undefined_value());
615 __ j(
equal, &use_global_receiver);
620 __ bind(&convert_to_object);
630 __ Set(
edx, Immediate(0));
638 __ jmp(&patch_receiver);
642 __ bind(&use_global_receiver);
643 const int kGlobalIndex =
650 __ bind(&patch_receiver);
653 __ jmp(&shift_arguments);
658 __ Set(
edx, Immediate(1));
661 __ bind(&non_function);
662 __ Set(
edx, Immediate(2));
673 __ bind(&shift_arguments);
687 { Label
function, non_proxy;
690 __ Set(
ebx, Immediate(0));
691 __ cmp(
edx, Immediate(1));
699 __ GetBuiltinEntry(
edx, Builtins::CALL_FUNCTION_PROXY);
700 __ jmp(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
701 RelocInfo::CODE_TARGET);
705 __ GetBuiltinEntry(
edx, Builtins::CALL_NON_FUNCTION);
706 __ jmp(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
707 RelocInfo::CODE_TARGET);
722 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline());
724 ParameterCount expected(0);
730 void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
737 __ push(Operand(
ebp, kFunctionOffset));
738 __ push(Operand(
ebp, kArgumentsOffset));
745 ExternalReference real_stack_limit =
746 ExternalReference::address_of_real_stack_limit(masm->isolate());
747 __ mov(
edi, Operand::StaticVariable(real_stack_limit));
761 __ push(Operand(
ebp, 4 * kPointerSize));
768 const int kLimitOffset =
770 const int kIndexOffset = kLimitOffset - 1 *
kPointerSize;
772 __ push(Immediate(0));
775 __ mov(
ebx, Operand(
ebp, kReceiverOffset));
779 __ mov(
edi, Operand(
ebp, kFunctionOffset));
788 Label call_to_object, use_global_receiver;
794 Factory* factory = masm->isolate()->factory();
804 __ JumpIfSmi(
ebx, &call_to_object);
805 __ cmp(
ebx, factory->null_value());
806 __ j(
equal, &use_global_receiver);
807 __ cmp(
ebx, factory->undefined_value());
808 __ j(
equal, &use_global_receiver);
813 __ bind(&call_to_object);
817 __ jmp(&push_receiver);
820 __ bind(&use_global_receiver);
821 const int kGlobalOffset =
829 __ bind(&push_receiver);
834 __ mov(
ecx, Operand(
ebp, kIndexOffset));
837 __ mov(
edx, Operand(
ebp, kArgumentsOffset));
840 Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Initialize();
841 __ call(ic, RelocInfo::CODE_TARGET);
851 __ mov(
ecx, Operand(
ebp, kIndexOffset));
853 __ mov(Operand(
ebp, kIndexOffset),
ecx);
856 __ cmp(
ecx, Operand(
ebp, kLimitOffset));
862 ParameterCount actual(
eax);
864 __ mov(
edi, Operand(
ebp, kFunctionOffset));
870 frame_scope.GenerateLeaveFrame();
871 __ ret(3 * kPointerSize);
874 __ bind(&call_proxy);
877 __ Set(
ebx, Immediate(0));
879 __ GetBuiltinEntry(
edx, Builtins::CALL_FUNCTION_PROXY);
880 __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
881 RelocInfo::CODE_TARGET);
885 __ ret(3 * kPointerSize);
893 static void AllocateEmptyJSArray(MacroAssembler* masm,
894 Register array_function,
899 Label* gc_required) {
903 __ LoadInitialArrayMap(array_function, scratch2, scratch1,
false);
908 if (initial_capacity > 0) {
911 __ AllocateInNewSpace(size,
924 Factory* factory = masm->isolate()->factory();
926 factory->empty_fixed_array());
932 if (initial_capacity == 0) {
934 factory->empty_fixed_array());
951 factory->fixed_array_map());
957 static const int kLoopUnfoldLimit = 4;
958 if (initial_capacity <= kLoopUnfoldLimit) {
961 __ mov(scratch3, factory->the_hole_value());
962 for (
int i = 0; i < initial_capacity; i++) {
969 __ mov(scratch2, Immediate(initial_capacity));
976 factory->the_hole_value());
993 static void AllocateJSArray(MacroAssembler* masm,
994 Register array_function,
997 Register elements_array,
998 Register elements_array_end,
1000 bool fill_with_hole,
1001 Label* gc_required) {
1003 ASSERT(!fill_with_hole || array_size.is(
ecx));
1004 ASSERT(!fill_with_hole || !result.is(
eax));
1006 __ LoadInitialArrayMap(array_function, scratch,
1007 elements_array, fill_with_hole);
1028 Factory* factory = masm->isolate()->factory();
1029 __ mov(elements_array, factory->empty_fixed_array());
1048 factory->fixed_array_map());
1056 if (fill_with_hole) {
1057 __ SmiUntag(array_size);
1058 __ lea(
edi, Operand(elements_array,
1060 __ mov(
eax, factory->the_hole_value());
1064 const int kRepStosThreshold = 16;
1065 Label loop, entry, done;
1066 __ cmp(
ecx, kRepStosThreshold);
1073 __ cmp(
edi, elements_array_end);
1094 static void ArrayNativeCode(MacroAssembler* masm,
1095 bool construct_call,
1096 Label* call_generic_code) {
1097 Label argc_one_or_more, argc_two_or_more, prepare_generic_code_call,
1098 empty_array, not_empty_array, finish, cant_transition_map, not_double;
1103 if (construct_call) {
1114 __ bind(&empty_array);
1116 AllocateEmptyJSArray(masm,
1122 &prepare_generic_code_call);
1123 __ IncrementCounter(masm->isolate()->counters()->array_function_native(), 1);
1125 if (construct_call) {
1128 __ ret(kPointerSize);
1132 __ bind(&argc_one_or_more);
1136 __ mov(
ecx, Operand(
esp, (push_count + 1) * kPointerSize));
1146 for (
int i = push_count; i > 0; i--) {
1147 __ mov(
eax, Operand(
esp, i * kPointerSize));
1148 __ mov(Operand(
esp, (i + 1) * kPointerSize),
eax);
1151 __ push(Immediate(0));
1152 __ jmp(&empty_array);
1154 __ bind(¬_empty_array);
1170 AllocateJSArray(masm,
1178 &prepare_generic_code_call);
1179 Counters* counters = masm->isolate()->counters();
1180 __ IncrementCounter(counters->array_function_native(), 1);
1183 if (construct_call) {
1186 __ ret(2 * kPointerSize);
1189 __ bind(&argc_two_or_more);
1198 AllocateJSArray(masm,
1206 &prepare_generic_code_call);
1207 __ IncrementCounter(counters->array_function_native(), 1);
1209 __ mov(
ebx, Operand(
esp, kPointerSize));
1219 int last_arg_offset = (construct_call ? 4 : 3) * kPointerSize;
1220 __ lea(
edi, Operand(
esp, last_arg_offset));
1226 Label has_non_smi_element;
1241 if (FLAG_smi_only_arrays) {
1242 __ JumpIfNotSmi(
eax, &has_non_smi_element);
1245 __ add(
edx, Immediate(kPointerSize));
1258 __ mov(
ecx, Operand(
esp, last_arg_offset - kPointerSize));
1262 last_arg_offset - kPointerSize));
1265 __ bind(&has_non_smi_element);
1268 masm->isolate()->factory()->heap_number_map(),
1271 __ bind(&cant_transition_map);
1274 __ UndoAllocationInNewSpace(
eax);
1275 __ jmp(&prepare_generic_code_call);
1277 __ bind(¬_double);
1281 __ LoadTransitionedArrayMapConditional(
1286 &cant_transition_map);
1292 __ lea(
edi, Operand(
esp, last_arg_offset));
1299 __ add(
edx, Immediate(kPointerSize));
1305 __ bind(&prepare_generic_code_call);
1307 if (construct_call) {
1310 __ jmp(call_generic_code);
1314 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
1320 Label generic_array_code;
1325 if (FLAG_debug_code) {
1330 __ Assert(
not_zero,
"Unexpected initial map for InternalArray function");
1332 __ Assert(
equal,
"Unexpected initial map for InternalArray function");
1337 ArrayNativeCode(masm,
false, &generic_array_code);
1341 __ bind(&generic_array_code);
1342 Handle<Code> array_code =
1343 masm->isolate()->builtins()->InternalArrayCodeGeneric();
1344 __ jmp(array_code, RelocInfo::CODE_TARGET);
1348 void Builtins::Generate_ArrayCode(MacroAssembler* masm) {
1354 Label generic_array_code;
1359 if (FLAG_debug_code) {
1364 __ Assert(
not_zero,
"Unexpected initial map for Array function");
1366 __ Assert(
equal,
"Unexpected initial map for Array function");
1370 ArrayNativeCode(masm,
false, &generic_array_code);
1374 __ bind(&generic_array_code);
1375 Handle<Code> array_code =
1376 masm->isolate()->builtins()->ArrayCodeGeneric();
1377 __ jmp(array_code, RelocInfo::CODE_TARGET);
1381 void Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) {
1388 Label generic_constructor;
1390 if (FLAG_debug_code) {
1398 __ Assert(
not_zero,
"Unexpected initial map for Array function");
1400 __ Assert(
equal,
"Unexpected initial map for Array function");
1404 ArrayNativeCode(masm,
true, &generic_constructor);
1408 __ bind(&generic_constructor);
1409 Handle<Code> generic_construct_stub =
1410 masm->isolate()->builtins()->JSConstructStubGeneric();
1411 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET);
1415 void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
1423 Counters* counters = masm->isolate()->counters();
1424 __ IncrementCounter(counters->string_ctor_calls(), 1);
1426 if (FLAG_debug_code) {
1429 __ Assert(
equal,
"Unexpected String function");
1436 __ j(
zero, &no_arguments);
1444 Label not_cached, argument_is_string;
1453 __ IncrementCounter(counters->string_ctor_cached_number(), 1);
1454 __ bind(&argument_is_string);
1471 __ LoadGlobalFunctionInitialMap(
edi,
ecx);
1472 if (FLAG_debug_code) {
1475 __ Assert(
equal,
"Unexpected string wrapper instance size");
1477 __ Assert(
equal,
"Unexpected unused properties of string wrapper");
1482 Factory* factory = masm->isolate()->factory();
1483 __ Set(
ecx, Immediate(factory->empty_fixed_array()));
1498 Label convert_argument;
1499 __ bind(¬_cached);
1501 __ JumpIfSmi(
eax, &convert_argument);
1505 __ IncrementCounter(counters->string_ctor_string_value(), 1);
1506 __ jmp(&argument_is_string);
1509 __ bind(&convert_argument);
1510 __ IncrementCounter(counters->string_ctor_conversions(), 1);
1519 __ jmp(&argument_is_string);
1523 __ bind(&no_arguments);
1524 __ Set(
ebx, Immediate(factory->empty_string()));
1526 __ lea(
esp, Operand(
esp, kPointerSize));
1528 __ jmp(&argument_is_string);
1532 __ bind(&gc_required);
1533 __ IncrementCounter(counters->string_ctor_gc_required(), 1);
1537 __ CallRuntime(Runtime::kNewStringWrapper, 1);
1543 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
1562 static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
1577 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
1585 Label invoke, dont_adapt_arguments;
1586 __ IncrementCounter(masm->isolate()->counters()->arguments_adaptors(), 1);
1588 Label enough, too_few;
1592 __ j(
equal, &dont_adapt_arguments);
1596 EnterArgumentsAdaptorFrame(masm);
1606 __ push(Operand(
eax, 0));
1607 __ sub(
eax, Immediate(kPointerSize));
1615 EnterArgumentsAdaptorFrame(masm);
1624 __ sub(
eax, Immediate(1));
1629 __ push(Operand(
edi, 0));
1630 __ sub(
edi, Immediate(kPointerSize));
1638 __ push(Immediate(masm->isolate()->factory()->undefined_value()));
1650 masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
1653 LeaveArgumentsAdaptorFrame(masm);
1659 __ bind(&dont_adapt_arguments);
1664 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
1665 CpuFeatures::TryForceFeatureScope scope(
SSE2);
1667 __ Abort(
"Unreachable code: Cannot optimize without SSE2 support.");
1675 if (FLAG_debug_code) {
1677 __ Assert(
equal,
"test eax instruction not found after loop stack check");
1696 __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1);
1709 __ bind(&stack_check);
1711 ExternalReference stack_limit =
1712 ExternalReference::address_of_stack_limit(masm->isolate());
1713 __ cmp(
esp, Operand::StaticVariable(stack_limit));
1715 StackCheckStub stub;
1716 __ TailCallStub(&stub);
1717 if (FLAG_debug_code) {
1718 __ Abort(
"Unreachable code: returned from tail call.");
1731 generator.Generate();
1739 #endif // V8_TARGET_ARCH_IA32
static const int kLengthOffset
const intptr_t kSmiTagMask
static const int kCodeOffset
static const int kCodeEntryOffset
static const int kPrototypeOrInitialMapOffset
static const int kAllowOSRAtLoopNestingLevelOffset
static Smi * FromInt(int value)
const intptr_t kIntptrSignBit
static const int kGlobalReceiverOffset
static const int kConstructionCountOffset
static const int kNativeByteOffset
static bool IsSupported(CpuFeature f)
static const int kStrictModeBitWithinByte
static const int kCallerSPOffset
#define ASSERT(condition)
const int kPointerSizeLog2
static const int kInstanceSizeOffset
static const int kUnusedPropertyFieldsOffset
static const int kGlobalContextOffset
static const byte kTestAlByte
static const int kContextOffset
STATIC_ASSERT((FixedDoubleArray::kHeaderSize &kDoubleAlignmentMask)==0)
static const int kDontAdaptArgumentsSentinel
Operand FieldOperand(Register object, int offset)
static const int kExpressionsOffset
static const int kPropertiesOffset
static const int kInObjectPropertiesOffset
static const int kElementsOffset
static const int kNativeBitWithinByte
static const int kArgcOffset
static const int kFunctionArgOffset
static const int kLengthOffset
static int SizeFor(int length)
static const int kHeaderSize
static const int kMapOffset
static const int kLengthOffset
static const int kContextOffset
static const int kFunctionOffset
static const int kReceiverArgOffset
static const int kFormalParameterCountOffset
static const int kStrictModeByteOffset
static const int kHeaderSize
Condition NegateCondition(Condition cond)
static const int kArgvOffset
static const int kHeaderSize
static void GenerateLookupNumberStringCache(MacroAssembler *masm, Register object, Register result, Register scratch1, Register scratch2, Register scratch3, bool object_is_smi, Label *not_found)
static const int kPreallocatedArrayElements
static const int kValueOffset
static const int kSharedFunctionInfoOffset
static const int kInitialMaxFastElementArray
static const int kPreAllocatedPropertyFieldsOffset