30 #if defined(V8_TARGET_ARCH_IA32)
43 #define __ ACCESS_MASM(masm)
47 Label check_heap_number, call_builtin;
48 __ JumpIfNotSmi(
eax, &check_heap_number, Label::kNear);
51 __ bind(&check_heap_number);
53 Factory* factory = masm->isolate()->factory();
54 __ cmp(
ebx, Immediate(factory->heap_number_map()));
58 __ bind(&call_builtin);
88 Factory* factory = masm->isolate()->factory();
89 __ mov(
ebx, Immediate(factory->empty_fixed_array()));
93 Immediate(factory->the_hole_value()));
98 Immediate(factory->undefined_value()));
115 __ push(Immediate(factory->false_value()));
117 __ TailCallRuntime(Runtime::kNewClosure, 3, 1);
132 Factory* factory = masm->isolate()->factory();
134 factory->function_context_map());
139 __ Set(
ebx, Immediate(0));
149 __ mov(
ebx, factory->undefined_value());
150 for (
int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
160 __ TailCallRuntime(Runtime::kNewFunctionContext, 1, 1);
183 Factory* factory = masm->isolate()->factory();
185 factory->block_context_map());
193 Label after_sentinel;
194 __ JumpIfNotSmi(
ecx, &after_sentinel, Label::kNear);
195 if (FLAG_debug_code) {
196 const char* message =
"Expected 0 as a Smi sentinel";
203 __ bind(&after_sentinel);
217 factory->the_hole_value());
219 __ mov(
ebx, factory->the_hole_value());
220 for (
int i = 0; i < slots_; i++) {
231 __ TailCallRuntime(Runtime::kPushBlockContext, 2, 1);
235 static void GenerateFastCloneShallowArrayCommon(
236 MacroAssembler* masm,
246 int elements_size = 0;
250 : FixedArray::SizeFor(length);
270 __ lea(
edx, Operand(
eax, JSArray::kSize));
286 while (i < elements_size) {
291 ASSERT(i == elements_size);
313 Factory* factory = masm->isolate()->factory();
314 __ cmp(
ecx, factory->undefined_value());
321 Label double_elements, check_fast_elements;
323 __ CheckMap(
ebx, factory->fixed_cow_array_map(),
325 GenerateFastCloneShallowArrayCommon(masm, 0,
329 __ bind(&check_fast_elements);
330 __ CheckMap(
ebx, factory->fixed_array_map(),
332 GenerateFastCloneShallowArrayCommon(masm, length_,
336 __ bind(&double_elements);
341 if (FLAG_debug_code) {
343 Handle<Map> expected_map;
345 message =
"Expected (writable) fixed array";
346 expected_map = factory->fixed_array_map();
348 message =
"Expected (writable) fixed double array";
349 expected_map = factory->fixed_double_array_map();
352 message =
"Expected copy-on-write fixed array";
353 expected_map = factory->fixed_cow_array_map();
362 GenerateFastCloneShallowArrayCommon(masm, length_, mode, &slow_case);
367 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1);
389 Factory* factory = masm->isolate()->factory();
390 __ cmp(
ecx, factory->undefined_value());
410 __ ret(4 * kPointerSize);
413 __ TailCallRuntime(Runtime::kCreateObjectLiteralShallow, 4, 1);
423 Factory* factory = masm->isolate()->factory();
424 const Register argument =
eax;
425 const Register map =
edx;
428 __ mov(argument, Operand(
esp, 1 * kPointerSize));
432 CheckOddball(masm,
UNDEFINED, Heap::kUndefinedValueRootIndex,
false);
435 CheckOddball(masm,
BOOLEAN, Heap::kFalseValueRootIndex,
false);
436 CheckOddball(masm,
BOOLEAN, Heap::kTrueValueRootIndex,
true);
439 CheckOddball(masm,
NULL_TYPE, Heap::kNullValueRootIndex,
false);
444 __ JumpIfNotSmi(argument, ¬_smi, Label::kNear);
446 if (!tos_.
is(argument)) {
447 __ mov(tos_, argument);
449 __ ret(1 * kPointerSize);
453 __ JumpIfSmi(argument, &patch, Label::kNear);
463 Label not_undetectable;
464 __ j(
zero, ¬_undetectable, Label::kNear);
465 __ Set(tos_, Immediate(0));
466 __ ret(1 * kPointerSize);
467 __ bind(¬_undetectable);
475 __ j(
below, ¬_js_object, Label::kNear);
477 if (!tos_.
is(argument)) {
478 __ Set(tos_, Immediate(1));
480 __ ret(1 * kPointerSize);
481 __ bind(¬_js_object);
490 __ ret(1 * kPointerSize);
491 __ bind(¬_string);
496 Label not_heap_number, false_result;
497 __ cmp(map, factory->heap_number_map());
502 __ j(
zero, &false_result, Label::kNear);
504 if (!tos_.
is(argument)) {
505 __ Set(tos_, Immediate(1));
507 __ ret(1 * kPointerSize);
508 __ bind(&false_result);
509 __ Set(tos_, Immediate(0));
510 __ ret(1 * kPointerSize);
511 __ bind(¬_heap_number);
515 GenerateTypeTransition(masm);
525 CpuFeatures::Scope scope(
SSE2);
532 const int argument_count = 1;
534 AllowExternalCallThatCantCauseGC scope(masm);
535 __ PrepareCallCFunction(argument_count,
ecx);
536 __ mov(Operand(
esp, 0 * kPointerSize),
537 Immediate(ExternalReference::isolate_address()));
539 ExternalReference::store_buffer_overflow_function(masm->isolate()),
542 CpuFeatures::Scope scope(
SSE2);
554 void ToBooleanStub::CheckOddball(MacroAssembler* masm,
558 const Register argument =
eax;
561 Label different_value;
562 __ CompareRoot(argument, value);
566 __ Set(tos_, Immediate(0));
567 }
else if (!tos_.
is(argument)) {
570 __ Set(tos_, Immediate(1));
572 __ ret(1 * kPointerSize);
573 __ bind(&different_value);
578 void ToBooleanStub::GenerateTypeTransition(MacroAssembler* masm) {
585 __ TailCallExternalReference(
586 ExternalReference(IC_Utility(IC::kToBoolean_Patch), masm->isolate()),
592 class FloatingPointHelper :
public AllStatic {
603 static void LoadFloatOperand(MacroAssembler* masm, Register number);
609 static void LoadFloatOperands(MacroAssembler* masm,
611 ArgLocation arg_location = ARGS_ON_STACK);
615 static void LoadFloatSmis(MacroAssembler* masm, Register scratch);
620 static void CheckFloatOperands(MacroAssembler* masm,
626 static void CheckFloatOperandsAreInt32(MacroAssembler* masm,
631 static void LoadUnknownsAsIntegers(MacroAssembler* masm,
633 Label* operand_conversion_failure);
639 static void CheckLoadedIntegersWereInt32(MacroAssembler* masm,
646 static void LoadSSE2Operands(MacroAssembler* masm);
652 static void LoadSSE2Operands(MacroAssembler* masm, Label* not_numbers);
656 static void LoadSSE2Smis(MacroAssembler* masm, Register scratch);
660 static void CheckSSE2OperandsAreInt32(MacroAssembler* masm,
670 static void IntegerConvert(MacroAssembler* masm,
673 Label* conversion_failure) {
675 Label done, right_exponent, normal_exponent;
676 Register scratch =
ebx;
677 Register scratch2 =
edi;
681 __ mov(scratch2, scratch);
684 CpuFeatures::Scope scope(
SSE3);
686 static const uint32_t kTooBigExponent =
688 __ cmp(scratch2, Immediate(kTooBigExponent));
693 __ sub(
esp, Immediate(
sizeof(uint64_t)));
695 __ fisttp_d(Operand(
esp, 0));
697 __ add(
esp, Immediate(
sizeof(uint64_t)));
706 const uint32_t non_smi_exponent =
708 __ cmp(scratch2, Immediate(non_smi_exponent));
711 __ j(
equal, &right_exponent, Label::kNear);
714 __ j(
less, &normal_exponent, Label::kNear);
719 const uint32_t big_non_smi_exponent =
721 __ cmp(scratch2, Immediate(big_non_smi_exponent));
725 __ mov(scratch2, scratch);
734 __ shl(scratch2, big_shift_distance);
739 __ shr(
ecx, 32 - big_shift_distance);
740 __ or_(
ecx, scratch2);
742 __ test(scratch, scratch);
745 __ jmp(&done, Label::kNear);
748 __ bind(&normal_exponent);
754 const uint32_t zero_exponent =
756 __ sub(scratch2, Immediate(zero_exponent));
758 __ j(
less, &done, Label::kNear);
762 __ mov(
ecx, Immediate(30));
763 __ sub(
ecx, scratch2);
765 __ bind(&right_exponent);
775 __ shl(scratch, shift_distance);
782 __ shr(scratch2, 32 - shift_distance);
783 __ or_(scratch2, scratch);
792 __ mov(
ecx, scratch2);
793 __ jmp(&done, Label::kNear);
795 __ sub(
ecx, scratch2);
801 void UnaryOpStub::PrintName(StringStream* stream) {
803 const char* overwrite_name =
NULL;
808 stream->Add(
"UnaryOpStub_%s_%s_%s",
816 void UnaryOpStub::Generate(MacroAssembler* masm) {
817 switch (operand_type_) {
819 GenerateTypeTransition(masm);
822 GenerateSmiStub(masm);
825 GenerateHeapNumberStub(masm);
828 GenerateGenericStub(masm);
834 void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
846 __ TailCallExternalReference(
847 ExternalReference(IC_Utility(IC::kUnaryOp_Patch), masm->isolate()), 4, 1);
852 void UnaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
855 GenerateSmiStubSub(masm);
858 GenerateSmiStubBitNot(masm);
866 void UnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) {
867 Label non_smi, undo, slow;
868 GenerateSmiCodeSub(masm, &non_smi, &undo, &slow,
869 Label::kNear, Label::kNear, Label::kNear);
871 GenerateSmiCodeUndo(masm);
874 GenerateTypeTransition(masm);
878 void UnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) {
880 GenerateSmiCodeBitNot(masm, &non_smi);
882 GenerateTypeTransition(masm);
886 void UnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm,
890 Label::Distance non_smi_near,
891 Label::Distance undo_near,
892 Label::Distance slow_near) {
894 __ JumpIfNotSmi(
eax, non_smi, non_smi_near);
898 __ j(
zero, slow, slow_near);
902 __ Set(
eax, Immediate(0));
909 void UnaryOpStub::GenerateSmiCodeBitNot(
910 MacroAssembler* masm,
912 Label::Distance non_smi_near) {
914 __ JumpIfNotSmi(
eax, non_smi, non_smi_near);
923 void UnaryOpStub::GenerateSmiCodeUndo(MacroAssembler* masm) {
929 void UnaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
932 GenerateHeapNumberStubSub(masm);
935 GenerateHeapNumberStubBitNot(masm);
943 void UnaryOpStub::GenerateHeapNumberStubSub(MacroAssembler* masm) {
944 Label non_smi, undo, slow, call_builtin;
945 GenerateSmiCodeSub(masm, &non_smi, &undo, &call_builtin, Label::kNear);
947 GenerateHeapNumberCodeSub(masm, &slow);
949 GenerateSmiCodeUndo(masm);
951 GenerateTypeTransition(masm);
952 __ bind(&call_builtin);
953 GenerateGenericCodeFallback(masm);
957 void UnaryOpStub::GenerateHeapNumberStubBitNot(
958 MacroAssembler* masm) {
960 GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
962 GenerateHeapNumberCodeBitNot(masm, &slow);
964 GenerateTypeTransition(masm);
968 void UnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm,
971 __ cmp(
edx, masm->isolate()->factory()->heap_number_map());
981 Label slow_allocate_heapnumber, heapnumber_allocated;
982 __ AllocateHeapNumber(
eax,
ebx,
ecx, &slow_allocate_heapnumber);
983 __ jmp(&heapnumber_allocated, Label::kNear);
985 __ bind(&slow_allocate_heapnumber);
989 __ CallRuntime(Runtime::kNumberAlloc, 0);
993 __ bind(&heapnumber_allocated);
1005 void UnaryOpStub::GenerateHeapNumberCodeBitNot(MacroAssembler* masm,
1008 __ cmp(
edx, masm->isolate()->factory()->heap_number_map());
1017 __ cmp(
ecx, 0xc0000000);
1018 __ j(
sign, &try_float, Label::kNear);
1026 __ bind(&try_float);
1028 Label slow_allocate_heapnumber, heapnumber_allocated;
1030 __ AllocateHeapNumber(
eax,
edx,
edi, &slow_allocate_heapnumber);
1031 __ jmp(&heapnumber_allocated);
1033 __ bind(&slow_allocate_heapnumber);
1040 __ CallRuntime(Runtime::kNumberAlloc, 0);
1049 __ bind(&heapnumber_allocated);
1052 CpuFeatures::Scope use_sse2(
SSE2);
1057 __ fild_s(Operand(
esp, 0));
1066 void UnaryOpStub::GenerateGenericStub(MacroAssembler* masm) {
1069 GenerateGenericStubSub(masm);
1071 case Token::BIT_NOT:
1072 GenerateGenericStubBitNot(masm);
1080 void UnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) {
1081 Label non_smi, undo, slow;
1082 GenerateSmiCodeSub(masm, &non_smi, &undo, &slow, Label::kNear);
1084 GenerateHeapNumberCodeSub(masm, &slow);
1086 GenerateSmiCodeUndo(masm);
1088 GenerateGenericCodeFallback(masm);
1092 void UnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) {
1093 Label non_smi, slow;
1094 GenerateSmiCodeBitNot(masm, &non_smi, Label::kNear);
1096 GenerateHeapNumberCodeBitNot(masm, &slow);
1098 GenerateGenericCodeFallback(masm);
1102 void UnaryOpStub::GenerateGenericCodeFallback(MacroAssembler* masm) {
1111 case Token::BIT_NOT:
1120 void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
1135 __ TailCallExternalReference(
1136 ExternalReference(IC_Utility(IC::kBinaryOp_Patch),
1145 void BinaryOpStub::GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm) {
1158 __ TailCallExternalReference(
1159 ExternalReference(IC_Utility(IC::kBinaryOp_Patch),
1166 void BinaryOpStub::Generate(MacroAssembler* masm) {
1169 AllowStubCallsScope allow_stub_calls(masm,
true);
1171 switch (operands_type_) {
1173 GenerateTypeTransition(masm);
1176 GenerateSmiStub(masm);
1179 GenerateInt32Stub(masm);
1182 GenerateHeapNumberStub(masm);
1185 GenerateOddballStub(masm);
1188 GenerateBothStringStub(masm);
1191 GenerateStringStub(masm);
1194 GenerateGeneric(masm);
1202 void BinaryOpStub::PrintName(StringStream* stream) {
1204 const char* overwrite_name;
1209 default: overwrite_name =
"UnknownOverwrite";
break;
1211 stream->Add(
"BinaryOpStub_%s_%s_%s",
1218 void BinaryOpStub::GenerateSmiCode(
1219 MacroAssembler* masm,
1221 SmiCodeGenerateHeapNumberResults allow_heapnumber_results) {
1224 Comment load_comment(masm,
"-- Load arguments");
1225 Register left =
edx;
1226 Register right =
eax;
1227 if (op_ ==
Token::DIV || op_ == Token::MOD) {
1236 Comment smi_check_comment(masm,
"-- Smi check arguments");
1238 Register combined =
ecx;
1239 ASSERT(!left.is(combined) && !right.is(combined));
1246 __ or_(right, left);
1250 case Token::BIT_XOR:
1251 case Token::BIT_AND:
1257 __ mov(combined, right);
1258 __ or_(combined, left);
1268 __ or_(right, left);
1278 __ JumpIfNotSmi(combined, ¬_smis);
1282 Comment perform_smi(masm,
"-- Perform smi operation");
1283 Label use_fp_on_smis;
1289 case Token::BIT_XOR:
1291 __ xor_(right, left);
1294 case Token::BIT_AND:
1296 __ and_(right, left);
1306 __ cmp(left, 0xc0000000);
1307 __ j(
sign, &use_fp_on_smis);
1336 __ test(left, Immediate(0xc0000000));
1345 __ add(right, left);
1350 __ sub(left, right);
1364 __ imul(right, left);
1367 __ NegativeZeroTest(right, combined, &use_fp_on_smis);
1375 __ test(right, right);
1376 __ j(
zero, &use_fp_on_smis);
1386 __ cmp(
eax, 0x40000000);
1389 __ NegativeZeroTest(
eax, combined, &use_fp_on_smis);
1399 __ test(right, right);
1408 __ NegativeZeroTest(
edx, combined, slow);
1427 case Token::BIT_AND:
1428 case Token::BIT_XOR:
1432 __ ret(2 * kPointerSize);
1441 if (allow_heapnumber_results == NO_HEAPNUMBER_RESULTS) {
1442 __ bind(&use_fp_on_smis);
1450 __ sub(right, left);
1454 __ add(left, right);
1471 ASSERT(allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS);
1475 Comment perform_float(masm,
"-- Perform float operation on smis");
1476 __ bind(&use_fp_on_smis);
1483 if (op_ == Token::SHR) {
1484 __ mov(Operand(
esp, 1 * kPointerSize), left);
1485 __ mov(Operand(
esp, 2 * kPointerSize), Immediate(0));
1486 __ fild_d(Operand(
esp, 1 * kPointerSize));
1491 CpuFeatures::Scope use_sse2(
SSE2);
1495 __ mov(Operand(
esp, 1 * kPointerSize), left);
1496 __ fild_s(Operand(
esp, 1 * kPointerSize));
1500 __ ret(2 * kPointerSize);
1508 Comment perform_float(masm,
"-- Perform float operation on smis");
1509 __ bind(&use_fp_on_smis);
1514 __ sub(right, left);
1518 __ add(left, right);
1535 CpuFeatures::Scope use_sse2(
SSE2);
1536 FloatingPointHelper::LoadSSE2Smis(masm,
ebx);
1546 FloatingPointHelper::LoadFloatSmis(masm,
ebx);
1568 Comment done_comment(masm,
"-- Enter non-smi code");
1593 void BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
1604 case Token::BIT_AND:
1605 case Token::BIT_XOR:
1609 GenerateRegisterArgsPush(masm);
1617 GenerateSmiCode(masm, &call_runtime, NO_HEAPNUMBER_RESULTS);
1619 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS);
1621 __ bind(&call_runtime);
1627 GenerateTypeTransition(masm);
1631 case Token::BIT_AND:
1632 case Token::BIT_XOR:
1636 GenerateTypeTransitionWithSavedArgs(masm);
1644 void BinaryOpStub::GenerateStringStub(MacroAssembler* masm) {
1649 GenerateAddStrings(masm);
1650 GenerateTypeTransition(masm);
1654 void BinaryOpStub::GenerateBothStringStub(MacroAssembler* masm) {
1662 Register left =
edx;
1663 Register right =
eax;
1666 __ JumpIfSmi(left, &call_runtime, Label::kNear);
1671 __ JumpIfSmi(right, &call_runtime, Label::kNear);
1676 GenerateRegisterArgsPush(masm);
1677 __ TailCallStub(&string_add_stub);
1679 __ bind(&call_runtime);
1680 GenerateTypeTransition(masm);
1689 void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
1703 CpuFeatures::Scope use_sse2(
SSE2);
1704 FloatingPointHelper::LoadSSE2Operands(masm, ¬_floats);
1705 FloatingPointHelper::CheckSSE2OperandsAreInt32(masm, ¬_int32,
ecx);
1706 if (op_ == Token::MOD) {
1707 GenerateRegisterArgsPush(masm);
1725 GenerateHeapResultAllocation(masm, &call_runtime);
1730 FloatingPointHelper::CheckFloatOperands(masm, ¬_floats,
ebx);
1731 FloatingPointHelper::LoadFloatOperands(
1734 FloatingPointHelper::ARGS_IN_REGISTERS);
1735 FloatingPointHelper::CheckFloatOperandsAreInt32(masm, ¬_int32);
1736 if (op_ == Token::MOD) {
1740 GenerateRegisterArgsPush(masm);
1750 Label after_alloc_failure;
1751 GenerateHeapResultAllocation(masm, &after_alloc_failure);
1754 __ bind(&after_alloc_failure);
1756 __ jmp(&call_runtime);
1760 __ bind(¬_floats);
1761 __ bind(¬_int32);
1762 GenerateTypeTransition(masm);
1767 case Token::BIT_AND:
1768 case Token::BIT_XOR:
1772 GenerateRegisterArgsPush(masm);
1775 Label non_smi_result;
1776 FloatingPointHelper::LoadUnknownsAsIntegers(masm,
1779 FloatingPointHelper::CheckLoadedIntegersWereInt32(masm, use_sse3_,
1782 case Token::BIT_OR:
__ or_(
eax,
ecx);
break;
1783 case Token::BIT_AND:
__ and_(
eax,
ecx);
break;
1784 case Token::BIT_XOR:
__ xor_(
eax,
ecx);
break;
1785 case Token::SAR:
__ sar_cl(
eax);
break;
1786 case Token::SHL:
__ shl_cl(
eax);
break;
1787 case Token::SHR:
__ shr_cl(
eax);
break;
1790 if (op_ == Token::SHR) {
1792 __ test(
eax, Immediate(0xc0000000));
1796 __ cmp(
eax, 0xc0000000);
1797 __ j(
negative, &non_smi_result, Label::kNear);
1801 __ ret(2 * kPointerSize);
1805 if (op_ != Token::SHR) {
1806 __ bind(&non_smi_result);
1809 Label skip_allocation;
1816 1 * kPointerSize : 2 * kPointerSize));
1817 __ JumpIfNotSmi(
eax, &skip_allocation, Label::kNear);
1820 __ AllocateHeapNumber(
eax,
ecx,
edx, &call_runtime);
1821 __ bind(&skip_allocation);
1827 CpuFeatures::Scope use_sse2(
SSE2);
1831 __ mov(Operand(
esp, 1 * kPointerSize),
ebx);
1832 __ fild_s(Operand(
esp, 1 * kPointerSize));
1835 __ ret(2 * kPointerSize);
1838 __ bind(¬_floats);
1839 __ bind(¬_int32);
1840 GenerateTypeTransitionWithSavedArgs(masm);
1848 __ bind(&call_runtime);
1852 GenerateRegisterArgsPush(masm);
1856 GenerateRegisterArgsPush(masm);
1860 GenerateRegisterArgsPush(masm);
1864 GenerateRegisterArgsPush(masm);
1872 case Token::BIT_AND:
1875 case Token::BIT_XOR:
1893 void BinaryOpStub::GenerateOddballStub(MacroAssembler* masm) {
1897 GenerateAddStrings(masm);
1900 Factory* factory = masm->isolate()->factory();
1904 __ cmp(
edx, factory->undefined_value());
1909 __ mov(
edx, Immediate(factory->nan_value()));
1911 __ jmp(&done, Label::kNear);
1913 __ cmp(
eax, factory->undefined_value());
1918 __ mov(
eax, Immediate(factory->nan_value()));
1922 GenerateHeapNumberStub(masm);
1926 void BinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
1937 CpuFeatures::Scope use_sse2(
SSE2);
1938 FloatingPointHelper::LoadSSE2Operands(masm, ¬_floats);
1947 GenerateHeapResultAllocation(masm, &call_runtime);
1951 FloatingPointHelper::CheckFloatOperands(masm, ¬_floats,
ebx);
1952 FloatingPointHelper::LoadFloatOperands(
1955 FloatingPointHelper::ARGS_IN_REGISTERS);
1963 Label after_alloc_failure;
1964 GenerateHeapResultAllocation(masm, &after_alloc_failure);
1967 __ bind(&after_alloc_failure);
1969 __ jmp(&call_runtime);
1972 __ bind(¬_floats);
1973 GenerateTypeTransition(masm);
1982 case Token::BIT_AND:
1983 case Token::BIT_XOR:
1987 GenerateRegisterArgsPush(masm);
1989 Label non_smi_result;
1990 FloatingPointHelper::LoadUnknownsAsIntegers(masm,
1994 case Token::BIT_OR:
__ or_(
eax,
ecx);
break;
1995 case Token::BIT_AND:
__ and_(
eax,
ecx);
break;
1996 case Token::BIT_XOR:
__ xor_(
eax,
ecx);
break;
1997 case Token::SAR:
__ sar_cl(
eax);
break;
1998 case Token::SHL:
__ shl_cl(
eax);
break;
1999 case Token::SHR:
__ shr_cl(
eax);
break;
2002 if (op_ == Token::SHR) {
2004 __ test(
eax, Immediate(0xc0000000));
2008 __ cmp(
eax, 0xc0000000);
2009 __ j(
negative, &non_smi_result, Label::kNear);
2013 __ ret(2 * kPointerSize);
2017 if (op_ != Token::SHR) {
2018 __ bind(&non_smi_result);
2021 Label skip_allocation;
2028 1 * kPointerSize : 2 * kPointerSize));
2029 __ JumpIfNotSmi(
eax, &skip_allocation, Label::kNear);
2032 __ AllocateHeapNumber(
eax,
ecx,
edx, &call_runtime);
2033 __ bind(&skip_allocation);
2039 CpuFeatures::Scope use_sse2(
SSE2);
2043 __ mov(Operand(
esp, 1 * kPointerSize),
ebx);
2044 __ fild_s(Operand(
esp, 1 * kPointerSize));
2047 __ ret(2 * kPointerSize);
2050 __ bind(¬_floats);
2051 GenerateTypeTransitionWithSavedArgs(masm);
2059 __ bind(&call_runtime);
2063 GenerateRegisterArgsPush(masm);
2067 GenerateRegisterArgsPush(masm);
2071 GenerateRegisterArgsPush(masm);
2075 GenerateRegisterArgsPush(masm);
2079 GenerateRegisterArgsPush(masm);
2085 case Token::BIT_AND:
2088 case Token::BIT_XOR:
2106 void BinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
2109 Counters* counters = masm->isolate()->counters();
2110 __ IncrementCounter(counters->generic_binary_stub_calls(), 1);
2120 case Token::BIT_AND:
2121 case Token::BIT_XOR:
2125 GenerateRegisterArgsPush(masm);
2131 GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS);
2141 CpuFeatures::Scope use_sse2(
SSE2);
2142 FloatingPointHelper::LoadSSE2Operands(masm, ¬_floats);
2151 GenerateHeapResultAllocation(masm, &call_runtime);
2155 FloatingPointHelper::CheckFloatOperands(masm, ¬_floats,
ebx);
2156 FloatingPointHelper::LoadFloatOperands(
2159 FloatingPointHelper::ARGS_IN_REGISTERS);
2167 Label after_alloc_failure;
2168 GenerateHeapResultAllocation(masm, &after_alloc_failure);
2171 __ bind(&after_alloc_failure);
2173 __ jmp(&call_runtime);
2175 __ bind(¬_floats);
2183 case Token::BIT_AND:
2184 case Token::BIT_XOR:
2188 Label non_smi_result;
2189 FloatingPointHelper::LoadUnknownsAsIntegers(masm,
2193 case Token::BIT_OR:
__ or_(
eax,
ecx);
break;
2194 case Token::BIT_AND:
__ and_(
eax,
ecx);
break;
2195 case Token::BIT_XOR:
__ xor_(
eax,
ecx);
break;
2196 case Token::SAR:
__ sar_cl(
eax);
break;
2197 case Token::SHL:
__ shl_cl(
eax);
break;
2198 case Token::SHR:
__ shr_cl(
eax);
break;
2201 if (op_ == Token::SHR) {
2203 __ test(
eax, Immediate(0xc0000000));
2207 __ cmp(
eax, 0xc0000000);
2208 __ j(
negative, &non_smi_result, Label::kNear);
2212 __ ret(2 * kPointerSize);
2216 if (op_ != Token::SHR) {
2217 __ bind(&non_smi_result);
2220 Label skip_allocation;
2227 1 * kPointerSize : 2 * kPointerSize));
2228 __ JumpIfNotSmi(
eax, &skip_allocation, Label::kNear);
2231 __ AllocateHeapNumber(
eax,
ecx,
edx, &call_runtime);
2232 __ bind(&skip_allocation);
2238 CpuFeatures::Scope use_sse2(
SSE2);
2242 __ mov(Operand(
esp, 1 * kPointerSize),
ebx);
2243 __ fild_s(Operand(
esp, 1 * kPointerSize));
2246 __ ret(2 * kPointerSize);
2255 __ bind(&call_runtime);
2258 GenerateAddStrings(masm);
2259 GenerateRegisterArgsPush(masm);
2264 GenerateRegisterArgsPush(masm);
2268 GenerateRegisterArgsPush(masm);
2272 GenerateRegisterArgsPush(masm);
2281 case Token::BIT_AND:
2284 case Token::BIT_XOR:
2302 void BinaryOpStub::GenerateAddStrings(MacroAssembler* masm) {
2304 Label left_not_string, call_runtime;
2307 Register left =
edx;
2308 Register right =
eax;
2311 __ JumpIfSmi(left, &left_not_string, Label::kNear);
2316 GenerateRegisterArgsPush(masm);
2317 __ TailCallStub(&string_add_left_stub);
2320 __ bind(&left_not_string);
2321 __ JumpIfSmi(right, &call_runtime, Label::kNear);
2326 GenerateRegisterArgsPush(masm);
2327 __ TailCallStub(&string_add_right_stub);
2330 __ bind(&call_runtime);
2334 void BinaryOpStub::GenerateHeapResultAllocation(
2335 MacroAssembler* masm,
2336 Label* alloc_failure) {
2337 Label skip_allocation;
2343 __ JumpIfNotSmi(
edx, &skip_allocation, Label::kNear);
2350 __ bind(&skip_allocation);
2358 __ JumpIfNotSmi(
eax, &skip_allocation, Label::kNear);
2367 __ bind(&skip_allocation);
2374 void BinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
2397 Label runtime_call_clear_stack;
2399 const bool tagged = (argument_type_ ==
TAGGED);
2402 Label input_not_smi;
2404 __ mov(
eax, Operand(
esp, kPointerSize));
2405 __ JumpIfNotSmi(
eax, &input_not_smi, Label::kNear);
2410 __ sub(
esp, Immediate(2 * kPointerSize));
2412 __ fild_s(Operand(
esp, 0));
2413 __ fst_d(Operand(
esp, 0));
2416 __ jmp(&loaded, Label::kNear);
2417 __ bind(&input_not_smi);
2420 Factory* factory = masm->isolate()->factory();
2421 __ cmp(
ebx, Immediate(factory->heap_number_map()));
2432 CpuFeatures::Scope sse4_scope(
SSE4_1);
2456 Immediate(TranscendentalCache::SubCache::kCacheSize - 1));
2462 ExternalReference cache_array =
2463 ExternalReference::transcendental_cache_array_address(masm->isolate());
2464 __ mov(
eax, Immediate(cache_array));
2465 int cache_array_index =
2466 type_ *
sizeof(masm->isolate()->transcendental_cache()->caches_[0]);
2467 __ mov(
eax, Operand(
eax, cache_array_index));
2471 __ j(
zero, &runtime_call_clear_stack);
2474 { TranscendentalCache::SubCache::Element test_elem[2];
2475 char* elem_start =
reinterpret_cast<char*
>(&test_elem[0]);
2476 char* elem2_start =
reinterpret_cast<char*
>(&test_elem[1]);
2477 char* elem_in0 =
reinterpret_cast<char*
>(&(test_elem[0].in[0]));
2478 char* elem_in1 =
reinterpret_cast<char*
>(&(test_elem[0].in[1]));
2479 char* elem_out =
reinterpret_cast<char*
>(&(test_elem[0].output));
2480 CHECK_EQ(12, elem2_start - elem_start);
2481 CHECK_EQ(0, elem_in0 - elem_start);
2496 Counters* counters = masm->isolate()->counters();
2497 __ IncrementCounter(counters->transcendental_cache_hit(), 1);
2501 __ ret(kPointerSize);
2507 __ bind(&cache_miss);
2508 __ IncrementCounter(counters->transcendental_cache_miss(), 1);
2513 __ AllocateHeapNumber(
eax,
edi,
no_reg, &runtime_call_clear_stack);
2518 __ fld_d(Operand(
esp, 0));
2527 __ ret(kPointerSize);
2533 __ bind(&skip_cache);
2536 __ fld_d(Operand(
esp, 0));
2538 __ fstp_d(Operand(
esp, 0));
2547 __ CallRuntimeSaveDoubles(Runtime::kAllocateInNewSpace);
2554 __ bind(&runtime_call_clear_stack);
2556 __ bind(&runtime_call);
2557 ExternalReference runtime =
2558 ExternalReference(RuntimeFunction(), masm->isolate());
2559 __ TailCallExternalReference(runtime, 1, 1);
2561 __ bind(&runtime_call_clear_stack);
2562 __ bind(&runtime_call);
2568 __ CallRuntime(RuntimeFunction(), 1);
2584 return Runtime::kAbort;
2601 Label in_range, done;
2605 __ and_(
edi, Immediate(0x7ff00000));
2606 int supported_exponent_limit =
2608 __ cmp(
edi, Immediate(supported_exponent_limit));
2609 __ j(
below, &in_range, Label::kNear);
2611 __ cmp(
edi, Immediate(0x7ff00000));
2612 Label non_nan_result;
2617 __ push(Immediate(0x7ff80000));
2618 __ push(Immediate(0));
2619 __ fld_d(Operand(
esp, 0));
2620 __ add(
esp, Immediate(2 * kPointerSize));
2621 __ jmp(&done, Label::kNear);
2623 __ bind(&non_nan_result);
2632 Label no_exceptions;
2636 __ test(
eax, Immediate(5));
2637 __ j(
zero, &no_exceptions, Label::kNear);
2639 __ bind(&no_exceptions);
2644 Label partial_remainder_loop;
2645 __ bind(&partial_remainder_loop);
2649 __ test(
eax, Immediate(0x400 ));
2689 void FloatingPointHelper::LoadUnknownsAsIntegers(MacroAssembler* masm,
2691 Label* conversion_failure) {
2693 Label arg1_is_object, check_undefined_arg1;
2694 Label arg2_is_object, check_undefined_arg2;
2695 Label load_arg2, done;
2698 __ JumpIfNotSmi(
edx, &arg1_is_object, Label::kNear);
2704 __ bind(&check_undefined_arg1);
2705 Factory* factory = masm->isolate()->factory();
2706 __ cmp(
edx, factory->undefined_value());
2708 __ mov(
edx, Immediate(0));
2711 __ bind(&arg1_is_object);
2713 __ cmp(
ebx, factory->heap_number_map());
2717 IntegerConvert(masm,
edx, use_sse3, conversion_failure);
2721 __ bind(&load_arg2);
2724 __ JumpIfNotSmi(
eax, &arg2_is_object, Label::kNear);
2731 __ bind(&check_undefined_arg2);
2732 __ cmp(
eax, factory->undefined_value());
2734 __ mov(
ecx, Immediate(0));
2737 __ bind(&arg2_is_object);
2739 __ cmp(
ebx, factory->heap_number_map());
2743 IntegerConvert(masm,
eax, use_sse3, conversion_failure);
2749 void FloatingPointHelper::CheckLoadedIntegersWereInt32(MacroAssembler* masm,
2756 void FloatingPointHelper::LoadFloatOperand(MacroAssembler* masm,
2758 Label load_smi, done;
2760 __ JumpIfSmi(number, &load_smi, Label::kNear);
2762 __ jmp(&done, Label::kNear);
2765 __ SmiUntag(number);
2767 __ fild_s(Operand(
esp, 0));
2774 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm) {
2775 Label load_smi_edx, load_eax, load_smi_eax, done;
2777 __ JumpIfSmi(
edx, &load_smi_edx, Label::kNear);
2782 __ JumpIfSmi(
eax, &load_smi_eax, Label::kNear);
2784 __ jmp(&done, Label::kNear);
2786 __ bind(&load_smi_edx);
2792 __ bind(&load_smi_eax);
2801 void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm,
2802 Label* not_numbers) {
2803 Label load_smi_edx, load_eax, load_smi_eax, load_float_eax, done;
2805 __ JumpIfSmi(
edx, &load_smi_edx, Label::kNear);
2806 Factory* factory = masm->isolate()->factory();
2812 __ JumpIfSmi(
eax, &load_smi_eax, Label::kNear);
2814 __ j(
equal, &load_float_eax, Label::kNear);
2815 __ jmp(not_numbers);
2816 __ bind(&load_smi_edx);
2821 __ bind(&load_smi_eax);
2825 __ jmp(&done, Label::kNear);
2826 __ bind(&load_float_eax);
2832 void FloatingPointHelper::LoadSSE2Smis(MacroAssembler* masm,
2834 const Register left =
edx;
2835 const Register right =
eax;
2836 __ mov(scratch, left);
2837 ASSERT(!scratch.is(right));
2838 __ SmiUntag(scratch);
2839 __ cvtsi2sd(
xmm0, scratch);
2841 __ mov(scratch, right);
2842 __ SmiUntag(scratch);
2843 __ cvtsi2sd(
xmm1, scratch);
2847 void FloatingPointHelper::CheckSSE2OperandsAreInt32(MacroAssembler* masm,
2850 __ cvttsd2si(scratch, Operand(
xmm0));
2851 __ cvtsi2sd(
xmm2, scratch);
2855 __ cvttsd2si(scratch, Operand(
xmm1));
2856 __ cvtsi2sd(
xmm2, scratch);
2863 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm,
2865 ArgLocation arg_location) {
2866 Label load_smi_1, load_smi_2, done_load_1, done;
2867 if (arg_location == ARGS_IN_REGISTERS) {
2868 __ mov(scratch,
edx);
2870 __ mov(scratch, Operand(
esp, 2 * kPointerSize));
2872 __ JumpIfSmi(scratch, &load_smi_1, Label::kNear);
2874 __ bind(&done_load_1);
2876 if (arg_location == ARGS_IN_REGISTERS) {
2877 __ mov(scratch,
eax);
2879 __ mov(scratch, Operand(
esp, 1 * kPointerSize));
2881 __ JumpIfSmi(scratch, &load_smi_2, Label::kNear);
2883 __ jmp(&done, Label::kNear);
2885 __ bind(&load_smi_1);
2886 __ SmiUntag(scratch);
2888 __ fild_s(Operand(
esp, 0));
2890 __ jmp(&done_load_1);
2892 __ bind(&load_smi_2);
2893 __ SmiUntag(scratch);
2895 __ fild_s(Operand(
esp, 0));
2902 void FloatingPointHelper::LoadFloatSmis(MacroAssembler* masm,
2904 const Register left =
edx;
2905 const Register right =
eax;
2906 __ mov(scratch, left);
2907 ASSERT(!scratch.is(right));
2908 __ SmiUntag(scratch);
2910 __ fild_s(Operand(
esp, 0));
2912 __ mov(scratch, right);
2913 __ SmiUntag(scratch);
2914 __ mov(Operand(
esp, 0), scratch);
2915 __ fild_s(Operand(
esp, 0));
2920 void FloatingPointHelper::CheckFloatOperands(MacroAssembler* masm,
2923 Label test_other, done;
2926 __ JumpIfSmi(
edx, &test_other, Label::kNear);
2928 Factory* factory = masm->isolate()->factory();
2929 __ cmp(scratch, factory->heap_number_map());
2932 __ bind(&test_other);
2933 __ JumpIfSmi(
eax, &done, Label::kNear);
2935 __ cmp(scratch, factory->heap_number_map());
2943 void FloatingPointHelper::CheckFloatOperandsAreInt32(MacroAssembler* masm,
2950 CpuFeatures::Scope use_sse2(
SSE2);
2951 Factory* factory = masm->isolate()->factory();
2952 const Register exponent =
eax;
2953 const Register base =
edx;
2954 const Register scratch =
ecx;
2955 const XMMRegister double_result =
xmm3;
2956 const XMMRegister double_base =
xmm2;
2957 const XMMRegister double_exponent =
xmm1;
2958 const XMMRegister double_scratch =
xmm4;
2960 Label call_runtime, done, exponent_not_smi, int_exponent;
2963 __ mov(scratch, Immediate(1));
2964 __ cvtsi2sd(double_result, scratch);
2967 Label base_is_smi, unpack_exponent;
2971 __ mov(base, Operand(
esp, 2 * kPointerSize));
2972 __ mov(exponent, Operand(
esp, 1 * kPointerSize));
2974 __ JumpIfSmi(base, &base_is_smi, Label::kNear);
2976 factory->heap_number_map());
2980 __ jmp(&unpack_exponent, Label::kNear);
2982 __ bind(&base_is_smi);
2984 __ cvtsi2sd(double_base, base);
2986 __ bind(&unpack_exponent);
2987 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear);
2988 __ SmiUntag(exponent);
2989 __ jmp(&int_exponent);
2991 __ bind(&exponent_not_smi);
2993 factory->heap_number_map());
2995 __ movdbl(double_exponent,
2997 }
else if (exponent_type_ ==
TAGGED) {
2998 __ JumpIfNotSmi(exponent, &exponent_not_smi, Label::kNear);
2999 __ SmiUntag(exponent);
3000 __ jmp(&int_exponent);
3002 __ bind(&exponent_not_smi);
3003 __ movdbl(double_exponent,
3007 if (exponent_type_ !=
INTEGER) {
3010 __ cvttsd2si(exponent, Operand(double_exponent));
3012 __ cmp(exponent, Immediate(0x80000000u));
3014 __ cvtsi2sd(double_scratch, exponent);
3016 __ ucomisd(double_exponent, double_scratch);
3023 Label continue_sqrt, continue_rsqrt, not_plus_half;
3026 __ mov(scratch, Immediate(0x3F000000u));
3027 __ movd(double_scratch, scratch);
3028 __ cvtss2sd(double_scratch, double_scratch);
3030 __ ucomisd(double_scratch, double_exponent);
3037 __ mov(scratch, 0xFF800000u);
3038 __ movd(double_scratch, scratch);
3039 __ cvtss2sd(double_scratch, double_scratch);
3040 __ ucomisd(double_base, double_scratch);
3044 __ j(
carry, &continue_sqrt, Label::kNear);
3047 __ xorps(double_result, double_result);
3048 __ subsd(double_result, double_scratch);
3051 __ bind(&continue_sqrt);
3053 __ xorps(double_scratch, double_scratch);
3054 __ addsd(double_scratch, double_base);
3055 __ sqrtsd(double_result, double_scratch);
3059 __ bind(¬_plus_half);
3061 __ subsd(double_scratch, double_result);
3063 __ ucomisd(double_scratch, double_exponent);
3070 __ mov(scratch, 0xFF800000u);
3071 __ movd(double_scratch, scratch);
3072 __ cvtss2sd(double_scratch, double_scratch);
3073 __ ucomisd(double_base, double_scratch);
3077 __ j(
carry, &continue_rsqrt, Label::kNear);
3080 __ xorps(double_result, double_result);
3083 __ bind(&continue_rsqrt);
3085 __ xorps(double_exponent, double_exponent);
3086 __ addsd(double_exponent, double_base);
3087 __ sqrtsd(double_exponent, double_exponent);
3088 __ divsd(double_result, double_exponent);
3093 Label fast_power_failed;
3094 __ bind(&fast_power);
3098 __ movdbl(Operand(
esp, 0), double_exponent);
3099 __ fld_d(Operand(
esp, 0));
3100 __ movdbl(Operand(
esp, 0), double_base);
3101 __ fld_d(Operand(
esp, 0));
3120 __ test_b(
eax, 0x5F);
3121 __ j(
not_zero, &fast_power_failed, Label::kNear);
3122 __ fstp_d(Operand(
esp, 0));
3123 __ movdbl(double_result, Operand(
esp, 0));
3127 __ bind(&fast_power_failed);
3130 __ jmp(&call_runtime);
3134 __ bind(&int_exponent);
3135 const XMMRegister double_scratch2 = double_exponent;
3136 __ mov(scratch, exponent);
3137 __ movsd(double_scratch, double_base);
3138 __ movsd(double_scratch2, double_result);
3141 Label no_neg, while_true, no_multiply;
3142 __ test(scratch, scratch);
3147 __ bind(&while_true);
3150 __ mulsd(double_result, double_scratch);
3151 __ bind(&no_multiply);
3153 __ mulsd(double_scratch, double_scratch);
3158 __ test(exponent, exponent);
3160 __ divsd(double_scratch2, double_result);
3161 __ movsd(double_result, double_scratch2);
3164 __ xorps(double_scratch2, double_scratch2);
3165 __ ucomisd(double_scratch2, double_result);
3170 __ cvtsi2sd(double_exponent, exponent);
3173 Counters* counters = masm->isolate()->counters();
3176 __ bind(&call_runtime);
3177 __ TailCallRuntime(Runtime::kMath_pow_cfunction, 2, 1);
3182 __ AllocateHeapNumber(
eax, scratch, base, &call_runtime);
3184 __ IncrementCounter(counters->math_pow(), 1);
3185 __ ret(2 * kPointerSize);
3187 __ bind(&call_runtime);
3189 AllowExternalCallThatCantCauseGC scope(masm);
3190 __ PrepareCallCFunction(4, scratch);
3194 ExternalReference::power_double_double_function(masm->isolate()), 4);
3199 __ fstp_d(Operand(
esp, 0));
3200 __ movdbl(double_result, Operand(
esp, 0));
3204 __ IncrementCounter(counters->math_pow(), 1);
3210 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
3220 __ JumpIfNotSmi(
edx, &slow, Label::kNear);
3227 __ j(
equal, &adaptor, Label::kNear);
3265 __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1);
3269 void ArgumentsAccessStub::GenerateNewNonStrictSlow(MacroAssembler* masm) {
3284 __ mov(Operand(
esp, 1 * kPointerSize),
ecx);
3287 __ mov(Operand(
esp, 2 * kPointerSize),
edx);
3290 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1);
3294 void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) {
3301 __ mov(
ebx, Operand(
esp, 1 * kPointerSize));
3307 Label adaptor_frame, try_allocate;
3311 __ j(
equal, &adaptor_frame, Label::kNear);
3315 __ jmp(&try_allocate, Label::kNear);
3318 __ bind(&adaptor_frame);
3322 __ mov(Operand(
esp, 2 * kPointerSize),
edx);
3333 __ bind(&try_allocate);
3340 const int kParameterMapHeaderSize =
3342 Label no_parameter_map;
3344 __ j(
zero, &no_parameter_map, Label::kNear);
3346 __ bind(&no_parameter_map);
3363 Label has_mapped_parameters, copy;
3366 __ mov(
ebx, Operand(
esp, 0 * kPointerSize));
3368 __ j(
not_zero, &has_mapped_parameters, Label::kNear);
3371 __ jmp(©, Label::kNear);
3373 __ bind(&has_mapped_parameters);
3393 __ mov(
edx, Operand(
esp, 4 * kPointerSize));
3421 Label skip_parameter_map;
3423 __ j(
zero, &skip_parameter_map);
3426 Immediate(
FACTORY->non_strict_arguments_elements_map()));
3441 Label parameters_loop, parameters_test;
3443 __ mov(
eax, Operand(
esp, 2 * kPointerSize));
3445 __ add(
ebx, Operand(
esp, 4 * kPointerSize));
3460 __ jmp(¶meters_test, Label::kNear);
3462 __ bind(¶meters_loop);
3467 __ bind(¶meters_test);
3469 __ j(
not_zero, ¶meters_loop, Label::kNear);
3472 __ bind(&skip_parameter_map);
3482 Immediate(
FACTORY->fixed_array_map()));
3485 Label arguments_loop, arguments_test;
3486 __ mov(
ebx, Operand(
esp, 1 * kPointerSize));
3487 __ mov(
edx, Operand(
esp, 4 * kPointerSize));
3490 __ jmp(&arguments_test, Label::kNear);
3492 __ bind(&arguments_loop);
3493 __ sub(
edx, Immediate(kPointerSize));
3498 __ bind(&arguments_test);
3500 __ j(
less, &arguments_loop, Label::kNear);
3507 __ ret(3 * kPointerSize);
3512 __ mov(Operand(
esp, 1 * kPointerSize),
ecx);
3513 __ TailCallRuntime(Runtime::kNewStrictArgumentsFast, 3, 1);
3517 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
3524 Label adaptor_frame, try_allocate, runtime;
3528 __ j(
equal, &adaptor_frame, Label::kNear);
3531 __ mov(
ecx, Operand(
esp, 1 * kPointerSize));
3532 __ jmp(&try_allocate, Label::kNear);
3535 __ bind(&adaptor_frame);
3537 __ mov(Operand(
esp, 1 * kPointerSize),
ecx);
3540 __ mov(Operand(
esp, 2 * kPointerSize),
edx);
3544 Label add_arguments_object;
3545 __ bind(&try_allocate);
3547 __ j(
zero, &add_arguments_object, Label::kNear);
3549 __ bind(&add_arguments_object);
3570 __ mov(
ecx, Operand(
esp, 1 * kPointerSize));
3578 __ j(
zero, &done, Label::kNear);
3581 __ mov(
edx, Operand(
esp, 2 * kPointerSize));
3588 Immediate(
FACTORY->fixed_array_map()));
3597 __ mov(
ebx, Operand(
edx, -1 * kPointerSize));
3599 __ add(
edi, Immediate(kPointerSize));
3600 __ sub(
edx, Immediate(kPointerSize));
3606 __ ret(3 * kPointerSize);
3610 __ TailCallRuntime(Runtime::kNewStrictArgumentsFast, 3, 1);
3614 void RegExpExecStub::Generate(MacroAssembler* masm) {
3618 #ifdef V8_INTERPRETED_REGEXP
3619 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
3620 #else // V8_INTERPRETED_REGEXP
3629 static const int kLastMatchInfoOffset = 1 *
kPointerSize;
3630 static const int kPreviousIndexOffset = 2 *
kPointerSize;
3634 Label runtime, invoke_regexp;
3637 ExternalReference address_of_regexp_stack_memory_address =
3638 ExternalReference::address_of_regexp_stack_memory_address(
3640 ExternalReference address_of_regexp_stack_memory_size =
3641 ExternalReference::address_of_regexp_stack_memory_size(masm->isolate());
3642 __ mov(
ebx, Operand::StaticVariable(address_of_regexp_stack_memory_size));
3647 __ mov(
eax, Operand(
esp, kJSRegExpOffset));
3649 __ JumpIfSmi(
eax, &runtime);
3654 if (FLAG_debug_code) {
3656 __ Check(
not_zero,
"Unexpected type for RegExp data, FixedArray expected");
3658 __ Check(
equal,
"Unexpected type for RegExp data, FixedArray expected");
3674 __ add(
edx, Immediate(2));
3682 __ mov(
eax, Operand(
esp, kSubjectOffset));
3683 __ JumpIfSmi(
eax, &runtime);
3694 __ mov(
eax, Operand(
esp, kPreviousIndexOffset));
3695 __ JumpIfNotSmi(
eax, &runtime);
3702 __ mov(
eax, Operand(
esp, kLastMatchInfoOffset));
3703 __ JumpIfSmi(
eax, &runtime);
3709 Factory* factory = masm->isolate()->factory();
3710 __ cmp(
eax, factory->fixed_array_map());
3721 __ Set(
edi, Immediate(0));
3724 Label seq_ascii_string, seq_two_byte_string, check_code;
3725 __ mov(
eax, Operand(
esp, kSubjectOffset));
3734 __ j(
zero, &seq_two_byte_string, Label::kNear);
3741 __ j(
zero, &seq_ascii_string, Label::kNear);
3750 Label cons_string, external_string, check_encoding;
3756 __ j(
less, &cons_string);
3757 __ j(
equal, &external_string);
3769 __ jmp(&check_encoding, Label::kNear);
3771 __ bind(&cons_string);
3775 __ bind(&check_encoding);
3783 __ j(
zero, &seq_two_byte_string, Label::kNear);
3789 __ bind(&seq_ascii_string);
3793 __ Set(
ecx, Immediate(1));
3794 __ jmp(&check_code, Label::kNear);
3796 __ bind(&seq_two_byte_string);
3800 __ Set(
ecx, Immediate(0));
3802 __ bind(&check_code);
3806 __ JumpIfSmi(
edx, &runtime);
3813 __ mov(
ebx, Operand(
esp, kPreviousIndexOffset));
3821 Counters* counters = masm->isolate()->counters();
3822 __ IncrementCounter(counters->regexp_entry_native(), 1);
3825 static const int kRegExpExecuteArguments = 9;
3826 __ EnterApiExitFrame(kRegExpExecuteArguments);
3829 __ mov(Operand(
esp, 8 * kPointerSize),
3830 Immediate(ExternalReference::isolate_address()));
3833 __ mov(Operand(
esp, 7 * kPointerSize), Immediate(1));
3836 __ mov(
esi, Operand::StaticVariable(address_of_regexp_stack_memory_address));
3837 __ add(
esi, Operand::StaticVariable(address_of_regexp_stack_memory_size));
3838 __ mov(Operand(
esp, 6 * kPointerSize),
esi);
3842 __ mov(Operand(
esp, 5 * kPointerSize), Immediate(0));
3845 __ mov(Operand(
esp, 4 * kPointerSize),
3846 Immediate(ExternalReference::address_of_static_offsets_vector(
3850 __ mov(Operand(
esp, 1 * kPointerSize),
ebx);
3857 __ mov(
esi, Operand(
ebp, kSubjectOffset + kPointerSize));
3858 __ mov(Operand(
esp, 0 * kPointerSize),
esi);
3876 Label setup_two_byte, setup_rest;
3878 __ j(
zero, &setup_two_byte, Label::kNear);
3881 __ mov(Operand(
esp, 3 * kPointerSize),
ecx);
3883 __ mov(Operand(
esp, 2 * kPointerSize),
ecx);
3884 __ jmp(&setup_rest, Label::kNear);
3886 __ bind(&setup_two_byte);
3890 __ mov(Operand(
esp, 3 * kPointerSize),
ecx);
3892 __ mov(Operand(
esp, 2 * kPointerSize),
ecx);
3894 __ bind(&setup_rest);
3901 __ LeaveApiExitFrame();
3919 ExternalReference pending_exception(Isolate::kPendingExceptionAddress,
3921 __ mov(
edx, Immediate(masm->isolate()->factory()->the_hole_value()));
3922 __ mov(
eax, Operand::StaticVariable(pending_exception));
3928 __ mov(Operand::StaticVariable(pending_exception),
edx);
3932 __ cmp(
eax, factory->termination_exception());
3933 Label throw_termination_exception;
3934 __ j(
equal, &throw_termination_exception, Label::kNear);
3939 __ bind(&throw_termination_exception);
3940 __ ThrowUncatchable(
eax);
3944 __ mov(
eax, factory->null_value());
3945 __ ret(4 * kPointerSize);
3949 __ mov(
eax, Operand(
esp, kJSRegExpOffset));
3955 __ add(
edx, Immediate(2));
3959 __ mov(
eax, Operand(
esp, kLastMatchInfoOffset));
3969 __ mov(
eax, Operand(
esp, kSubjectOffset));
3971 __ RecordWriteField(
ebx,
3976 __ mov(
eax, Operand(
esp, kSubjectOffset));
3978 __ RecordWriteField(
ebx,
3985 ExternalReference address_of_static_offsets_vector =
3986 ExternalReference::address_of_static_offsets_vector(masm->isolate());
3987 __ mov(
ecx, Immediate(address_of_static_offsets_vector));
3992 Label next_capture, done;
3995 __ bind(&next_capture);
3996 __ sub(
edx, Immediate(1));
4007 __ jmp(&next_capture);
4011 __ mov(
eax, Operand(
esp, kLastMatchInfoOffset));
4012 __ ret(4 * kPointerSize);
4017 __ bind(&external_string);
4020 if (FLAG_debug_code) {
4024 __ Assert(
zero,
"external string expected, but not found");
4033 __ jmp(&seq_two_byte_string);
4037 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1);
4038 #endif // V8_INTERPRETED_REGEXP
4042 void RegExpConstructResultStub::Generate(MacroAssembler* masm) {
4043 const int kMaxInlineLength = 100;
4046 __ mov(
ebx, Operand(
esp, kPointerSize * 3));
4047 __ JumpIfNotSmi(
ebx, &slowcase);
4071 Factory* factory = masm->isolate()->factory();
4072 __ mov(
ecx, Immediate(factory->empty_fixed_array()));
4081 __ mov(
ecx, Operand(
esp, kPointerSize * 1));
4083 __ mov(
ecx, Operand(
esp, kPointerSize * 2));
4085 __ mov(
ecx, Operand(
esp, kPointerSize * 3));
4095 Immediate(factory->fixed_array_map()));
4100 __ mov(
edx, Immediate(factory->the_hole_value()));
4111 __ sub(
ecx, Immediate(1));
4116 __ ret(3 * kPointerSize);
4119 __ TailCallRuntime(Runtime::kRegExpConstructResult, 3, 1);
4131 Register number_string_cache = result;
4132 Register mask = scratch1;
4133 Register scratch = scratch2;
4136 ExternalReference roots_array_start =
4137 ExternalReference::roots_array_start(masm->isolate());
4138 __ mov(scratch, Immediate(Heap::kNumberStringCacheRootIndex));
4139 __ mov(number_string_cache,
4145 __ sub(mask, Immediate(1));
4151 Label smi_hash_calculated;
4152 Label load_result_from_cache;
4153 if (object_is_smi) {
4154 __ mov(scratch,
object);
4155 __ SmiUntag(scratch);
4159 __ JumpIfNotSmi(
object, ¬_smi, Label::kNear);
4160 __ mov(scratch,
object);
4161 __ SmiUntag(scratch);
4162 __ jmp(&smi_hash_calculated, Label::kNear);
4165 masm->isolate()->factory()->heap_number_map());
4171 __ and_(scratch, mask);
4172 Register index = scratch;
4173 Register probe = mask;
4179 __ JumpIfSmi(probe, not_found);
4181 CpuFeatures::Scope fscope(
SSE2);
4192 __ jmp(&load_result_from_cache, Label::kNear);
4195 __ bind(&smi_hash_calculated);
4197 __ and_(scratch, mask);
4198 Register index = scratch;
4208 __ bind(&load_result_from_cache);
4214 Counters* counters = masm->isolate()->counters();
4215 __ IncrementCounter(counters->number_to_string_native(), 1);
4219 void NumberToStringStub::Generate(MacroAssembler* masm) {
4222 __ mov(
ebx, Operand(
esp, kPointerSize));
4226 __ ret(1 * kPointerSize);
4230 __ TailCallRuntime(Runtime::kNumberToStringSkipCache, 1, 1);
4234 static int NegativeComparisonResult(
Condition cc) {
4244 Label check_unequal_objects;
4247 if (include_smi_compare_) {
4248 Label non_smi, smi_done;
4251 __ JumpIfNotSmi(
ecx, &non_smi, Label::kNear);
4259 }
else if (FLAG_debug_code) {
4263 __ Assert(
not_zero,
"Unexpected smi operands.");
4272 Label not_identical;
4279 Label check_for_nan;
4280 __ cmp(
edx, masm->isolate()->factory()->undefined_value());
4284 __ bind(&check_for_nan);
4290 if (never_nan_nan_ && (cc_ ==
equal)) {
4296 Immediate(masm->isolate()->factory()->heap_number_map()));
4297 __ j(
equal, &heap_number, Label::kNear);
4306 __ bind(&heap_number);
4319 __ Set(
eax, Immediate(0));
4339 __ bind(¬_identical);
4344 if (cc_ ==
equal && strict_) {
4364 __ sub(
ecx, Immediate(0x01));
4373 Immediate(masm->isolate()->factory()->heap_number_map()));
4375 __ j(
equal, &slow, Label::kNear);
4387 Label first_non_object;
4390 __ j(
below, &first_non_object, Label::kNear);
4393 Label return_not_equal;
4395 __ bind(&return_not_equal);
4398 __ bind(&first_non_object);
4401 __ j(
equal, &return_not_equal);
4408 __ j(
equal, &return_not_equal);
4415 if (include_number_compare_) {
4416 Label non_number_comparison;
4419 CpuFeatures::Scope use_sse2(
SSE2);
4420 CpuFeatures::Scope use_cmov(
CMOV);
4422 FloatingPointHelper::LoadSSE2Operands(masm, &non_number_comparison);
4435 FloatingPointHelper::CheckFloatOperands(
4436 masm, &non_number_comparison,
ebx);
4437 FloatingPointHelper::LoadFloatOperand(masm,
eax);
4438 FloatingPointHelper::LoadFloatOperand(masm,
edx);
4444 Label below_label, above_label;
4446 __ j(
below, &below_label, Label::kNear);
4447 __ j(
above, &above_label, Label::kNear);
4449 __ Set(
eax, Immediate(0));
4452 __ bind(&below_label);
4456 __ bind(&above_label);
4463 __ bind(&unordered);
4473 __ bind(&non_number_comparison);
4477 Label check_for_strings;
4479 BranchIfNonSymbol(masm, &check_for_strings,
eax,
ecx);
4480 BranchIfNonSymbol(masm, &check_for_strings,
edx,
ecx);
4488 __ bind(&check_for_strings);
4491 &check_unequal_objects);
4509 __ Abort(
"Unexpected fall-through from string comparison");
4512 __ bind(&check_unequal_objects);
4513 if (cc_ ==
equal && !strict_) {
4517 Label not_both_objects;
4518 Label return_unequal;
4526 __ j(
not_zero, ¬_both_objects, Label::kNear);
4528 __ j(
below, ¬_both_objects, Label::kNear);
4530 __ j(
below, ¬_both_objects, Label::kNear);
4536 __ j(
zero, &return_unequal, Label::kNear);
4539 __ j(
zero, &return_unequal, Label::kNear);
4543 __ bind(&return_unequal);
4547 __ bind(¬_both_objects);
4558 builtin = strict_ ? Builtins::STRICT_EQUALS : Builtins::EQUALS;
4573 void CompareStub::BranchIfNonSymbol(MacroAssembler* masm,
4577 __ JumpIfSmi(
object, label);
4587 __ TailCallRuntime(Runtime::kStackGuard, 0, 1);
4592 __ TailCallRuntime(Runtime::kInterrupt, 0, 1);
4596 static void GenerateRecordCallTarget(MacroAssembler* masm) {
4602 Isolate* isolate = masm->isolate();
4603 Label initialize, done;
4611 __ j(
equal, &done, Label::kNear);
4613 __ j(
equal, &done, Label::kNear);
4618 __ j(
equal, &initialize, Label::kNear);
4623 __ jmp(&done, Label::kNear);
4626 __ bind(&initialize);
4637 Isolate* isolate = masm->isolate();
4638 Label slow, non_function;
4643 if (ReceiverMightBeImplicit()) {
4647 __ mov(
eax, Operand(
esp, (argc_ + 1) * kPointerSize));
4649 __ cmp(
eax, isolate->factory()->the_hole_value());
4654 __ mov(Operand(
esp, (argc_ + 1) * kPointerSize),
ecx);
4655 __ bind(&receiver_ok);
4659 __ JumpIfSmi(
edi, &non_function);
4664 if (RecordCallTarget()) {
4665 GenerateRecordCallTarget(masm);
4669 ParameterCount actual(argc_);
4671 if (ReceiverMightBeImplicit()) {
4672 Label call_as_function;
4673 __ cmp(
eax, isolate->factory()->the_hole_value());
4674 __ j(
equal, &call_as_function);
4675 __ InvokeFunction(
edi,
4680 __ bind(&call_as_function);
4682 __ InvokeFunction(
edi,
4690 if (RecordCallTarget()) {
4703 __ Set(
eax, Immediate(argc_ + 1));
4704 __ Set(
ebx, Immediate(0));
4706 __ GetBuiltinEntry(
edx, Builtins::CALL_FUNCTION_PROXY);
4708 Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline();
4709 __ jmp(adaptor, RelocInfo::CODE_TARGET);
4714 __ bind(&non_function);
4715 __ mov(Operand(
esp, (argc_ + 1) * kPointerSize),
edi);
4716 __ Set(
eax, Immediate(argc_));
4717 __ Set(
ebx, Immediate(0));
4719 __ GetBuiltinEntry(
edx, Builtins::CALL_NON_FUNCTION);
4720 Handle<Code> adaptor = isolate->builtins()->ArgumentsAdaptorTrampoline();
4721 __ jmp(adaptor, RelocInfo::CODE_TARGET);
4729 Label slow, non_function_call;
4732 __ JumpIfSmi(
edi, &non_function_call);
4737 if (RecordCallTarget()) {
4738 GenerateRecordCallTarget(masm);
4754 __ GetBuiltinEntry(
edx, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR);
4757 __ bind(&non_function_call);
4758 __ GetBuiltinEntry(
edx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
4761 __ Set(
ebx, Immediate(0));
4762 Handle<Code> arguments_adaptor =
4763 masm->isolate()->builtins()->ArgumentsAdaptorTrampoline();
4765 __ jmp(arguments_adaptor, RelocInfo::CODE_TARGET);
4769 bool CEntryStub::NeedsImmovableCode() {
4775 return (!save_doubles_ ||
ISOLATE->fp_stubs_generated()) &&
4780 void CodeStub::GenerateStubsAheadOfTime() {
4788 void CodeStub::GenerateFPStubs() {
4790 Handle<Code> code = save_doubles.GetCode();
4791 code->set_is_pregenerated(
true);
4792 code->GetIsolate()->set_fp_stubs_generated(
true);
4798 Handle<Code> code = stub.GetCode();
4799 code->set_is_pregenerated(
true);
4803 void CEntryStub::GenerateCore(MacroAssembler* masm,
4804 Label* throw_normal_exception,
4805 Label* throw_termination_exception,
4806 Label* throw_out_of_memory_exception,
4808 bool always_allocate_scope) {
4819 if (FLAG_debug_code) {
4820 __ CheckStackAlignment();
4829 __ mov(Operand(
esp, 0 * kPointerSize),
eax);
4833 ExternalReference scope_depth =
4834 ExternalReference::heap_always_allocate_scope_depth(masm->isolate());
4835 if (always_allocate_scope) {
4836 __ inc(Operand::StaticVariable(scope_depth));
4840 __ mov(Operand(
esp, 0 * kPointerSize),
edi);
4841 __ mov(Operand(
esp, 1 * kPointerSize),
esi);
4842 __ mov(Operand(
esp, 2 * kPointerSize),
4843 Immediate(ExternalReference::isolate_address()));
4847 if (always_allocate_scope) {
4848 __ dec(Operand::StaticVariable(scope_depth));
4853 if (FLAG_debug_code) {
4855 __ cmp(
eax, masm->isolate()->factory()->the_hole_value());
4862 Label failure_returned;
4867 __ j(
zero, &failure_returned);
4869 ExternalReference pending_exception_address(
4870 Isolate::kPendingExceptionAddress, masm->isolate());
4874 if (FLAG_debug_code) {
4876 __ mov(
edx, Immediate(masm->isolate()->factory()->the_hole_value()));
4878 __ cmp(
edx, Operand::StaticVariable(pending_exception_address));
4880 __ j(
equal, &okay, Label::kNear);
4891 __ bind(&failure_returned);
4897 __ j(
zero, &retry, Label::kNear);
4901 __ j(
equal, throw_out_of_memory_exception);
4904 __ mov(
eax, Operand::StaticVariable(pending_exception_address));
4905 __ mov(
edx, Immediate(masm->isolate()->factory()->the_hole_value()));
4906 __ mov(Operand::StaticVariable(pending_exception_address),
edx);
4910 __ cmp(
eax, masm->isolate()->factory()->termination_exception());
4911 __ j(
equal, throw_termination_exception);
4914 __ jmp(throw_normal_exception);
4943 Label throw_normal_exception;
4944 Label throw_termination_exception;
4945 Label throw_out_of_memory_exception;
4949 &throw_normal_exception,
4950 &throw_termination_exception,
4951 &throw_out_of_memory_exception,
4957 &throw_normal_exception,
4958 &throw_termination_exception,
4959 &throw_out_of_memory_exception,
4965 __ mov(
eax, Immediate(reinterpret_cast<int32_t>(failure)));
4967 &throw_normal_exception,
4968 &throw_termination_exception,
4969 &throw_out_of_memory_exception,
4973 __ bind(&throw_out_of_memory_exception);
4975 Isolate* isolate = masm->isolate();
4976 ExternalReference external_caught(Isolate::kExternalCaughtExceptionAddress,
4978 __ mov(Operand::StaticVariable(external_caught), Immediate(
false));
4981 ExternalReference pending_exception(Isolate::kPendingExceptionAddress,
4984 __ mov(Operand::StaticVariable(pending_exception),
eax);
4987 __ bind(&throw_termination_exception);
4988 __ ThrowUncatchable(
eax);
4990 __ bind(&throw_normal_exception);
4996 Label invoke, handler_entry, exit;
4997 Label not_outermost_js, not_outermost_js_2;
5004 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
5013 ExternalReference c_entry_fp(Isolate::kCEntryFPAddress, masm->isolate());
5014 __ push(Operand::StaticVariable(c_entry_fp));
5017 ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress,
5019 __ cmp(Operand::StaticVariable(js_entry_sp), Immediate(0));
5021 __ mov(Operand::StaticVariable(js_entry_sp),
ebp);
5022 __ push(Immediate(
Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)));
5023 __ jmp(&invoke, Label::kNear);
5024 __ bind(¬_outermost_js);
5025 __ push(Immediate(
Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME)));
5030 __ bind(&handler_entry);
5031 handler_offset_ = handler_entry.pos();
5034 ExternalReference pending_exception(Isolate::kPendingExceptionAddress,
5036 __ mov(Operand::StaticVariable(pending_exception),
eax);
5043 __ PushTryHandler(StackHandler::JS_ENTRY, 0);
5046 __ mov(
edx, Immediate(masm->isolate()->factory()->the_hole_value()));
5047 __ mov(Operand::StaticVariable(pending_exception),
edx);
5050 __ push(Immediate(0));
5057 ExternalReference construct_entry(Builtins::kJSConstructEntryTrampoline,
5059 __ mov(
edx, Immediate(construct_entry));
5061 ExternalReference entry(Builtins::kJSEntryTrampoline,
5063 __ mov(
edx, Immediate(entry));
5077 __ mov(Operand::StaticVariable(js_entry_sp), Immediate(0));
5078 __ bind(¬_outermost_js_2);
5081 __ pop(Operand::StaticVariable(ExternalReference(
5082 Isolate::kCEntryFPAddress,
5089 __ add(
esp, Immediate(2 * kPointerSize));
5115 ASSERT(HasArgsInRegisters() || !HasCallSiteInlineCheck());
5118 Register
object =
eax;
5120 Register
function =
edx;
5121 Register prototype =
edi;
5122 Register scratch =
ecx;
5125 static const int kDeltaToCmpImmediate = 2;
5126 static const int kDeltaToMov = 8;
5127 static const int kDeltaToMovImmediate = 9;
5128 static const int8_t kCmpEdiOperandByte1 = BitCast<int8_t, uint8_t>(0x3b);
5129 static const int8_t kCmpEdiOperandByte2 = BitCast<int8_t, uint8_t>(0x3d);
5130 static const int8_t kMovEaxImmediateByte = BitCast<int8_t, uint8_t>(0xb8);
5132 ExternalReference roots_array_start =
5133 ExternalReference::roots_array_start(masm->isolate());
5139 Label slow, not_js_object;
5140 if (!HasArgsInRegisters()) {
5141 __ mov(
object, Operand(
esp, 2 * kPointerSize));
5142 __ mov(
function, Operand(
esp, 1 * kPointerSize));
5146 __ JumpIfSmi(
object, ¬_js_object);
5147 __ IsObjectJSObjectType(
object, map, scratch, ¬_js_object);
5151 if (!HasCallSiteInlineCheck()) {
5154 __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex));
5155 __ cmp(
function, Operand::StaticArray(scratch,
5157 roots_array_start));
5159 __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex));
5160 __ cmp(map, Operand::StaticArray(
5163 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex));
5164 __ mov(
eax, Operand::StaticArray(
5166 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
5171 __ TryGetFunctionPrototype(
function, prototype, scratch, &slow,
true);
5174 __ JumpIfSmi(prototype, &slow);
5175 __ IsObjectJSObjectType(prototype, scratch, scratch, &slow);
5179 if (!HasCallSiteInlineCheck()) {
5180 __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex));
5183 __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex));
5189 ASSERT(HasArgsInRegisters());
5191 __ mov(scratch, Operand(
esp, 0 * kPointerSize));
5192 __ sub(scratch, Operand(
esp, 1 * kPointerSize));
5193 if (FLAG_debug_code) {
5194 __ cmpb(Operand(scratch, 0), kCmpEdiOperandByte1);
5195 __ Assert(
equal,
"InstanceofStub unexpected call site cache (cmp 1)");
5196 __ cmpb(Operand(scratch, 1), kCmpEdiOperandByte2);
5197 __ Assert(
equal,
"InstanceofStub unexpected call site cache (cmp 2)");
5199 __ mov(scratch, Operand(scratch, kDeltaToCmpImmediate));
5200 __ mov(Operand(scratch, 0), map);
5206 Label loop, is_instance, is_not_instance;
5208 __ cmp(scratch, prototype);
5209 __ j(
equal, &is_instance, Label::kNear);
5210 Factory* factory = masm->isolate()->factory();
5211 __ cmp(scratch, Immediate(factory->null_value()));
5212 __ j(
equal, &is_not_instance, Label::kNear);
5217 __ bind(&is_instance);
5218 if (!HasCallSiteInlineCheck()) {
5219 __ Set(
eax, Immediate(0));
5220 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex));
5221 __ mov(Operand::StaticArray(scratch,
5225 __ mov(
eax, factory->true_value());
5226 __ mov(scratch, Operand(
esp, 0 * kPointerSize));
5227 __ sub(scratch, Operand(
esp, 1 * kPointerSize));
5228 if (FLAG_debug_code) {
5229 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte);
5230 __ Assert(
equal,
"InstanceofStub unexpected call site cache (mov)");
5232 __ mov(Operand(scratch, kDeltaToMovImmediate),
eax);
5233 if (!ReturnTrueFalseObject()) {
5234 __ Set(
eax, Immediate(0));
5237 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
5239 __ bind(&is_not_instance);
5240 if (!HasCallSiteInlineCheck()) {
5242 __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex));
5243 __ mov(Operand::StaticArray(
5247 __ mov(
eax, factory->false_value());
5248 __ mov(scratch, Operand(
esp, 0 * kPointerSize));
5249 __ sub(scratch, Operand(
esp, 1 * kPointerSize));
5250 if (FLAG_debug_code) {
5251 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte);
5252 __ Assert(
equal,
"InstanceofStub unexpected call site cache (mov)");
5254 __ mov(Operand(scratch, kDeltaToMovImmediate),
eax);
5255 if (!ReturnTrueFalseObject()) {
5259 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
5261 Label object_not_null, object_not_null_or_smi;
5262 __ bind(¬_js_object);
5265 __ JumpIfSmi(
function, &slow, Label::kNear);
5270 __ cmp(
object, factory->null_value());
5273 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
5275 __ bind(&object_not_null);
5277 __ JumpIfNotSmi(
object, &object_not_null_or_smi, Label::kNear);
5279 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
5281 __ bind(&object_not_null_or_smi);
5283 Condition is_string = masm->IsObjectStringType(
object, scratch, scratch);
5286 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
5290 if (!ReturnTrueFalseObject()) {
5292 if (HasArgsInRegisters()) {
5308 Label true_value, done;
5310 __ j(
zero, &true_value, Label::kNear);
5311 __ mov(
eax, factory->false_value());
5312 __ jmp(&done, Label::kNear);
5313 __ bind(&true_value);
5314 __ mov(
eax, factory->true_value());
5316 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize);
5327 int CompareStub::MinorKey() {
5331 ASSERT(static_cast<unsigned>(cc_) < (1 << 12));
5333 return ConditionField::encode(static_cast<unsigned>(cc_))
5334 | RegisterField::encode(
false)
5335 | StrictField::encode(strict_)
5336 | NeverNanNanField::encode(cc_ ==
equal ? never_nan_nan_ :
false)
5337 | IncludeNumberCompareField::encode(include_number_compare_)
5338 | IncludeSmiCompareField::encode(include_smi_compare_);
5344 void CompareStub::PrintName(StringStream* stream) {
5346 const char* cc_name;
5348 case less: cc_name =
"LT";
break;
5349 case greater: cc_name =
"GT";
break;
5352 case equal: cc_name =
"EQ";
break;
5354 default: cc_name =
"UnknownCondition";
break;
5357 stream->Add(
"CompareStub_%s", cc_name);
5358 if (strict_ && is_equality) stream->Add(
"_STRICT");
5359 if (never_nan_nan_ && is_equality) stream->Add(
"_NO_NAN");
5360 if (!include_number_compare_) stream->Add(
"_NO_NUMBER");
5361 if (!include_smi_compare_) stream->Add(
"_NO_SMI");
5371 __ JumpIfSmi(object_, receiver_not_string_);
5382 __ JumpIfNotSmi(index_, &index_not_smi_);
5383 __ bind(&got_smi_index_);
5389 __ SmiUntag(index_);
5391 Factory* factory = masm->isolate()->factory();
5393 masm, factory, object_, index_, result_, &call_runtime_);
5401 MacroAssembler* masm,
5402 const RuntimeCallHelper& call_helper) {
5403 __ Abort(
"Unexpected fallthrough to CharCodeAt slow case");
5406 __ bind(&index_not_smi_);
5409 masm->isolate()->factory()->heap_number_map(),
5412 call_helper.BeforeCall(masm);
5416 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1);
5420 __ CallRuntime(Runtime::kNumberToSmi, 1);
5422 if (!index_.
is(
eax)) {
5425 __ mov(index_,
eax);
5431 call_helper.AfterCall(masm);
5434 __ JumpIfNotSmi(index_, index_out_of_range_);
5436 __ jmp(&got_smi_index_);
5441 __ bind(&call_runtime_);
5442 call_helper.BeforeCall(masm);
5446 __ CallRuntime(Runtime::kStringCharCodeAt, 2);
5447 if (!result_.
is(
eax)) {
5448 __ mov(result_,
eax);
5450 call_helper.AfterCall(masm);
5453 __ Abort(
"Unexpected fallthrough from CharCodeAt slow case");
5470 Factory* factory = masm->isolate()->factory();
5471 __ Set(result_, Immediate(factory->single_character_string_cache()));
5479 __ cmp(result_, factory->undefined_value());
5486 MacroAssembler* masm,
5487 const RuntimeCallHelper& call_helper) {
5488 __ Abort(
"Unexpected fallthrough to CharFromCode slow case");
5490 __ bind(&slow_case_);
5491 call_helper.BeforeCall(masm);
5493 __ CallRuntime(Runtime::kCharFromCode, 1);
5494 if (!result_.
is(
eax)) {
5495 __ mov(result_,
eax);
5497 call_helper.AfterCall(masm);
5500 __ Abort(
"Unexpected fallthrough from CharFromCode slow case");
5514 MacroAssembler* masm,
5515 const RuntimeCallHelper& call_helper) {
5516 char_code_at_generator_.
GenerateSlow(masm, call_helper);
5517 char_from_code_generator_.
GenerateSlow(masm, call_helper);
5521 void StringAddStub::Generate(MacroAssembler* masm) {
5522 Label call_runtime, call_builtin;
5526 __ mov(
eax, Operand(
esp, 2 * kPointerSize));
5527 __ mov(
edx, Operand(
esp, 1 * kPointerSize));
5531 __ JumpIfSmi(
eax, &call_runtime);
5536 __ JumpIfSmi(
edx, &call_runtime);
5544 GenerateConvertArgument(masm, 2 * kPointerSize,
eax,
ebx,
ecx,
edi,
5546 builtin_id = Builtins::STRING_ADD_RIGHT;
5548 ASSERT((flags_ & NO_STRING_CHECK_LEFT_IN_STUB) != 0);
5549 GenerateConvertArgument(masm, 1 * kPointerSize,
edx,
ebx,
ecx,
edi,
5551 builtin_id = Builtins::STRING_ADD_LEFT;
5559 Label second_not_zero_length, both_not_zero_length;
5563 __ j(
not_zero, &second_not_zero_length, Label::kNear);
5565 Counters* counters = masm->isolate()->counters();
5566 __ IncrementCounter(counters->string_add_native(), 1);
5567 __ ret(2 * kPointerSize);
5568 __ bind(&second_not_zero_length);
5572 __ j(
not_zero, &both_not_zero_length, Label::kNear);
5575 __ IncrementCounter(counters->string_add_native(), 1);
5576 __ ret(2 * kPointerSize);
5584 Label string_add_flat_result, longer_than_two;
5585 __ bind(&both_not_zero_length);
5596 __ JumpIfNotBothSequentialAsciiStrings(
eax,
edx,
ebx,
ecx, &call_runtime);
5604 Label make_two_character_string, make_two_character_string_no_reload;
5607 &make_two_character_string_no_reload, &make_two_character_string);
5608 __ IncrementCounter(counters->string_add_native(), 1);
5609 __ ret(2 * kPointerSize);
5612 __ bind(&make_two_character_string);
5614 __ mov(
eax, Operand(
esp, 2 * kPointerSize));
5615 __ mov(
edx, Operand(
esp, 1 * kPointerSize));
5619 __ bind(&make_two_character_string_no_reload);
5620 __ IncrementCounter(counters->string_add_make_two_char(), 1);
5621 __ AllocateAsciiString(
eax, 2,
edi,
edx, &call_runtime);
5627 __ IncrementCounter(counters->string_add_native(), 1);
5628 __ ret(2 * kPointerSize);
5630 __ bind(&longer_than_two);
5633 __ j(
below, &string_add_flat_result);
5637 Label non_ascii, allocated, ascii_data;
5647 __ bind(&ascii_data);
5650 __ bind(&allocated);
5652 if (FLAG_debug_code)
__ AbortIfNotSmi(
ebx);
5659 __ IncrementCounter(counters->string_add_native(), 1);
5660 __ ret(2 * kPointerSize);
5661 __ bind(&non_ascii);
5686 Label first_prepared, second_prepared;
5687 Label first_is_sequential, second_is_sequential;
5688 __ bind(&string_add_flat_result);
5694 __ j(
zero, &first_is_sequential, Label::kNear);
5701 __ jmp(&first_prepared, Label::kNear);
5702 __ bind(&first_is_sequential);
5704 __ bind(&first_prepared);
5715 __ j(
zero, &second_is_sequential, Label::kNear);
5722 __ jmp(&second_prepared, Label::kNear);
5723 __ bind(&second_is_sequential);
5725 __ bind(&second_prepared);
5731 Label non_ascii_string_add_flat_result, call_runtime_drop_two;
5736 __ j(
zero, &non_ascii_string_add_flat_result);
5748 __ mov(
edx, Operand(
esp, 4 * kPointerSize));
5759 __ mov(
edx, Operand(
esp, 2 * kPointerSize));
5768 __ IncrementCounter(counters->string_add_native(), 1);
5769 __ ret(2 * kPointerSize);
5775 __ bind(&non_ascii_string_add_flat_result);
5785 __ mov(
edx, Operand(
esp, 4 * kPointerSize));
5796 __ mov(
edx, Operand(
esp, 2 * kPointerSize));
5805 __ IncrementCounter(counters->string_add_native(), 1);
5806 __ ret(2 * kPointerSize);
5809 __ bind(&call_runtime_drop_two);
5812 __ bind(&call_runtime);
5813 __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
5815 if (call_builtin.is_linked()) {
5816 __ bind(&call_builtin);
5822 void StringAddStub::GenerateConvertArgument(MacroAssembler* masm,
5830 Label not_string, done;
5831 __ JumpIfSmi(arg, ¬_string);
5837 __ bind(¬_string);
5846 __ mov(arg, scratch1);
5847 __ mov(Operand(
esp, stack_offset), arg);
5851 __ bind(¬_cached);
5852 __ JumpIfSmi(arg, slow);
5859 __ mov(Operand(
esp, stack_offset), arg);
5876 __ mov_b(scratch, Operand(src, 0));
5877 __ mov_b(Operand(dest, 0), scratch);
5878 __ add(src, Immediate(1));
5879 __ add(dest, Immediate(1));
5881 __ mov_w(scratch, Operand(src, 0));
5882 __ mov_w(Operand(dest, 0), scratch);
5883 __ add(src, Immediate(2));
5884 __ add(dest, Immediate(2));
5886 __ sub(count, Immediate(1));
5903 ASSERT(!scratch.is(dest));
5904 ASSERT(!scratch.is(src));
5905 ASSERT(!scratch.is(count));
5909 __ test(count, count);
5919 __ test(count, Immediate(~3));
5920 __ j(
zero, &last_bytes, Label::kNear);
5923 __ mov(scratch, count);
5929 __ mov(count, scratch);
5933 __ bind(&last_bytes);
5934 __ test(count, count);
5940 __ mov_b(scratch, Operand(src, 0));
5941 __ mov_b(Operand(dest, 0), scratch);
5942 __ add(src, Immediate(1));
5943 __ add(dest, Immediate(1));
5944 __ sub(count, Immediate(1));
5960 Register scratch = scratch3;
5964 Label not_array_index;
5965 __ mov(scratch, c1);
5966 __ sub(scratch, Immediate(static_cast<int>(
'0')));
5967 __ cmp(scratch, Immediate(static_cast<int>(
'9' -
'0')));
5968 __ j(
above, ¬_array_index, Label::kNear);
5969 __ mov(scratch, c2);
5970 __ sub(scratch, Immediate(static_cast<int>(
'0')));
5971 __ cmp(scratch, Immediate(static_cast<int>(
'9' -
'0')));
5974 __ bind(¬_array_index);
5976 Register hash = scratch1;
5982 Register chars = c1;
5990 Register symbol_table = c2;
5991 ExternalReference roots_array_start =
5992 ExternalReference::roots_array_start(masm->isolate());
5994 __ mov(symbol_table,
5998 Register mask = scratch2;
6001 __ sub(mask, Immediate(1));
6011 static const int kProbes = 4;
6012 Label found_in_symbol_table;
6013 Label next_probe[kProbes], next_probe_pop_mask[kProbes];
6014 Register candidate = scratch;
6015 for (
int i = 0; i < kProbes; i++) {
6017 __ mov(scratch, hash);
6019 __ add(scratch, Immediate(SymbolTable::GetProbeOffset(i)));
6021 __ and_(scratch, mask);
6032 Factory* factory = masm->isolate()->factory();
6033 __ cmp(candidate, factory->undefined_value());
6035 __ cmp(candidate, factory->the_hole_value());
6046 Register temp = mask;
6051 __ JumpIfInstanceTypeIsNotSequentialAscii(
6052 temp, temp, &next_probe_pop_mask[i]);
6056 __ and_(temp, 0x0000ffff);
6057 __ cmp(chars, temp);
6058 __ j(
equal, &found_in_symbol_table);
6059 __ bind(&next_probe_pop_mask[i]);
6061 __ bind(&next_probe[i]);
6068 Register result = candidate;
6069 __ bind(&found_in_symbol_table);
6071 if (!result.is(
eax)) {
6072 __ mov(
eax, result);
6083 ExternalReference roots_array_start =
6084 ExternalReference::roots_array_start(masm->isolate());
6085 __ mov(scratch, Immediate(Heap::kHashSeedRootIndex));
6086 __ mov(scratch, Operand::StaticArray(scratch,
6088 roots_array_start));
6089 __ SmiUntag(scratch);
6090 __ add(scratch, character);
6091 __ mov(hash, scratch);
6092 __ shl(scratch, 10);
6093 __ add(hash, scratch);
6095 int32_t seed = masm->isolate()->heap()->HashSeed();
6096 __ lea(scratch, Operand(character, seed));
6097 __ shl(scratch, 10);
6098 __ lea(hash, Operand(scratch, character,
times_1, seed));
6101 __ mov(scratch, hash);
6103 __ xor_(hash, scratch);
6112 __ add(hash, character);
6114 __ mov(scratch, hash);
6115 __ shl(scratch, 10);
6116 __ add(hash, scratch);
6118 __ mov(scratch, hash);
6120 __ xor_(hash, scratch);
6128 __ mov(scratch, hash);
6130 __ add(hash, scratch);
6132 __ mov(scratch, hash);
6133 __ shr(scratch, 11);
6134 __ xor_(hash, scratch);
6136 __ mov(scratch, hash);
6137 __ shl(scratch, 15);
6138 __ add(hash, scratch);
6143 Label hash_not_zero;
6144 __ j(
not_zero, &hash_not_zero, Label::kNear);
6146 __ bind(&hash_not_zero);
6150 void SubStringStub::Generate(MacroAssembler* masm) {
6160 __ mov(
eax, Operand(
esp, 3 * kPointerSize));
6162 __ JumpIfSmi(
eax, &runtime);
6170 __ mov(
ecx, Operand(
esp, 1 * kPointerSize));
6171 __ JumpIfNotSmi(
ecx, &runtime);
6172 __ mov(
edx, Operand(
esp, 2 * kPointerSize));
6173 __ JumpIfNotSmi(
edx, &runtime);
6176 Label not_original_string;
6178 __ j(
below, ¬_original_string, Label::kNear);
6182 Counters* counters = masm->isolate()->counters();
6183 __ IncrementCounter(counters->sub_string_native(), 1);
6184 __ ret(3 * kPointerSize);
6185 __ bind(¬_original_string);
6193 Label underlying_unpacked, sliced_string, seq_or_external_string;
6198 __ j(
zero, &seq_or_external_string, Label::kNear);
6200 Factory* factory = masm->isolate()->factory();
6202 __ j(
not_zero, &sliced_string, Label::kNear);
6206 factory->empty_string());
6212 __ jmp(&underlying_unpacked, Label::kNear);
6214 __ bind(&sliced_string);
6221 __ jmp(&underlying_unpacked, Label::kNear);
6223 __ bind(&seq_or_external_string);
6227 __ bind(&underlying_unpacked);
6229 if (FLAG_string_slices) {
6237 __ j(
less, ©_routine);
6243 Label two_byte_slice, set_slice_header;
6247 __ j(
zero, &two_byte_slice, Label::kNear);
6249 __ jmp(&set_slice_header, Label::kNear);
6250 __ bind(&two_byte_slice);
6252 __ bind(&set_slice_header);
6258 __ IncrementCounter(counters->sub_string_native(), 1);
6259 __ ret(3 * kPointerSize);
6261 __ bind(©_routine);
6270 Label two_byte_sequential, runtime_drop_two, sequential_string;
6274 __ j(
zero, &sequential_string);
6286 __ bind(&sequential_string);
6293 __ j(
zero, &two_byte_sequential);
6317 __ IncrementCounter(counters->sub_string_native(), 1);
6318 __ ret(3 * kPointerSize);
6320 __ bind(&two_byte_sequential);
6347 __ IncrementCounter(counters->sub_string_native(), 1);
6348 __ ret(3 * kPointerSize);
6351 __ bind(&runtime_drop_two);
6356 __ TailCallRuntime(Runtime::kSubString, 3, 1);
6364 Register scratch2) {
6365 Register length = scratch1;
6368 Label strings_not_equal, check_zero_length;
6371 __ j(
equal, &check_zero_length, Label::kNear);
6372 __ bind(&strings_not_equal);
6377 Label compare_chars;
6378 __ bind(&check_zero_length);
6380 __ test(length, length);
6381 __ j(
not_zero, &compare_chars, Label::kNear);
6386 __ bind(&compare_chars);
6387 GenerateAsciiCharsCompareLoop(masm, left, right, length, scratch2,
6388 &strings_not_equal, Label::kNear);
6401 Register scratch3) {
6402 Counters* counters = masm->isolate()->counters();
6403 __ IncrementCounter(counters->string_compare_native(), 1);
6408 __ mov(scratch3, scratch1);
6411 Register length_delta = scratch3;
6415 __ sub(scratch1, length_delta);
6416 __ bind(&left_shorter);
6418 Register min_length = scratch1;
6421 Label compare_lengths;
6422 __ test(min_length, min_length);
6423 __ j(
zero, &compare_lengths, Label::kNear);
6426 Label result_not_equal;
6427 GenerateAsciiCharsCompareLoop(masm, left, right, min_length, scratch2,
6428 &result_not_equal, Label::kNear);
6431 __ bind(&compare_lengths);
6432 __ test(length_delta, length_delta);
6433 __ j(
not_zero, &result_not_equal, Label::kNear);
6441 Label result_greater;
6442 __ bind(&result_not_equal);
6443 __ j(
greater, &result_greater, Label::kNear);
6450 __ bind(&result_greater);
6456 void StringCompareStub::GenerateAsciiCharsCompareLoop(
6457 MacroAssembler* masm,
6462 Label* chars_not_equal,
6463 Label::Distance chars_not_equal_near) {
6467 __ SmiUntag(length);
6473 Register index = length;
6478 __ mov_b(scratch, Operand(left, index,
times_1, 0));
6479 __ cmpb(scratch, Operand(right, index,
times_1, 0));
6480 __ j(
not_equal, chars_not_equal, chars_not_equal_near);
6486 void StringCompareStub::Generate(MacroAssembler* masm) {
6494 __ mov(
edx, Operand(
esp, 2 * kPointerSize));
6495 __ mov(
eax, Operand(
esp, 1 * kPointerSize));
6503 __ IncrementCounter(masm->isolate()->counters()->string_compare_native(), 1);
6504 __ ret(2 * kPointerSize);
6509 __ JumpIfNotBothSequentialAsciiStrings(
edx,
eax,
ecx,
ebx, &runtime);
6514 __ add(
esp, Immediate(2 * kPointerSize));
6521 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
6525 void ICCompareStub::GenerateSmis(MacroAssembler* masm) {
6530 __ JumpIfNotSmi(
ecx, &miss, Label::kNear);
6532 if (GetCondition() ==
equal) {
6551 void ICCompareStub::GenerateHeapNumbers(MacroAssembler* masm) {
6555 Label unordered, maybe_undefined1, maybe_undefined2;
6559 __ JumpIfSmi(
ecx, &generic_stub, Label::kNear);
6569 CpuFeatures::Scope scope1(
SSE2);
6570 CpuFeatures::Scope scope2(
CMOV);
6592 __ bind(&unordered);
6594 __ bind(&generic_stub);
6595 __ jmp(stub.GetCode(), RelocInfo::CODE_TARGET);
6597 __ bind(&maybe_undefined1);
6599 __ cmp(
eax, Immediate(masm->isolate()->factory()->undefined_value()));
6606 __ bind(&maybe_undefined2);
6608 __ cmp(
edx, Immediate(masm->isolate()->factory()->undefined_value()));
6617 void ICCompareStub::GenerateSymbols(MacroAssembler* masm) {
6622 Register left =
edx;
6623 Register right =
eax;
6624 Register tmp1 =
ecx;
6625 Register tmp2 =
ebx;
6631 __ and_(tmp1, right);
6632 __ JumpIfSmi(tmp1, &miss, Label::kNear);
6640 __ and_(tmp1, tmp2);
6642 __ j(
zero, &miss, Label::kNear);
6646 __ cmp(left, right);
6662 void ICCompareStub::GenerateStrings(MacroAssembler* masm) {
6669 Register left =
edx;
6670 Register right =
eax;
6671 Register tmp1 =
ecx;
6672 Register tmp2 =
ebx;
6673 Register tmp3 =
edi;
6678 __ and_(tmp1, right);
6679 __ JumpIfSmi(tmp1, &miss);
6695 __ cmp(left, right);
6711 __ and_(tmp1, tmp2);
6713 __ j(
zero, &do_compare, Label::kNear);
6718 __ bind(&do_compare);
6723 __ JumpIfNotBothSequentialAsciiStrings(left, right, tmp1, tmp2, &runtime);
6728 masm, left, right, tmp1, tmp2);
6731 masm, left, right, tmp1, tmp2, tmp3);
6741 __ TailCallRuntime(Runtime::kStringEquals, 2, 1);
6743 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
6751 void ICCompareStub::GenerateObjects(MacroAssembler* masm) {
6756 __ JumpIfSmi(
ecx, &miss, Label::kNear);
6772 void ICCompareStub::GenerateKnownObjects(MacroAssembler* masm) {
6776 __ JumpIfSmi(
ecx, &miss, Label::kNear);
6780 __ cmp(
ecx, known_map_);
6782 __ cmp(
ebx, known_map_);
6793 void ICCompareStub::GenerateMiss(MacroAssembler* masm) {
6796 ExternalReference miss = ExternalReference(IC_Utility(IC::kCompareIC_Miss),
6804 __ CallExternalReference(miss, 3);
6824 Register properties,
6825 Handle<String>
name,
6827 ASSERT(name->IsSymbol());
6834 for (
int i = 0; i < kInlinedProbes; i++) {
6836 Register index =
r0;
6842 StringDictionary::GetProbeOffset(i))));
6846 __ lea(index, Operand(index, index,
times_2, 0));
6847 Register entity_name =
r0;
6852 __ cmp(entity_name, masm->isolate()->factory()->undefined_value());
6856 __ cmp(entity_name, Handle<String>(name));
6861 __ cmp(entity_name, masm->isolate()->factory()->the_hole_value());
6862 __ j(
equal, &the_hole, Label::kNear);
6876 __ push(Immediate(Handle<Object>(name)));
6877 __ push(Immediate(name->Hash()));
6896 ASSERT(!elements.is(r0));
6897 ASSERT(!elements.is(r1));
6902 if (FLAG_debug_code)
__ AbortIfNotString(name);
6911 for (
int i = 0; i < kInlinedProbes; i++) {
6916 __ add(r0, Immediate(StringDictionary::GetProbeOffset(i)));
6922 __ lea(r0, Operand(r0, r0,
times_2, 0));
6925 __ cmp(name, Operand(elements,
6963 Label in_dictionary, maybe_in_dictionary, not_in_dictionary;
6965 Register scratch = result_;
6969 __ SmiUntag(scratch);
6977 for (
int i = kInlinedProbes; i < kTotalProbes; i++) {
6979 __ mov(scratch, Operand(
esp, 2 * kPointerSize));
6981 __ add(scratch, Immediate(StringDictionary::GetProbeOffset(i)));
6983 __ and_(scratch, Operand(
esp, 0));
6987 __ lea(index_, Operand(scratch, scratch,
times_2, 0));
6991 __ mov(scratch, Operand(dictionary_,
6995 __ cmp(scratch, masm->isolate()->factory()->undefined_value());
6996 __ j(
equal, ¬_in_dictionary);
6999 __ cmp(scratch, Operand(
esp, 3 * kPointerSize));
7011 __ j(
zero, &maybe_in_dictionary);
7015 __ bind(&maybe_in_dictionary);
7020 __ mov(result_, Immediate(0));
7022 __ ret(2 * kPointerSize);
7025 __ bind(&in_dictionary);
7026 __ mov(result_, Immediate(1));
7028 __ ret(2 * kPointerSize);
7030 __ bind(¬_in_dictionary);
7031 __ mov(result_, Immediate(0));
7033 __ ret(2 * kPointerSize);
7037 struct AheadOfTimeWriteBarrierStubList {
7038 Register object, value, address;
7043 #define REG(Name) { kRegister_ ## Name ## _Code }
7045 static const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = {
7083 for (
const AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime;
7084 !entry->object.is(
no_reg);
7086 if (object_.
is(entry->object) &&
7087 value_.
is(entry->value) &&
7088 address_.
is(entry->address) &&
7089 remembered_set_action_ == entry->action &&
7100 stub1.GetCode()->set_is_pregenerated(
true);
7102 CpuFeatures::TryForceFeatureScope scope(
SSE2);
7105 stub2.GetCode()->set_is_pregenerated(
true);
7111 for (
const AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime;
7112 !entry->object.is(
no_reg);
7119 stub.GetCode()->set_is_pregenerated(
true);
7128 void RecordWriteStub::Generate(MacroAssembler* masm) {
7129 Label skip_to_incremental_noncompacting;
7130 Label skip_to_incremental_compacting;
7136 __ jmp(&skip_to_incremental_noncompacting, Label::kNear);
7137 __ jmp(&skip_to_incremental_compacting, Label::kFar);
7140 __ RememberedSetHelper(object_,
7149 __ bind(&skip_to_incremental_noncompacting);
7152 __ bind(&skip_to_incremental_compacting);
7162 void RecordWriteStub::GenerateIncremental(MacroAssembler* masm, Mode mode) {
7166 Label dont_need_remembered_set;
7168 __ mov(regs_.scratch0(), Operand(regs_.address(), 0));
7169 __ JumpIfNotInNewSpace(regs_.scratch0(),
7171 &dont_need_remembered_set);
7173 __ CheckPageFlag(regs_.object(),
7177 &dont_need_remembered_set);
7181 CheckNeedsToInformIncrementalMarker(
7183 kUpdateRememberedSetOnNoNeedToInformIncrementalMarker,
7185 InformIncrementalMarker(masm, mode);
7186 regs_.Restore(masm);
7187 __ RememberedSetHelper(object_,
7193 __ bind(&dont_need_remembered_set);
7196 CheckNeedsToInformIncrementalMarker(
7198 kReturnOnNoNeedToInformIncrementalMarker,
7200 InformIncrementalMarker(masm, mode);
7201 regs_.Restore(masm);
7206 void RecordWriteStub::InformIncrementalMarker(MacroAssembler* masm, Mode mode) {
7207 regs_.SaveCallerSaveRegisters(masm, save_fp_regs_mode_);
7208 int argument_count = 3;
7209 __ PrepareCallCFunction(argument_count, regs_.scratch0());
7210 __ mov(Operand(
esp, 0 * kPointerSize), regs_.object());
7212 __ mov(Operand(
esp, 1 * kPointerSize), regs_.address());
7215 __ mov(regs_.scratch0(), Operand(regs_.address(), 0));
7216 __ mov(Operand(
esp, 1 * kPointerSize), regs_.scratch0());
7218 __ mov(Operand(
esp, 2 * kPointerSize),
7219 Immediate(ExternalReference::isolate_address()));
7221 AllowExternalCallThatCantCauseGC scope(masm);
7224 ExternalReference::incremental_evacuation_record_write_function(
7230 ExternalReference::incremental_marking_record_write_function(
7234 regs_.RestoreCallerSaveRegisters(masm, save_fp_regs_mode_);
7238 void RecordWriteStub::CheckNeedsToInformIncrementalMarker(
7239 MacroAssembler* masm,
7240 OnNoNeedToInformIncrementalMarker on_no_need,
7242 Label object_is_black, need_incremental, need_incremental_pop_object;
7246 __ JumpIfBlack(regs_.object(),
7252 regs_.Restore(masm);
7253 if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) {
7254 __ RememberedSetHelper(object_,
7263 __ bind(&object_is_black);
7266 __ mov(regs_.scratch0(), Operand(regs_.address(), 0));
7269 Label ensure_not_white;
7271 __ CheckPageFlag(regs_.scratch0(),
7278 __ CheckPageFlag(regs_.object(),
7285 __ jmp(&need_incremental);
7287 __ bind(&ensure_not_white);
7292 __ push(regs_.object());
7293 __ EnsureNotWhite(regs_.scratch0(),
7296 &need_incremental_pop_object,
7298 __ pop(regs_.object());
7300 regs_.Restore(masm);
7301 if (on_no_need == kUpdateRememberedSetOnNoNeedToInformIncrementalMarker) {
7302 __ RememberedSetHelper(object_,
7311 __ bind(&need_incremental_pop_object);
7312 __ pop(regs_.object());
7314 __ bind(&need_incremental);
7320 void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) {
7331 Label double_elements;
7333 Label slow_elements;
7334 Label slow_elements_from_double;
7335 Label fast_elements;
7337 __ CheckFastElements(
edi, &double_elements);
7340 __ JumpIfSmi(
eax, &smi_element);
7341 __ CheckFastSmiElements(
edi, &fast_elements, Label::kNear);
7346 __ bind(&slow_elements);
7357 __ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1);
7359 __ bind(&slow_elements_from_double);
7361 __ jmp(&slow_elements);
7364 __ bind(&fast_elements);
7378 __ bind(&smi_element);
7385 __ bind(&double_elements);
7389 __ StoreNumberToDoubleElements(
eax,
7394 &slow_elements_from_double,
7404 #endif // V8_TARGET_ARCH_IA32
static const int kResourceDataOffset
static const int kCallerFPOffset
void GenerateFast(MacroAssembler *masm)
void GenerateSlow(MacroAssembler *masm, const RuntimeCallHelper &call_helper)
static const int kLengthOffset
static const int kBitFieldOffset
void GenerateFast(MacroAssembler *masm)
STATIC_CHECK((kStringRepresentationMask|kStringEncodingMask)==Internals::kFullStringRepresentationMask)
const intptr_t kSmiTagMask
static const int kCodeOffset
static const int kEvacuationCandidateMask
#define CHECK_EQ(expected, value)
void GenerateSlow(MacroAssembler *masm, const RuntimeCallHelper &call_helper)
static const int kCodeEntryOffset
static const int kMaxAsciiCharCode
static const int kPrototypeOrInitialMapOffset
#define COMPARE(asm_, compare_string)
static int SlotOffset(int index)
RecordWriteStub(Register object, Register value, Register address, RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode)
static const int kStaticOffsetsVectorSize
static const int kArgumentsObjectSize
static void GenerateFixedRegStubsAheadOfTime()
const uint32_t kTwoByteStringTag
const int kFailureTypeTagSize
static const uint32_t kExponentMask
static const char * GetName(TypeInfo type_info)
static Failure * InternalError()
static void GenerateCopyCharacters(MacroAssembler *masm, Register dest, Register src, Register count, Register scratch, bool ascii)
static void PerformGC(Object *result)
static const char * Name(Value tok)
static Smi * FromInt(int value)
void Generate(MacroAssembler *masm)
static const byte kTwoByteNopInstruction
value format" "after each garbage collection") DEFINE_bool(print_cumulative_gc_stat, false, "print cumulative GC statistics in name=value format on exit") DEFINE_bool(trace_gc_verbose, false, "print more details following each garbage collection") DEFINE_bool(trace_fragmentation, false, "report fragmentation for old pointer and data pages") DEFINE_bool(collect_maps, true, "garbage collect maps from which no objects can be reached") DEFINE_bool(flush_code, true, "flush code that we expect not to use again before full gc") DEFINE_bool(incremental_marking, true, "use incremental marking") DEFINE_bool(incremental_marking_steps, true, "do incremental marking steps") DEFINE_bool(trace_incremental_marking, false, "trace progress of the incremental marking") DEFINE_bool(use_idle_notification, true, "Use idle notification to reduce memory footprint.") DEFINE_bool(send_idle_notification, false, "Send idle notifcation between stress runs.") DEFINE_bool(use_ic, true, "use inline caching") DEFINE_bool(native_code_counters, false, "generate extra code for manipulating stats counters") DEFINE_bool(always_compact, false, "Perform compaction on every full GC") DEFINE_bool(lazy_sweeping, true, "Use lazy sweeping for old pointer and data spaces") DEFINE_bool(never_compact, false, "Never perform compaction on full GC-testing only") DEFINE_bool(compact_code_space, true, "Compact code space on full non-incremental collections") DEFINE_bool(cleanup_code_caches_at_gc, true, "Flush inline caches prior to mark compact collection and" "flush code caches in maps during mark compact cycle.") DEFINE_int(random_seed, 0, "Default seed for initializing random generator" "(0, the default, means to use system random).") DEFINE_bool(use_verbose_printer, true, "allows verbose printing") DEFINE_bool(allow_natives_syntax, false, "allow natives syntax") DEFINE_bool(trace_sim, false, "Trace simulator execution") DEFINE_bool(check_icache, false, "Check icache flushes in ARM and MIPS simulator") DEFINE_int(stop_sim_at, 0, "Simulator stop after x number of instructions") DEFINE_int(sim_stack_alignment, 8, "Stack alingment in bytes in simulator(4 or 8, 8 is default)") DEFINE_bool(trace_exception, false, "print stack trace when throwing exceptions") DEFINE_bool(preallocate_message_memory, false, "preallocate some memory to build stack traces.") DEFINE_bool(randomize_hashes, true, "randomize hashes to avoid predictable hash collisions" "(with snapshots this option cannot override the baked-in seed)") DEFINE_int(hash_seed, 0, "Fixed seed to use to hash property keys(0 means random)" "(with snapshots this option cannot override the baked-in seed)") DEFINE_bool(preemption, false, "activate a 100ms timer that switches between V8 threads") DEFINE_bool(regexp_optimization, true, "generate optimized regexp code") DEFINE_bool(testing_bool_flag, true, "testing_bool_flag") DEFINE_int(testing_int_flag, 13, "testing_int_flag") DEFINE_float(testing_float_flag, 2.5, "float-flag") DEFINE_string(testing_string_flag, "Hello, world!", "string-flag") DEFINE_int(testing_prng_seed, 42, "Seed used for threading test randomness") DEFINE_string(testing_serialization_file, "/tmp/serdes", "file in which to serialize heap") DEFINE_bool(help, false, "Print usage message, including flags, on console") DEFINE_bool(dump_counters, false, "Dump counters on exit") DEFINE_string(map_counters, "", "Map counters to a file") DEFINE_args(js_arguments, JSARGUMENTS_INIT, "Pass all remaining arguments to the script.Alias for\"--\".") DEFINE_bool(debug_compile_events, true,"Enable debugger compile events") DEFINE_bool(debug_script_collected_events, true,"Enable debugger script collected events") DEFINE_bool(gdbjit, false,"enable GDBJIT interface (disables compacting GC)") DEFINE_bool(gdbjit_full, false,"enable GDBJIT interface for all code objects") DEFINE_bool(gdbjit_dump, false,"dump elf objects with debug info to disk") DEFINE_string(gdbjit_dump_filter,"","dump only objects containing this substring") DEFINE_bool(force_marking_deque_overflows, false,"force overflows of marking deque by reducing it's size ""to 64 words") DEFINE_bool(stress_compaction, false,"stress the GC compactor to flush out bugs (implies ""--force_marking_deque_overflows)")#define FLAG DEFINE_bool(enable_slow_asserts, false,"enable asserts that are slow to execute") DEFINE_bool(trace_codegen, false,"print name of functions for which code is generated") DEFINE_bool(print_source, false,"pretty print source code") DEFINE_bool(print_builtin_source, false,"pretty print source code for builtins") DEFINE_bool(print_ast, false,"print source AST") DEFINE_bool(print_builtin_ast, false,"print source AST for builtins") DEFINE_string(stop_at,"","function name where to insert a breakpoint") DEFINE_bool(print_builtin_scopes, false,"print scopes for builtins") DEFINE_bool(print_scopes, false,"print scopes") DEFINE_bool(trace_contexts, false,"trace contexts operations") DEFINE_bool(gc_greedy, false,"perform GC prior to some allocations") DEFINE_bool(gc_verbose, false,"print stuff during garbage collection") DEFINE_bool(heap_stats, false,"report heap statistics before and after GC") DEFINE_bool(code_stats, false,"report code statistics after GC") DEFINE_bool(verify_heap, false,"verify heap pointers before and after GC") DEFINE_bool(print_handles, false,"report handles after GC") DEFINE_bool(print_global_handles, false,"report global handles after GC") DEFINE_bool(trace_ic, false,"trace inline cache state transitions") DEFINE_bool(print_interfaces, false,"print interfaces") DEFINE_bool(print_interface_details, false,"print interface inference details") DEFINE_int(print_interface_depth, 5,"depth for printing interfaces") DEFINE_bool(trace_normalization, false,"prints when objects are turned into dictionaries.") DEFINE_bool(trace_lazy, false,"trace lazy compilation") DEFINE_bool(collect_heap_spill_statistics, false,"report heap spill statistics along with heap_stats ""(requires heap_stats)") DEFINE_bool(trace_isolates, false,"trace isolate state changes") DEFINE_bool(log_state_changes, false,"Log state changes.") DEFINE_bool(regexp_possessive_quantifier, false,"enable possessive quantifier syntax for testing") DEFINE_bool(trace_regexp_bytecodes, false,"trace regexp bytecode execution") DEFINE_bool(trace_regexp_assembler, false,"trace regexp macro assembler calls.")#define FLAG DEFINE_bool(log, false,"Minimal logging (no API, code, GC, suspect, or handles samples).") DEFINE_bool(log_all, false,"Log all events to the log file.") DEFINE_bool(log_runtime, false,"Activate runtime system %Log call.") DEFINE_bool(log_api, false,"Log API events to the log file.") DEFINE_bool(log_code, false,"Log code events to the log file without profiling.") DEFINE_bool(log_gc, false,"Log heap samples on garbage collection for the hp2ps tool.") DEFINE_bool(log_handles, false,"Log global handle events.") DEFINE_bool(log_snapshot_positions, false,"log positions of (de)serialized objects in the snapshot.") DEFINE_bool(log_suspect, false,"Log suspect operations.") DEFINE_bool(prof, false,"Log statistical profiling information (implies --log-code).") DEFINE_bool(prof_auto, true,"Used with --prof, starts profiling automatically") DEFINE_bool(prof_lazy, false,"Used with --prof, only does sampling and logging"" when profiler is active (implies --noprof_auto).") DEFINE_bool(prof_browser_mode, true,"Used with --prof, turns on browser-compatible mode for profiling.") DEFINE_bool(log_regexp, false,"Log regular expression execution.") DEFINE_bool(sliding_state_window, false,"Update sliding state window counters.") DEFINE_string(logfile,"v8.log","Specify the name of the log file.") DEFINE_bool(ll_prof, false,"Enable low-level linux profiler.")#define FLAG DEFINE_bool(trace_elements_transitions, false,"trace elements transitions") DEFINE_bool(print_code_stubs, false,"print code stubs") DEFINE_bool(test_secondary_stub_cache, false,"test secondary stub cache by disabling the primary one") DEFINE_bool(test_primary_stub_cache, false,"test primary stub cache by disabling the secondary one") DEFINE_bool(print_code, false,"print generated code") DEFINE_bool(print_opt_code, false,"print optimized code") DEFINE_bool(print_unopt_code, false,"print unoptimized code before ""printing optimized code based on it") DEFINE_bool(print_code_verbose, false,"print more information for code") DEFINE_bool(print_builtin_code, false,"print generated code for builtins")#43"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flags.cc"2#define FLAG_MODE_DEFINE_DEFAULTS#1"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flag-definitions.h"1#define FLAG_FULL(ftype, ctype, nam, def, cmt)#define FLAG_READONLY(ftype, ctype, nam, def, cmt)#define DEFINE_implication(whenflag, thenflag)#define DEFINE_bool(nam, def, cmt)#define DEFINE_int(nam, def, cmt)#define DEFINE_float(nam, def, cmt)#define DEFINE_string(nam, def, cmt)#define DEFINE_args(nam, def, cmt)#define FLAG DEFINE_bool(use_strict, false,"enforce strict mode") DEFINE_bool(es5_readonly, false,"activate correct semantics for inheriting readonliness") DEFINE_bool(es52_globals, false,"activate new semantics for global var declarations") DEFINE_bool(harmony_typeof, false,"enable harmony semantics for typeof") DEFINE_bool(harmony_scoping, false,"enable harmony block scoping") DEFINE_bool(harmony_modules, false,"enable harmony modules (implies block scoping)") DEFINE_bool(harmony_proxies, false,"enable harmony proxies") DEFINE_bool(harmony_collections, false,"enable harmony collections (sets, maps, and weak maps)") DEFINE_bool(harmony, false,"enable all harmony features (except typeof)") DEFINE_implication(harmony, harmony_scoping) DEFINE_implication(harmony, harmony_modules) DEFINE_implication(harmony, harmony_proxies) DEFINE_implication(harmony, harmony_collections) DEFINE_implication(harmony_modules, harmony_scoping) DEFINE_bool(packed_arrays, false,"optimizes arrays that have no holes") DEFINE_bool(smi_only_arrays, true,"tracks arrays with only smi values") DEFINE_bool(clever_optimizations, true,"Optimize object size, Array shift, DOM strings and string +") DEFINE_bool(unbox_double_arrays, true,"automatically unbox arrays of doubles") DEFINE_bool(string_slices, true,"use string slices") DEFINE_bool(crankshaft, true,"use crankshaft") DEFINE_string(hydrogen_filter,"","optimization filter") DEFINE_bool(use_range, true,"use hydrogen range analysis") DEFINE_bool(eliminate_dead_phis, true,"eliminate dead phis") DEFINE_bool(use_gvn, true,"use hydrogen global value numbering") DEFINE_bool(use_canonicalizing, true,"use hydrogen instruction canonicalizing") DEFINE_bool(use_inlining, true,"use function inlining") DEFINE_int(max_inlined_source_size, 600,"maximum source size in bytes considered for a single inlining") DEFINE_int(max_inlined_nodes, 196,"maximum number of AST nodes considered for a single inlining") DEFINE_int(max_inlined_nodes_cumulative, 196,"maximum cumulative number of AST nodes considered for inlining") DEFINE_bool(loop_invariant_code_motion, true,"loop invariant code motion") DEFINE_bool(collect_megamorphic_maps_from_stub_cache, true,"crankshaft harvests type feedback from stub cache") DEFINE_bool(hydrogen_stats, false,"print statistics for hydrogen") DEFINE_bool(trace_hydrogen, false,"trace generated hydrogen to file") DEFINE_string(trace_phase,"Z","trace generated IR for specified phases") DEFINE_bool(trace_inlining, false,"trace inlining decisions") DEFINE_bool(trace_alloc, false,"trace register allocator") DEFINE_bool(trace_all_uses, false,"trace all use positions") DEFINE_bool(trace_range, false,"trace range analysis") DEFINE_bool(trace_gvn, false,"trace global value numbering") DEFINE_bool(trace_representation, false,"trace representation types") DEFINE_bool(stress_pointer_maps, false,"pointer map for every instruction") DEFINE_bool(stress_environments, false,"environment for every instruction") DEFINE_int(deopt_every_n_times, 0,"deoptimize every n times a deopt point is passed") DEFINE_bool(trap_on_deopt, false,"put a break point before deoptimizing") DEFINE_bool(deoptimize_uncommon_cases, true,"deoptimize uncommon cases") DEFINE_bool(polymorphic_inlining, true,"polymorphic inlining") DEFINE_bool(use_osr, true,"use on-stack replacement") DEFINE_bool(array_bounds_checks_elimination, false,"perform array bounds checks elimination") DEFINE_bool(array_index_dehoisting, false,"perform array index dehoisting") DEFINE_bool(trace_osr, false,"trace on-stack replacement") DEFINE_int(stress_runs, 0,"number of stress runs") DEFINE_bool(optimize_closures, true,"optimize closures") DEFINE_bool(inline_construct, true,"inline constructor calls") DEFINE_bool(inline_arguments, true,"inline functions with arguments object") DEFINE_int(loop_weight, 1,"loop weight for representation inference") DEFINE_bool(optimize_for_in, true,"optimize functions containing for-in loops") DEFINE_bool(experimental_profiler, true,"enable all profiler experiments") DEFINE_bool(watch_ic_patching, false,"profiler considers IC stability") DEFINE_int(frame_count, 1,"number of stack frames inspected by the profiler") DEFINE_bool(self_optimization, false,"primitive functions trigger their own optimization") DEFINE_bool(direct_self_opt, false,"call recompile stub directly when self-optimizing") DEFINE_bool(retry_self_opt, false,"re-try self-optimization if it failed") DEFINE_bool(count_based_interrupts, false,"trigger profiler ticks based on counting instead of timing") DEFINE_bool(interrupt_at_exit, false,"insert an interrupt check at function exit") DEFINE_bool(weighted_back_edges, false,"weight back edges by jump distance for interrupt triggering") DEFINE_int(interrupt_budget, 5900,"execution budget before interrupt is triggered") DEFINE_int(type_info_threshold, 15,"percentage of ICs that must have type info to allow optimization") DEFINE_int(self_opt_count, 130,"call count before self-optimization") DEFINE_implication(experimental_profiler, watch_ic_patching) DEFINE_implication(experimental_profiler, self_optimization) DEFINE_implication(experimental_profiler, retry_self_opt) DEFINE_implication(experimental_profiler, count_based_interrupts) DEFINE_implication(experimental_profiler, interrupt_at_exit) DEFINE_implication(experimental_profiler, weighted_back_edges) DEFINE_bool(trace_opt_verbose, false,"extra verbose compilation tracing") DEFINE_implication(trace_opt_verbose, trace_opt) DEFINE_bool(debug_code, false,"generate extra code (assertions) for debugging") DEFINE_bool(code_comments, false,"emit comments in code disassembly") DEFINE_bool(enable_sse2, true,"enable use of SSE2 instructions if available") DEFINE_bool(enable_sse3, true,"enable use of SSE3 instructions if available") DEFINE_bool(enable_sse4_1, true,"enable use of SSE4.1 instructions if available") DEFINE_bool(enable_cmov, true,"enable use of CMOV instruction if available") DEFINE_bool(enable_rdtsc, true,"enable use of RDTSC instruction if available") DEFINE_bool(enable_sahf, true,"enable use of SAHF instruction if available (X64 only)") DEFINE_bool(enable_vfp3, true,"enable use of VFP3 instructions if available - this implies ""enabling ARMv7 instructions (ARM only)") DEFINE_bool(enable_armv7, true,"enable use of ARMv7 instructions if available (ARM only)") DEFINE_bool(enable_fpu, true,"enable use of MIPS FPU instructions if available (MIPS only)") DEFINE_string(expose_natives_as, NULL,"expose natives in global object") DEFINE_string(expose_debug_as, NULL,"expose debug in global object") DEFINE_bool(expose_gc, false,"expose gc extension") DEFINE_bool(expose_externalize_string, false,"expose externalize string extension") DEFINE_int(stack_trace_limit, 10,"number of stack frames to capture") DEFINE_bool(builtins_in_stack_traces, false,"show built-in functions in stack traces") DEFINE_bool(disable_native_files, false,"disable builtin natives files") DEFINE_bool(inline_new, true,"use fast inline allocation") DEFINE_bool(stack_trace_on_abort, true,"print a stack trace if an assertion failure occurs") DEFINE_bool(trace, false,"trace function calls") DEFINE_bool(mask_constants_with_cookie, true,"use random jit cookie to mask large constants") DEFINE_bool(lazy, true,"use lazy compilation") DEFINE_bool(trace_opt, false,"trace lazy optimization") DEFINE_bool(trace_opt_stats, false,"trace lazy optimization statistics") DEFINE_bool(opt, true,"use adaptive optimizations") DEFINE_bool(always_opt, false,"always try to optimize functions") DEFINE_bool(prepare_always_opt, false,"prepare for turning on always opt") DEFINE_bool(trace_deopt, false,"trace deoptimization") DEFINE_int(min_preparse_length, 1024,"minimum length for automatic enable preparsing") DEFINE_bool(always_full_compiler, false,"try to use the dedicated run-once backend for all code") DEFINE_bool(trace_bailout, false,"print reasons for falling back to using the classic V8 backend") DEFINE_bool(compilation_cache, true,"enable compilation cache") DEFINE_bool(cache_prototype_transitions, true,"cache prototype transitions") DEFINE_bool(trace_debug_json, false,"trace debugging JSON request/response") DEFINE_bool(debugger_auto_break, true,"automatically set the debug break flag when debugger commands are ""in the queue") DEFINE_bool(enable_liveedit, true,"enable liveedit experimental feature") DEFINE_bool(break_on_abort, true,"always cause a debug break before aborting") DEFINE_int(stack_size, kPointerSize *123,"default size of stack region v8 is allowed to use (in kBytes)") DEFINE_int(max_stack_trace_source_length, 300,"maximum length of function source code printed in a stack trace.") DEFINE_bool(always_inline_smi_code, false,"always inline smi code in non-opt code") DEFINE_int(max_new_space_size, 0,"max size of the new generation (in kBytes)") DEFINE_int(max_old_space_size, 0,"max size of the old generation (in Mbytes)") DEFINE_int(max_executable_size, 0,"max size of executable memory (in Mbytes)") DEFINE_bool(gc_global, false,"always perform global GCs") DEFINE_int(gc_interval,-1,"garbage collect after <n> allocations") DEFINE_bool(trace_gc, false,"print one trace line following each garbage collection") DEFINE_bool(trace_gc_nvp, false,"print one detailed trace line in name=value format ""after each garbage collection") DEFINE_bool(print_cumulative_gc_stat, false,"print cumulative GC statistics in name=value format on exit") DEFINE_bool(trace_gc_verbose, false,"print more details following each garbage collection") DEFINE_bool(trace_fragmentation, false,"report fragmentation for old pointer and data pages") DEFINE_bool(collect_maps, true,"garbage collect maps from which no objects can be reached") DEFINE_bool(flush_code, true,"flush code that we expect not to use again before full gc") DEFINE_bool(incremental_marking, true,"use incremental marking") DEFINE_bool(incremental_marking_steps, true,"do incremental marking steps") DEFINE_bool(trace_incremental_marking, false,"trace progress of the incremental marking") DEFINE_bool(use_idle_notification, true,"Use idle notification to reduce memory footprint.") DEFINE_bool(send_idle_notification, false,"Send idle notifcation between stress runs.") DEFINE_bool(use_ic, true,"use inline caching") DEFINE_bool(native_code_counters, false,"generate extra code for manipulating stats counters") DEFINE_bool(always_compact, false,"Perform compaction on every full GC") DEFINE_bool(lazy_sweeping, true,"Use lazy sweeping for old pointer and data spaces") DEFINE_bool(never_compact, false,"Never perform compaction on full GC - testing only") DEFINE_bool(compact_code_space, true,"Compact code space on full non-incremental collections") DEFINE_bool(cleanup_code_caches_at_gc, true,"Flush inline caches prior to mark compact collection and ""flush code caches in maps during mark compact cycle.") DEFINE_int(random_seed, 0,"Default seed for initializing random generator ""(0, the default, means to use system random).") DEFINE_bool(use_verbose_printer, true,"allows verbose printing") DEFINE_bool(allow_natives_syntax, false,"allow natives syntax") DEFINE_bool(trace_sim, false,"Trace simulator execution") DEFINE_bool(check_icache, false,"Check icache flushes in ARM and MIPS simulator") DEFINE_int(stop_sim_at, 0,"Simulator stop after x number of instructions") DEFINE_int(sim_stack_alignment, 8,"Stack alingment in bytes in simulator (4 or 8, 8 is default)") DEFINE_bool(trace_exception, false,"print stack trace when throwing exceptions") DEFINE_bool(preallocate_message_memory, false,"preallocate some memory to build stack traces.") DEFINE_bool(randomize_hashes, true,"randomize hashes to avoid predictable hash collisions ""(with snapshots this option cannot override the baked-in seed)") DEFINE_int(hash_seed, 0,"Fixed seed to use to hash property keys (0 means random)""(with snapshots this option cannot override the baked-in seed)") DEFINE_bool(preemption, false,"activate a 100ms timer that switches between V8 threads") DEFINE_bool(regexp_optimization, true,"generate optimized regexp code") DEFINE_bool(testing_bool_flag, true,"testing_bool_flag") DEFINE_int(testing_int_flag, 13,"testing_int_flag") DEFINE_float(testing_float_flag, 2.5,"float-flag") DEFINE_string(testing_string_flag,"Hello, world!","string-flag") DEFINE_int(testing_prng_seed, 42,"Seed used for threading test randomness") DEFINE_string(testing_serialization_file,"/tmp/serdes","file in which to serialize heap") DEFINE_bool(help, false,"Print usage message, including flags, on console") DEFINE_bool(dump_counters, false,"Dump counters on exit") DEFINE_string(map_counters,"","Map counters to a file") DEFINE_args(js_arguments, JSARGUMENTS_INIT,"Pass all remaining arguments to the script. Alias for \"--\".") DEFINE_bool(debug_compile_events, true,"Enable debugger compile events") DEFINE_bool(debug_script_collected_events, true,"Enable debugger script collected events") DEFINE_bool(gdbjit, false,"enable GDBJIT interface (disables compacting GC)") DEFINE_bool(gdbjit_full, false,"enable GDBJIT interface for all code objects") DEFINE_bool(gdbjit_dump, false,"dump elf objects with debug info to disk") DEFINE_string(gdbjit_dump_filter,"","dump only objects containing this substring") DEFINE_bool(force_marking_deque_overflows, false,"force overflows of marking deque by reducing it's size ""to 64 words") DEFINE_bool(stress_compaction, false,"stress the GC compactor to flush out bugs (implies ""--force_marking_deque_overflows)")#define FLAG DEFINE_bool(enable_slow_asserts, false,"enable asserts that are slow to execute") DEFINE_bool(trace_codegen, false,"print name of functions for which code is generated") DEFINE_bool(print_source, false,"pretty print source code") DEFINE_bool(print_builtin_source, false,"pretty print source code for builtins") DEFINE_bool(print_ast, false,"print source AST") DEFINE_bool(print_builtin_ast, false,"print source AST for builtins") DEFINE_string(stop_at,"","function name where to insert a breakpoint") DEFINE_bool(print_builtin_scopes, false,"print scopes for builtins") DEFINE_bool(print_scopes, false,"print scopes") DEFINE_bool(trace_contexts, false,"trace contexts operations") DEFINE_bool(gc_greedy, false,"perform GC prior to some allocations") DEFINE_bool(gc_verbose, false,"print stuff during garbage collection") DEFINE_bool(heap_stats, false,"report heap statistics before and after GC") DEFINE_bool(code_stats, false,"report code statistics after GC") DEFINE_bool(verify_heap, false,"verify heap pointers before and after GC") DEFINE_bool(print_handles, false,"report handles after GC") DEFINE_bool(print_global_handles, false,"report global handles after GC") DEFINE_bool(trace_ic, false,"trace inline cache state transitions") DEFINE_bool(print_interfaces, false,"print interfaces") DEFINE_bool(print_interface_details, false,"print interface inference details") DEFINE_int(print_interface_depth, 5,"depth for printing interfaces") DEFINE_bool(trace_normalization, false,"prints when objects are turned into dictionaries.") DEFINE_bool(trace_lazy, false,"trace lazy compilation") DEFINE_bool(collect_heap_spill_statistics, false,"report heap spill statistics along with heap_stats ""(requires heap_stats)") DEFINE_bool(trace_isolates, false,"trace isolate state changes") DEFINE_bool(log_state_changes, false,"Log state changes.") DEFINE_bool(regexp_possessive_quantifier, false,"enable possessive quantifier syntax for testing") DEFINE_bool(trace_regexp_bytecodes, false,"trace regexp bytecode execution") DEFINE_bool(trace_regexp_assembler, false,"trace regexp macro assembler calls.")#define FLAG DEFINE_bool(log, false,"Minimal logging (no API, code, GC, suspect, or handles samples).") DEFINE_bool(log_all, false,"Log all events to the log file.") DEFINE_bool(log_runtime, false,"Activate runtime system %Log call.") DEFINE_bool(log_api, false,"Log API events to the log file.") DEFINE_bool(log_code, false,"Log code events to the log file without profiling.") DEFINE_bool(log_gc, false,"Log heap samples on garbage collection for the hp2ps tool.") DEFINE_bool(log_handles, false,"Log global handle events.") DEFINE_bool(log_snapshot_positions, false,"log positions of (de)serialized objects in the snapshot.") DEFINE_bool(log_suspect, false,"Log suspect operations.") DEFINE_bool(prof, false,"Log statistical profiling information (implies --log-code).") DEFINE_bool(prof_auto, true,"Used with --prof, starts profiling automatically") DEFINE_bool(prof_lazy, false,"Used with --prof, only does sampling and logging"" when profiler is active (implies --noprof_auto).") DEFINE_bool(prof_browser_mode, true,"Used with --prof, turns on browser-compatible mode for profiling.") DEFINE_bool(log_regexp, false,"Log regular expression execution.") DEFINE_bool(sliding_state_window, false,"Update sliding state window counters.") DEFINE_string(logfile,"v8.log","Specify the name of the log file.") DEFINE_bool(ll_prof, false,"Enable low-level linux profiler.")#define FLAG DEFINE_bool(trace_elements_transitions, false,"trace elements transitions") DEFINE_bool(print_code_stubs, false,"print code stubs") DEFINE_bool(test_secondary_stub_cache, false,"test secondary stub cache by disabling the primary one") DEFINE_bool(test_primary_stub_cache, false,"test primary stub cache by disabling the secondary one") DEFINE_bool(print_code, false,"print generated code") DEFINE_bool(print_opt_code, false,"print optimized code") DEFINE_bool(print_unopt_code, false,"print unoptimized code before ""printing optimized code based on it") DEFINE_bool(print_code_verbose, false,"print more information for code") DEFINE_bool(print_builtin_code, false,"print generated code for builtins")#47"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flags.cc"2 namespace{struct Flag{enum FlagType{TYPE_BOOL, TYPE_INT, TYPE_FLOAT, TYPE_STRING, TYPE_ARGS} name
static const int kDataOffset
static const int kGlobalReceiverOffset
void Generate(MacroAssembler *masm)
static Failure * OutOfMemoryException()
static const int kEmptyHashField
static void GenerateHashGetHash(MacroAssembler *masm, Register hash)
static const int kExponentBias
static Handle< Object > UninitializedSentinel(Isolate *isolate)
static bool IsSupported(CpuFeature f)
static Failure * Exception()
void Generate(MacroAssembler *masm)
virtual bool IsPregenerated()
void Generate(MacroAssembler *masm)
static const int kCallerSPOffset
bool CanBeUndetectable() const
#define ASSERT(condition)
const int kPointerSizeLog2
static const int kInstanceSizeOffset
static void GenerateCompareFlatAsciiStrings(MacroAssembler *masm, Register left, Register right, Register scratch1, Register scratch2, Register scratch3, Register scratch4)
static Handle< Object > MegamorphicSentinel(Isolate *isolate)
static const char * GetName(TypeInfo type_info)
const uint32_t kStringRepresentationMask
static void GenerateOperation(MacroAssembler *masm, TranscendentalCache::Type type)
MemOperand GlobalObjectOperand()
static const int kEntrySize
static const int kGlobalContextOffset
MemOperand ContextOperand(Register context, int index)
static const int kContextOffset
const uint32_t kAsciiDataHintTag
const uint32_t kShortExternalStringMask
static void GenerateNegativeLookup(MacroAssembler *masm, Label *miss, Label *done, Register receiver, Register properties, Handle< String > name, Register scratch0)
static const int kLastSubjectOffset
static const int kZeroHash
void Generate(MacroAssembler *masm)
static const int kHashFieldOffset
static const int kLastCaptureCountOffset
static const int kFirstOffset
static const int kMinLength
StringDictionaryLookupStub(LookupMode mode)
const uint32_t kNotStringTag
static const int kParentOffset
static const int kNonMantissaBitsInTopWord
static const int kLiteralsOffset
static const int kArgumentsObjectSizeStrict
static void GenerateCopyCharactersREP(MacroAssembler *masm, Register dest, Register src, Register count, Register scratch, bool ascii)
STATIC_ASSERT((FixedDoubleArray::kHeaderSize &kDoubleAlignmentMask)==0)
static const int kLengthOffset
static const int kCapacityOffset
const uint32_t kIsSymbolMask
static const int kExponentShift
const intptr_t kFailureTagMask
static const int kValueOffset
const int kFailureTagSize
static void GenerateFlatAsciiStringEquals(MacroAssembler *masm, Register left, Register right, Register scratch1, Register scratch2, Register scratch3)
static const int kIrregexpCaptureCountOffset
static const int kInputOffset
static bool IsBitOp(Value op)
const uint32_t kIsIndirectStringMask
void Generate(MacroAssembler *masm)
virtual bool IsPregenerated()
static const int kStringWrapperSafeForDefaultValueOf
Operand FieldOperand(Register object, int offset)
const uint32_t kAsciiDataHintMask
static const byte kFiveByteNopInstruction
void Generate(MacroAssembler *masm)
static const int kPropertiesOffset
static const int kMinLength
const uint32_t kShortExternalStringTag
static void GenerateHashAddCharacter(MacroAssembler *masm, Register hash, Register character)
static void Generate(MacroAssembler *masm, Register string, Register index, Register result, Label *call_runtime)
static const int kHeaderSize
static const int kNextFunctionLinkOffset
static int SizeFor(int length)
static const int kElementsOffset
const uint32_t kStringTag
const uint32_t kQuietNaNHighBitsMask
static bool IsEqualityOp(Value op)
static const int kOffsetOffset
void Generate(MacroAssembler *masm)
static const int kLengthOffset
static int SizeFor(int length)
void GenerateSlow(MacroAssembler *masm, const RuntimeCallHelper &call_helper)
virtual void Generate(MacroAssembler *masm)
static const int kLastMatchOverhead
static const int kHeaderSize
void Generate(MacroAssembler *masm)
static const int kMapOffset
bool is(Register reg) const
static const int kSkipEvacuationSlotsRecordingMask
const uint32_t kIsNotStringMask
static void GenerateFixedRegStubsAheadOfTime()
const uint32_t kSlicedNotConsMask
static const int kLengthOffset
void Generate(MacroAssembler *masm)
void Generate(MacroAssembler *masm)
static const int kSecondOffset
static void GeneratePositiveLookup(MacroAssembler *masm, Label *miss, Label *done, Register elements, Register name, Register r0, Register r1)
static const int kArgumentsLengthIndex
static const int kContextOffset
static const int kFunctionOffset
static const int kFirstCaptureOffset
static const uint32_t kHashBitMask
static const uint32_t kSignMask
static const int kLastInputOffset
static const int kHeaderSize
void GenerateBody(MacroAssembler *masm, bool is_construct)
static const int kDataAsciiCodeOffset
Condition NegateCondition(Condition cond)
#define ASSERT_EQ(v1, v2)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
static XMMRegister from_code(int code)
static void GenerateAheadOfTime()
static const uint32_t kMantissaMask
static const int kArgumentsCalleeIndex
static const int kIsUndetectable
static const int kHeaderSize
void Generate(MacroAssembler *masm)
void GenerateFast(MacroAssembler *masm)
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 kDataTagOffset
static const int kPrototypeOffset
static const int kElementsStartOffset
#define RUNTIME_ENTRY(name, nargs, ressize)
static void GenerateTwoCharacterSymbolTableProbe(MacroAssembler *masm, Register c1, Register c2, Register scratch1, Register scratch2, Register scratch3, Register scratch4, Register scratch5, Label *not_found)
static const int kMaxLength
static const int kValueOffset
bool Contains(Type type) const
const uint32_t kSymbolTag
const uint32_t kAsciiStringTag
static const int kConstructStubOffset
static const int kNumRegisters
static const int kHashShift
static const int kSharedFunctionInfoOffset
static const int kMaxValue
void Generate(MacroAssembler *masm)
static const int kBitField2Offset
void Generate(MacroAssembler *masm)
CEntryStub(int result_size, SaveFPRegsMode save_doubles=kDontSaveFPRegs)
void check(i::Vector< const char > string)
static const int kExponentOffset
static const int kValueOffset
static const int kDataUC16CodeOffset
void Generate(MacroAssembler *masm)
StoreBufferOverflowStub(SaveFPRegsMode save_fp)
static void GenerateHashInit(MacroAssembler *masm, Register hash, Register character)
static bool IsOrderedRelationalCompareOp(Value op)
const uint32_t kStringEncodingMask
static const int kInstanceTypeOffset
static const int kIndexOffset
static const int kMantissaOffset
void Generate(MacroAssembler *masm)
void Generate(MacroAssembler *masm)