Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Side by Side Diff: src/ia32/lithium-codegen-ia32.cc

Issue 47533002: Use nearlabel AFAP in lithium codegen (Closed) Base URL: git://github.com/v8/v8.git@master
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/ia32/macro-assembler-ia32.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 2029 matching lines...) Expand 10 before | Expand all | Expand 10 after
2040 if (index->value() == 0) { 2040 if (index->value() == 0) {
2041 __ mov(result, FieldOperand(object, JSDate::kValueOffset)); 2041 __ mov(result, FieldOperand(object, JSDate::kValueOffset));
2042 } else { 2042 } else {
2043 if (index->value() < JSDate::kFirstUncachedField) { 2043 if (index->value() < JSDate::kFirstUncachedField) {
2044 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); 2044 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
2045 __ mov(scratch, Operand::StaticVariable(stamp)); 2045 __ mov(scratch, Operand::StaticVariable(stamp));
2046 __ cmp(scratch, FieldOperand(object, JSDate::kCacheStampOffset)); 2046 __ cmp(scratch, FieldOperand(object, JSDate::kCacheStampOffset));
2047 __ j(not_equal, &runtime, Label::kNear); 2047 __ j(not_equal, &runtime, Label::kNear);
2048 __ mov(result, FieldOperand(object, JSDate::kValueOffset + 2048 __ mov(result, FieldOperand(object, JSDate::kValueOffset +
2049 kPointerSize * index->value())); 2049 kPointerSize * index->value()));
2050 __ jmp(&done); 2050 __ jmp(&done, Label::kNear);
2051 } 2051 }
2052 __ bind(&runtime); 2052 __ bind(&runtime);
2053 __ PrepareCallCFunction(2, scratch); 2053 __ PrepareCallCFunction(2, scratch);
2054 __ mov(Operand(esp, 0), object); 2054 __ mov(Operand(esp, 0), object);
2055 __ mov(Operand(esp, 1 * kPointerSize), Immediate(index)); 2055 __ mov(Operand(esp, 1 * kPointerSize), Immediate(index));
2056 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); 2056 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
2057 __ bind(&done); 2057 __ bind(&done);
2058 } 2058 }
2059 } 2059 }
2060 2060
(...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after
2582 __ ucomisd(input_reg, input_reg); 2582 __ ucomisd(input_reg, input_reg);
2583 EmitFalseBranch(instr, parity_odd); 2583 EmitFalseBranch(instr, parity_odd);
2584 } else { 2584 } else {
2585 // Put the value to the top of stack 2585 // Put the value to the top of stack
2586 X87Register src = ToX87Register(instr->object()); 2586 X87Register src = ToX87Register(instr->object());
2587 X87LoadForUsage(src); 2587 X87LoadForUsage(src);
2588 __ fld(0); 2588 __ fld(0);
2589 __ fld(0); 2589 __ fld(0);
2590 __ FCmp(); 2590 __ FCmp();
2591 Label ok; 2591 Label ok;
2592 __ j(parity_even, &ok); 2592 __ j(parity_even, &ok, Label::kNear);
2593 __ fstp(0); 2593 __ fstp(0);
2594 EmitFalseBranch(instr, no_condition); 2594 EmitFalseBranch(instr, no_condition);
2595 __ bind(&ok); 2595 __ bind(&ok);
2596 } 2596 }
2597 2597
2598 2598
2599 __ sub(esp, Immediate(kDoubleSize)); 2599 __ sub(esp, Immediate(kDoubleSize));
2600 if (use_sse2) { 2600 if (use_sse2) {
2601 CpuFeatureScope scope(masm(), SSE2); 2601 CpuFeatureScope scope(masm(), SSE2);
2602 XMMRegister input_reg = ToDoubleRegister(instr->object()); 2602 XMMRegister input_reg = ToDoubleRegister(instr->object());
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
2906 }; 2906 };
2907 2907
2908 DeferredInstanceOfKnownGlobal* deferred; 2908 DeferredInstanceOfKnownGlobal* deferred;
2909 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr, x87_stack_); 2909 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr, x87_stack_);
2910 2910
2911 Label done, false_result; 2911 Label done, false_result;
2912 Register object = ToRegister(instr->value()); 2912 Register object = ToRegister(instr->value());
2913 Register temp = ToRegister(instr->temp()); 2913 Register temp = ToRegister(instr->temp());
2914 2914
2915 // A Smi is not an instance of anything. 2915 // A Smi is not an instance of anything.
2916 __ JumpIfSmi(object, &false_result); 2916 __ JumpIfSmi(object, &false_result, Label::kNear);
2917 2917
2918 // This is the inlined call site instanceof cache. The two occurences of the 2918 // This is the inlined call site instanceof cache. The two occurences of the
2919 // hole value will be patched to the last map/result pair generated by the 2919 // hole value will be patched to the last map/result pair generated by the
2920 // instanceof stub. 2920 // instanceof stub.
2921 Label cache_miss; 2921 Label cache_miss;
2922 Register map = ToRegister(instr->temp()); 2922 Register map = ToRegister(instr->temp());
2923 __ mov(map, FieldOperand(object, HeapObject::kMapOffset)); 2923 __ mov(map, FieldOperand(object, HeapObject::kMapOffset));
2924 __ bind(deferred->map_check()); // Label for calculating code patching. 2924 __ bind(deferred->map_check()); // Label for calculating code patching.
2925 Handle<Cell> cache_cell = factory()->NewCell(factory()->the_hole_value()); 2925 Handle<Cell> cache_cell = factory()->NewCell(factory()->the_hole_value());
2926 __ cmp(map, Operand::ForCell(cache_cell)); // Patched to cached map. 2926 __ cmp(map, Operand::ForCell(cache_cell)); // Patched to cached map.
2927 __ j(not_equal, &cache_miss, Label::kNear); 2927 __ j(not_equal, &cache_miss, Label::kNear);
2928 __ mov(eax, factory()->the_hole_value()); // Patched to either true or false. 2928 __ mov(eax, factory()->the_hole_value()); // Patched to either true or false.
2929 __ jmp(&done); 2929 __ jmp(&done, Label::kNear);
2930 2930
2931 // The inlined call site cache did not match. Check for null and string 2931 // The inlined call site cache did not match. Check for null and string
2932 // before calling the deferred code. 2932 // before calling the deferred code.
2933 __ bind(&cache_miss); 2933 __ bind(&cache_miss);
2934 // Null is not an instance of anything. 2934 // Null is not an instance of anything.
2935 __ cmp(object, factory()->null_value()); 2935 __ cmp(object, factory()->null_value());
2936 __ j(equal, &false_result); 2936 __ j(equal, &false_result, Label::kNear);
2937 2937
2938 // String values are not instances of anything. 2938 // String values are not instances of anything.
2939 Condition is_string = masm_->IsObjectStringType(object, temp, temp); 2939 Condition is_string = masm_->IsObjectStringType(object, temp, temp);
2940 __ j(is_string, &false_result); 2940 __ j(is_string, &false_result, Label::kNear);
2941 2941
2942 // Go to the deferred code. 2942 // Go to the deferred code.
2943 __ jmp(deferred->entry()); 2943 __ jmp(deferred->entry());
2944 2944
2945 __ bind(&false_result); 2945 __ bind(&false_result);
2946 __ mov(ToRegister(instr->result()), factory()->false_value()); 2946 __ mov(ToRegister(instr->result()), factory()->false_value());
2947 2947
2948 // Here result has either true or false. Deferred code also produces true or 2948 // Here result has either true or false. Deferred code also produces true or
2949 // false object. 2949 // false object.
2950 __ bind(deferred->exit()); 2950 __ bind(deferred->exit());
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
3075 } 3075 }
3076 int no_frame_start = -1; 3076 int no_frame_start = -1;
3077 if (NeedsEagerFrame()) { 3077 if (NeedsEagerFrame()) {
3078 __ mov(esp, ebp); 3078 __ mov(esp, ebp);
3079 __ pop(ebp); 3079 __ pop(ebp);
3080 no_frame_start = masm_->pc_offset(); 3080 no_frame_start = masm_->pc_offset();
3081 } 3081 }
3082 if (dynamic_frame_alignment_) { 3082 if (dynamic_frame_alignment_) {
3083 Label no_padding; 3083 Label no_padding;
3084 __ cmp(edx, Immediate(kNoAlignmentPadding)); 3084 __ cmp(edx, Immediate(kNoAlignmentPadding));
3085 __ j(equal, &no_padding); 3085 __ j(equal, &no_padding, Label::kNear);
3086 3086
3087 EmitReturn(instr, true); 3087 EmitReturn(instr, true);
3088 __ bind(&no_padding); 3088 __ bind(&no_padding);
3089 } 3089 }
3090 3090
3091 EmitReturn(instr, false); 3091 EmitReturn(instr, false);
3092 if (no_frame_start != -1) { 3092 if (no_frame_start != -1) {
3093 info()->AddNoFrameRange(no_frame_start, masm_->pc_offset()); 3093 info()->AddNoFrameRange(no_frame_start, masm_->pc_offset());
3094 } 3094 }
3095 } 3095 }
(...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after
3600 // object as a receiver to normal functions. Values have to be 3600 // object as a receiver to normal functions. Values have to be
3601 // passed unchanged to builtins and strict-mode functions. 3601 // passed unchanged to builtins and strict-mode functions.
3602 Label global_object, receiver_ok; 3602 Label global_object, receiver_ok;
3603 3603
3604 // Do not transform the receiver to object for strict mode 3604 // Do not transform the receiver to object for strict mode
3605 // functions. 3605 // functions.
3606 __ mov(scratch, 3606 __ mov(scratch,
3607 FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); 3607 FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
3608 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset), 3608 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset),
3609 1 << SharedFunctionInfo::kStrictModeBitWithinByte); 3609 1 << SharedFunctionInfo::kStrictModeBitWithinByte);
3610 __ j(not_equal, &receiver_ok); // A near jump is not sufficient here! 3610 __ j(not_equal, &receiver_ok, Label::kNear);
Jakob Kummerow 2013/10/28 10:37:19 Why do you think this comment is not true anymore?
Weiliang 2013/10/28 14:31:49 Yes, thanks for pointing it out. near jump is not
3611 3611
3612 // Do not transform the receiver to object for builtins. 3612 // Do not transform the receiver to object for builtins.
3613 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kNativeByteOffset), 3613 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kNativeByteOffset),
3614 1 << SharedFunctionInfo::kNativeBitWithinByte); 3614 1 << SharedFunctionInfo::kNativeBitWithinByte);
3615 __ j(not_equal, &receiver_ok); 3615 __ j(not_equal, &receiver_ok, Label::kNear);
3616 3616
3617 // Normal function. Replace undefined or null with global receiver. 3617 // Normal function. Replace undefined or null with global receiver.
3618 __ cmp(receiver, factory()->null_value()); 3618 __ cmp(receiver, factory()->null_value());
3619 __ j(equal, &global_object, Label::kNear); 3619 __ j(equal, &global_object, Label::kNear);
3620 __ cmp(receiver, factory()->undefined_value()); 3620 __ cmp(receiver, factory()->undefined_value());
3621 __ j(equal, &global_object, Label::kNear); 3621 __ j(equal, &global_object, Label::kNear);
3622 3622
3623 // The receiver should be a JS object. 3623 // The receiver should be a JS object.
3624 __ test(receiver, Immediate(kSmiTagMask)); 3624 __ test(receiver, Immediate(kSmiTagMask));
3625 DeoptimizeIf(equal, instr->environment()); 3625 DeoptimizeIf(equal, instr->environment());
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
3814 3814
3815 // Preserve the value of all registers. 3815 // Preserve the value of all registers.
3816 PushSafepointRegistersScope scope(this); 3816 PushSafepointRegistersScope scope(this);
3817 3817
3818 __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 3818 __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset));
3819 // Check the sign of the argument. If the argument is positive, just 3819 // Check the sign of the argument. If the argument is positive, just
3820 // return it. We do not need to patch the stack since |input| and 3820 // return it. We do not need to patch the stack since |input| and
3821 // |result| are the same register and |input| will be restored 3821 // |result| are the same register and |input| will be restored
3822 // unchanged by popping safepoint registers. 3822 // unchanged by popping safepoint registers.
3823 __ test(tmp, Immediate(HeapNumber::kSignMask)); 3823 __ test(tmp, Immediate(HeapNumber::kSignMask));
3824 __ j(zero, &done); 3824 __ j(zero, &done, Label::kNear);
3825 3825
3826 __ AllocateHeapNumber(tmp, tmp2, no_reg, &slow); 3826 __ AllocateHeapNumber(tmp, tmp2, no_reg, &slow);
3827 __ jmp(&allocated, Label::kNear); 3827 __ jmp(&allocated, Label::kNear);
3828 3828
3829 // Slow case: Call the runtime system to do the number allocation. 3829 // Slow case: Call the runtime system to do the number allocation.
3830 __ bind(&slow); 3830 __ bind(&slow);
3831 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, 3831 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0,
3832 instr, instr->context()); 3832 instr, instr->context());
3833 // Set the pointer to the new heap number in tmp. 3833 // Set the pointer to the new heap number in tmp.
3834 if (!tmp.is(eax)) __ mov(tmp, eax); 3834 if (!tmp.is(eax)) __ mov(tmp, eax);
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
3970 XMMRegister input_reg = ToDoubleRegister(instr->value()); 3970 XMMRegister input_reg = ToDoubleRegister(instr->value());
3971 XMMRegister xmm_scratch = double_scratch0(); 3971 XMMRegister xmm_scratch = double_scratch0();
3972 XMMRegister input_temp = ToDoubleRegister(instr->temp()); 3972 XMMRegister input_temp = ToDoubleRegister(instr->temp());
3973 ExternalReference one_half = ExternalReference::address_of_one_half(); 3973 ExternalReference one_half = ExternalReference::address_of_one_half();
3974 ExternalReference minus_one_half = 3974 ExternalReference minus_one_half =
3975 ExternalReference::address_of_minus_one_half(); 3975 ExternalReference::address_of_minus_one_half();
3976 3976
3977 Label done, round_to_zero, below_one_half, do_not_compensate; 3977 Label done, round_to_zero, below_one_half, do_not_compensate;
3978 __ movsd(xmm_scratch, Operand::StaticVariable(one_half)); 3978 __ movsd(xmm_scratch, Operand::StaticVariable(one_half));
3979 __ ucomisd(xmm_scratch, input_reg); 3979 __ ucomisd(xmm_scratch, input_reg);
3980 __ j(above, &below_one_half); 3980 __ j(above, &below_one_half, Label::kNear);
3981 3981
3982 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). 3982 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x).
3983 __ addsd(xmm_scratch, input_reg); 3983 __ addsd(xmm_scratch, input_reg);
3984 __ cvttsd2si(output_reg, Operand(xmm_scratch)); 3984 __ cvttsd2si(output_reg, Operand(xmm_scratch));
3985 // Overflow is signalled with minint. 3985 // Overflow is signalled with minint.
3986 __ cmp(output_reg, 0x80000000u); 3986 __ cmp(output_reg, 0x80000000u);
3987 __ RecordComment("D2I conversion overflow"); 3987 __ RecordComment("D2I conversion overflow");
3988 DeoptimizeIf(equal, instr->environment()); 3988 DeoptimizeIf(equal, instr->environment());
3989 __ jmp(&done); 3989 __ jmp(&done, Label::kNear);
3990 3990
3991 __ bind(&below_one_half); 3991 __ bind(&below_one_half);
3992 __ movsd(xmm_scratch, Operand::StaticVariable(minus_one_half)); 3992 __ movsd(xmm_scratch, Operand::StaticVariable(minus_one_half));
3993 __ ucomisd(xmm_scratch, input_reg); 3993 __ ucomisd(xmm_scratch, input_reg);
3994 __ j(below_equal, &round_to_zero); 3994 __ j(below_equal, &round_to_zero, Label::kNear);
3995 3995
3996 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then 3996 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then
3997 // compare and compensate. 3997 // compare and compensate.
3998 __ movsd(input_temp, input_reg); // Do not alter input_reg. 3998 __ movsd(input_temp, input_reg); // Do not alter input_reg.
3999 __ subsd(input_temp, xmm_scratch); 3999 __ subsd(input_temp, xmm_scratch);
4000 __ cvttsd2si(output_reg, Operand(input_temp)); 4000 __ cvttsd2si(output_reg, Operand(input_temp));
4001 // Catch minint due to overflow, and to prevent overflow when compensating. 4001 // Catch minint due to overflow, and to prevent overflow when compensating.
4002 __ cmp(output_reg, 0x80000000u); 4002 __ cmp(output_reg, 0x80000000u);
4003 __ RecordComment("D2I conversion overflow"); 4003 __ RecordComment("D2I conversion overflow");
4004 DeoptimizeIf(equal, instr->environment()); 4004 DeoptimizeIf(equal, instr->environment());
4005 4005
4006 __ Cvtsi2sd(xmm_scratch, output_reg); 4006 __ Cvtsi2sd(xmm_scratch, output_reg);
4007 __ ucomisd(xmm_scratch, input_temp); 4007 __ ucomisd(xmm_scratch, input_temp);
4008 __ j(equal, &done); 4008 __ j(equal, &done, Label::kNear);
4009 __ sub(output_reg, Immediate(1)); 4009 __ sub(output_reg, Immediate(1));
4010 // No overflow because we already ruled out minint. 4010 // No overflow because we already ruled out minint.
4011 __ jmp(&done); 4011 __ jmp(&done, Label::kNear);
4012 4012
4013 __ bind(&round_to_zero); 4013 __ bind(&round_to_zero);
4014 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if 4014 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if
4015 // we can ignore the difference between a result of -0 and +0. 4015 // we can ignore the difference between a result of -0 and +0.
4016 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 4016 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
4017 // If the sign is positive, we return +0. 4017 // If the sign is positive, we return +0.
4018 __ movmskpd(output_reg, input_reg); 4018 __ movmskpd(output_reg, input_reg);
4019 __ test(output_reg, Immediate(1)); 4019 __ test(output_reg, Immediate(1));
4020 __ RecordComment("Minus zero"); 4020 __ RecordComment("Minus zero");
4021 DeoptimizeIf(not_zero, instr->environment()); 4021 DeoptimizeIf(not_zero, instr->environment());
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after
4356 ArrayNoArgumentConstructorStub stub(kind, context_mode, override_mode); 4356 ArrayNoArgumentConstructorStub stub(kind, context_mode, override_mode);
4357 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); 4357 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
4358 } else if (instr->arity() == 1) { 4358 } else if (instr->arity() == 1) {
4359 Label done; 4359 Label done;
4360 if (IsFastPackedElementsKind(kind)) { 4360 if (IsFastPackedElementsKind(kind)) {
4361 Label packed_case; 4361 Label packed_case;
4362 // We might need a change here 4362 // We might need a change here
4363 // look at the first argument 4363 // look at the first argument
4364 __ mov(ecx, Operand(esp, 0)); 4364 __ mov(ecx, Operand(esp, 0));
4365 __ test(ecx, ecx); 4365 __ test(ecx, ecx);
4366 __ j(zero, &packed_case); 4366 __ j(zero, &packed_case, Label::kNear);
4367 4367
4368 ElementsKind holey_kind = GetHoleyElementsKind(kind); 4368 ElementsKind holey_kind = GetHoleyElementsKind(kind);
4369 ArraySingleArgumentConstructorStub stub(holey_kind, context_mode, 4369 ArraySingleArgumentConstructorStub stub(holey_kind, context_mode,
4370 override_mode); 4370 override_mode);
4371 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); 4371 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
4372 __ jmp(&done); 4372 __ jmp(&done, Label::kNear);
4373 __ bind(&packed_case); 4373 __ bind(&packed_case);
4374 } 4374 }
4375 4375
4376 ArraySingleArgumentConstructorStub stub(kind, context_mode, override_mode); 4376 ArraySingleArgumentConstructorStub stub(kind, context_mode, override_mode);
4377 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); 4377 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
4378 __ bind(&done); 4378 __ bind(&done);
4379 } else { 4379 } else {
4380 ArrayNArgumentsConstructorStub stub(kind, context_mode, override_mode); 4380 ArrayNArgumentsConstructorStub stub(kind, context_mode, override_mode);
4381 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); 4381 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
4382 } 4382 }
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
4659 instr->additional_index()); 4659 instr->additional_index());
4660 4660
4661 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { 4661 if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
4662 CpuFeatureScope scope(masm(), SSE2); 4662 CpuFeatureScope scope(masm(), SSE2);
4663 XMMRegister value = ToDoubleRegister(instr->value()); 4663 XMMRegister value = ToDoubleRegister(instr->value());
4664 4664
4665 if (instr->NeedsCanonicalization()) { 4665 if (instr->NeedsCanonicalization()) {
4666 Label have_value; 4666 Label have_value;
4667 4667
4668 __ ucomisd(value, value); 4668 __ ucomisd(value, value);
4669 __ j(parity_odd, &have_value); // NaN. 4669 __ j(parity_odd, &have_value, Label::kNear); // NaN.
4670 4670
4671 __ movsd(value, Operand::StaticVariable(canonical_nan_reference)); 4671 __ movsd(value, Operand::StaticVariable(canonical_nan_reference));
4672 __ bind(&have_value); 4672 __ bind(&have_value);
4673 } 4673 }
4674 4674
4675 __ movsd(double_store_operand, value); 4675 __ movsd(double_store_operand, value);
4676 } else { 4676 } else {
4677 // Can't use SSE2 in the serializer 4677 // Can't use SSE2 in the serializer
4678 if (instr->hydrogen()->IsConstantHoleStore()) { 4678 if (instr->hydrogen()->IsConstantHoleStore()) {
4679 // This means we should store the (double) hole. No floating point 4679 // This means we should store the (double) hole. No floating point
(...skipping 15 matching lines...) Expand all
4695 } else { 4695 } else {
4696 Label no_special_nan_handling; 4696 Label no_special_nan_handling;
4697 X87Register value = ToX87Register(instr->value()); 4697 X87Register value = ToX87Register(instr->value());
4698 X87Fxch(value); 4698 X87Fxch(value);
4699 4699
4700 if (instr->NeedsCanonicalization()) { 4700 if (instr->NeedsCanonicalization()) {
4701 __ fld(0); 4701 __ fld(0);
4702 __ fld(0); 4702 __ fld(0);
4703 __ FCmp(); 4703 __ FCmp();
4704 4704
4705 __ j(parity_odd, &no_special_nan_handling); 4705 __ j(parity_odd, &no_special_nan_handling, Label::kNear);
4706 __ sub(esp, Immediate(kDoubleSize)); 4706 __ sub(esp, Immediate(kDoubleSize));
4707 __ fst_d(MemOperand(esp, 0)); 4707 __ fst_d(MemOperand(esp, 0));
4708 __ cmp(MemOperand(esp, sizeof(kHoleNanLower32)), 4708 __ cmp(MemOperand(esp, sizeof(kHoleNanLower32)),
4709 Immediate(kHoleNanUpper32)); 4709 Immediate(kHoleNanUpper32));
4710 __ add(esp, Immediate(kDoubleSize)); 4710 __ add(esp, Immediate(kDoubleSize));
4711 Label canonicalize; 4711 Label canonicalize;
4712 __ j(not_equal, &canonicalize); 4712 __ j(not_equal, &canonicalize, Label::kNear);
4713 __ jmp(&no_special_nan_handling); 4713 __ jmp(&no_special_nan_handling, Label::kNear);
4714 __ bind(&canonicalize); 4714 __ bind(&canonicalize);
4715 __ fstp(0); 4715 __ fstp(0);
4716 __ fld_d(Operand::StaticVariable(canonical_nan_reference)); 4716 __ fld_d(Operand::StaticVariable(canonical_nan_reference));
4717 } 4717 }
4718 4718
4719 __ bind(&no_special_nan_handling); 4719 __ bind(&no_special_nan_handling);
4720 __ fst_d(double_store_operand); 4720 __ fst_d(double_store_operand);
4721 } 4721 }
4722 } 4722 }
4723 } 4723 }
(...skipping 948 matching lines...) Expand 10 before | Expand all | Expand 10 after
5672 DeferredCheckMaps* deferred = NULL; 5672 DeferredCheckMaps* deferred = NULL;
5673 if (instr->hydrogen()->has_migration_target()) { 5673 if (instr->hydrogen()->has_migration_target()) {
5674 deferred = new(zone()) DeferredCheckMaps(this, instr, reg, x87_stack_); 5674 deferred = new(zone()) DeferredCheckMaps(this, instr, reg, x87_stack_);
5675 __ bind(deferred->check_maps()); 5675 __ bind(deferred->check_maps());
5676 } 5676 }
5677 5677
5678 UniqueSet<Map> map_set = instr->hydrogen()->map_set(); 5678 UniqueSet<Map> map_set = instr->hydrogen()->map_set();
5679 Label success; 5679 Label success;
5680 for (int i = 0; i < map_set.size() - 1; i++) { 5680 for (int i = 0; i < map_set.size() - 1; i++) {
5681 Handle<Map> map = map_set.at(i).handle(); 5681 Handle<Map> map = map_set.at(i).handle();
5682 __ CompareMap(reg, map, &success); 5682 __ CompareMap(reg, map);
5683 __ j(equal, &success); 5683 __ j(equal, &success, Label::kNear);
5684 } 5684 }
5685 5685
5686 Handle<Map> map = map_set.at(map_set.size() - 1).handle(); 5686 Handle<Map> map = map_set.at(map_set.size() - 1).handle();
5687 __ CompareMap(reg, map, &success); 5687 __ CompareMap(reg, map);
5688 if (instr->hydrogen()->has_migration_target()) { 5688 if (instr->hydrogen()->has_migration_target()) {
5689 __ j(not_equal, deferred->entry()); 5689 __ j(not_equal, deferred->entry());
5690 } else { 5690 } else {
5691 DeoptimizeIf(not_equal, instr->environment()); 5691 DeoptimizeIf(not_equal, instr->environment());
5692 } 5692 }
5693 5693
5694 __ bind(&success); 5694 __ bind(&success);
5695 } 5695 }
5696 5696
5697 5697
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
5755 Register scratch2 = ToRegister(instr->scratch2()); 5755 Register scratch2 = ToRegister(instr->scratch2());
5756 Register scratch3 = ToRegister(instr->scratch3()); 5756 Register scratch3 = ToRegister(instr->scratch3());
5757 Label is_smi, done, heap_number, valid_exponent, 5757 Label is_smi, done, heap_number, valid_exponent,
5758 largest_value, zero_result, maybe_nan_or_infinity; 5758 largest_value, zero_result, maybe_nan_or_infinity;
5759 5759
5760 __ JumpIfSmi(input_reg, &is_smi); 5760 __ JumpIfSmi(input_reg, &is_smi);
5761 5761
5762 // Check for heap number 5762 // Check for heap number
5763 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 5763 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5764 factory()->heap_number_map()); 5764 factory()->heap_number_map());
5765 __ j(equal, &heap_number, Label::kFar); 5765 __ j(equal, &heap_number, Label::kNear);
5766 5766
5767 // Check for undefined. Undefined is converted to zero for clamping 5767 // Check for undefined. Undefined is converted to zero for clamping
5768 // conversions. 5768 // conversions.
5769 __ cmp(input_reg, factory()->undefined_value()); 5769 __ cmp(input_reg, factory()->undefined_value());
5770 DeoptimizeIf(not_equal, instr->environment()); 5770 DeoptimizeIf(not_equal, instr->environment());
5771 __ jmp(&zero_result); 5771 __ jmp(&zero_result, Label::kNear);
5772 5772
5773 // Heap number 5773 // Heap number
5774 __ bind(&heap_number); 5774 __ bind(&heap_number);
5775 5775
5776 // Surprisingly, all of the hand-crafted bit-manipulations below are much 5776 // Surprisingly, all of the hand-crafted bit-manipulations below are much
5777 // faster than the x86 FPU built-in instruction, especially since "banker's 5777 // faster than the x86 FPU built-in instruction, especially since "banker's
5778 // rounding" would be additionally very expensive 5778 // rounding" would be additionally very expensive
5779 5779
5780 // Get exponent word. 5780 // Get exponent word.
5781 __ mov(scratch, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 5781 __ mov(scratch, FieldOperand(input_reg, HeapNumber::kExponentOffset));
5782 __ mov(scratch3, FieldOperand(input_reg, HeapNumber::kMantissaOffset)); 5782 __ mov(scratch3, FieldOperand(input_reg, HeapNumber::kMantissaOffset));
5783 5783
5784 // Test for negative values --> clamp to zero 5784 // Test for negative values --> clamp to zero
5785 __ test(scratch, scratch); 5785 __ test(scratch, scratch);
5786 __ j(negative, &zero_result); 5786 __ j(negative, &zero_result, Label::kNear);
5787 5787
5788 // Get exponent alone in scratch2. 5788 // Get exponent alone in scratch2.
5789 __ mov(scratch2, scratch); 5789 __ mov(scratch2, scratch);
5790 __ and_(scratch2, HeapNumber::kExponentMask); 5790 __ and_(scratch2, HeapNumber::kExponentMask);
5791 __ shr(scratch2, HeapNumber::kExponentShift); 5791 __ shr(scratch2, HeapNumber::kExponentShift);
5792 __ j(zero, &zero_result); 5792 __ j(zero, &zero_result, Label::kNear);
5793 __ sub(scratch2, Immediate(HeapNumber::kExponentBias - 1)); 5793 __ sub(scratch2, Immediate(HeapNumber::kExponentBias - 1));
5794 __ j(negative, &zero_result); 5794 __ j(negative, &zero_result, Label::kNear);
5795 5795
5796 const uint32_t non_int8_exponent = 7; 5796 const uint32_t non_int8_exponent = 7;
5797 __ cmp(scratch2, Immediate(non_int8_exponent + 1)); 5797 __ cmp(scratch2, Immediate(non_int8_exponent + 1));
5798 // If the exponent is too big, check for special values. 5798 // If the exponent is too big, check for special values.
5799 __ j(greater, &maybe_nan_or_infinity, Label::kNear); 5799 __ j(greater, &maybe_nan_or_infinity, Label::kNear);
5800 5800
5801 __ bind(&valid_exponent); 5801 __ bind(&valid_exponent);
5802 // Exponent word in scratch, exponent in scratch2. We know that 0 <= exponent 5802 // Exponent word in scratch, exponent in scratch2. We know that 0 <= exponent
5803 // < 7. The shift bias is the number of bits to shift the mantissa such that 5803 // < 7. The shift bias is the number of bits to shift the mantissa such that
5804 // with an exponent of 7 such the that top-most one is in bit 30, allowing 5804 // with an exponent of 7 such the that top-most one is in bit 30, allowing
(...skipping 10 matching lines...) Expand all
5815 __ shl_cl(scratch); 5815 __ shl_cl(scratch);
5816 // Use "banker's rounding" to spec: If fractional part of number is 0.5, then 5816 // Use "banker's rounding" to spec: If fractional part of number is 0.5, then
5817 // use the bit in the "ones" place and add it to the "halves" place, which has 5817 // use the bit in the "ones" place and add it to the "halves" place, which has
5818 // the effect of rounding to even. 5818 // the effect of rounding to even.
5819 __ mov(scratch2, scratch); 5819 __ mov(scratch2, scratch);
5820 const uint32_t one_half_bit_shift = 30 - sizeof(uint8_t) * 8; 5820 const uint32_t one_half_bit_shift = 30 - sizeof(uint8_t) * 8;
5821 const uint32_t one_bit_shift = one_half_bit_shift + 1; 5821 const uint32_t one_bit_shift = one_half_bit_shift + 1;
5822 __ and_(scratch2, Immediate((1 << one_bit_shift) - 1)); 5822 __ and_(scratch2, Immediate((1 << one_bit_shift) - 1));
5823 __ cmp(scratch2, Immediate(1 << one_half_bit_shift)); 5823 __ cmp(scratch2, Immediate(1 << one_half_bit_shift));
5824 Label no_round; 5824 Label no_round;
5825 __ j(less, &no_round); 5825 __ j(less, &no_round, Label::kNear);
5826 Label round_up; 5826 Label round_up;
5827 __ mov(scratch2, Immediate(1 << one_half_bit_shift)); 5827 __ mov(scratch2, Immediate(1 << one_half_bit_shift));
5828 __ j(greater, &round_up); 5828 __ j(greater, &round_up, Label::kNear);
5829 __ test(scratch3, scratch3); 5829 __ test(scratch3, scratch3);
5830 __ j(not_zero, &round_up); 5830 __ j(not_zero, &round_up, Label::kNear);
5831 __ mov(scratch2, scratch); 5831 __ mov(scratch2, scratch);
5832 __ and_(scratch2, Immediate(1 << one_bit_shift)); 5832 __ and_(scratch2, Immediate(1 << one_bit_shift));
5833 __ shr(scratch2, 1); 5833 __ shr(scratch2, 1);
5834 __ bind(&round_up); 5834 __ bind(&round_up);
5835 __ add(scratch, scratch2); 5835 __ add(scratch, scratch2);
5836 __ j(overflow, &largest_value); 5836 __ j(overflow, &largest_value, Label::kNear);
5837 __ bind(&no_round); 5837 __ bind(&no_round);
5838 __ shr(scratch, 23); 5838 __ shr(scratch, 23);
5839 __ mov(result_reg, scratch); 5839 __ mov(result_reg, scratch);
5840 __ jmp(&done, Label::kNear); 5840 __ jmp(&done, Label::kNear);
5841 5841
5842 __ bind(&maybe_nan_or_infinity); 5842 __ bind(&maybe_nan_or_infinity);
5843 // Check for NaN/Infinity, all other values map to 255 5843 // Check for NaN/Infinity, all other values map to 255
5844 __ cmp(scratch2, Immediate(HeapNumber::kInfinityOrNanExponent + 1)); 5844 __ cmp(scratch2, Immediate(HeapNumber::kInfinityOrNanExponent + 1));
5845 __ j(not_equal, &largest_value, Label::kNear); 5845 __ j(not_equal, &largest_value, Label::kNear);
5846 5846
5847 // Check for NaN, which differs from Infinity in that at least one mantissa 5847 // Check for NaN, which differs from Infinity in that at least one mantissa
5848 // bit is set. 5848 // bit is set.
5849 __ and_(scratch, HeapNumber::kMantissaMask); 5849 __ and_(scratch, HeapNumber::kMantissaMask);
5850 __ or_(scratch, FieldOperand(input_reg, HeapNumber::kMantissaOffset)); 5850 __ or_(scratch, FieldOperand(input_reg, HeapNumber::kMantissaOffset));
5851 __ j(not_zero, &zero_result); // M!=0 --> NaN 5851 __ j(not_zero, &zero_result, Label::kNear); // M!=0 --> NaN
5852 // Infinity -> Fall through to map to 255. 5852 // Infinity -> Fall through to map to 255.
5853 5853
5854 __ bind(&largest_value); 5854 __ bind(&largest_value);
5855 __ mov(result_reg, Immediate(255)); 5855 __ mov(result_reg, Immediate(255));
5856 __ jmp(&done, Label::kNear); 5856 __ jmp(&done, Label::kNear);
5857 5857
5858 __ bind(&zero_result); 5858 __ bind(&zero_result);
5859 __ xor_(result_reg, result_reg); 5859 __ xor_(result_reg, result_reg);
5860 __ jmp(&done); 5860 __ jmp(&done, Label::kNear);
5861 5861
5862 // smi 5862 // smi
5863 __ bind(&is_smi); 5863 __ bind(&is_smi);
5864 if (!input_reg.is(result_reg)) { 5864 if (!input_reg.is(result_reg)) {
5865 __ mov(result_reg, input_reg); 5865 __ mov(result_reg, input_reg);
5866 } 5866 }
5867 __ SmiUntag(result_reg); 5867 __ SmiUntag(result_reg);
5868 __ ClampUint8(result_reg); 5868 __ ClampUint8(result_reg);
5869 __ bind(&done); 5869 __ bind(&done);
5870 } 5870 }
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
5998 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); 5998 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index())));
5999 __ push(Immediate(instr->hydrogen()->pattern())); 5999 __ push(Immediate(instr->hydrogen()->pattern()));
6000 __ push(Immediate(instr->hydrogen()->flags())); 6000 __ push(Immediate(instr->hydrogen()->flags()));
6001 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); 6001 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr);
6002 __ mov(ebx, eax); 6002 __ mov(ebx, eax);
6003 6003
6004 __ bind(&materialized); 6004 __ bind(&materialized);
6005 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; 6005 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
6006 Label allocated, runtime_allocate; 6006 Label allocated, runtime_allocate;
6007 __ Allocate(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT); 6007 __ Allocate(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT);
6008 __ jmp(&allocated); 6008 __ jmp(&allocated, Label::kNear);
6009 6009
6010 __ bind(&runtime_allocate); 6010 __ bind(&runtime_allocate);
6011 __ push(ebx); 6011 __ push(ebx);
6012 __ push(Immediate(Smi::FromInt(size))); 6012 __ push(Immediate(Smi::FromInt(size)));
6013 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); 6013 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr);
6014 __ pop(ebx); 6014 __ pop(ebx);
6015 6015
6016 __ bind(&allocated); 6016 __ bind(&allocated);
6017 // Copy the content into the newly allocated memory. 6017 // Copy the content into the newly allocated memory.
6018 // (Unroll copy loop once for better throughput). 6018 // (Unroll copy loop once for better throughput).
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
6324 __ bind(&use_cache); 6324 __ bind(&use_cache);
6325 } 6325 }
6326 6326
6327 6327
6328 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { 6328 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
6329 Register map = ToRegister(instr->map()); 6329 Register map = ToRegister(instr->map());
6330 Register result = ToRegister(instr->result()); 6330 Register result = ToRegister(instr->result());
6331 Label load_cache, done; 6331 Label load_cache, done;
6332 __ EnumLength(result, map); 6332 __ EnumLength(result, map);
6333 __ cmp(result, Immediate(Smi::FromInt(0))); 6333 __ cmp(result, Immediate(Smi::FromInt(0)));
6334 __ j(not_equal, &load_cache); 6334 __ j(not_equal, &load_cache, Label::kNear);
6335 __ mov(result, isolate()->factory()->empty_fixed_array()); 6335 __ mov(result, isolate()->factory()->empty_fixed_array());
6336 __ jmp(&done); 6336 __ jmp(&done, Label::kNear);
6337 6337
6338 __ bind(&load_cache); 6338 __ bind(&load_cache);
6339 __ LoadInstanceDescriptors(map, result); 6339 __ LoadInstanceDescriptors(map, result);
6340 __ mov(result, 6340 __ mov(result,
6341 FieldOperand(result, DescriptorArray::kEnumCacheOffset)); 6341 FieldOperand(result, DescriptorArray::kEnumCacheOffset));
6342 __ mov(result, 6342 __ mov(result,
6343 FieldOperand(result, FixedArray::SizeFor(instr->idx()))); 6343 FieldOperand(result, FixedArray::SizeFor(instr->idx())));
6344 __ bind(&done); 6344 __ bind(&done);
6345 __ test(result, result); 6345 __ test(result, result);
6346 DeoptimizeIf(equal, instr->environment()); 6346 DeoptimizeIf(equal, instr->environment());
6347 } 6347 }
6348 6348
6349 6349
6350 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { 6350 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
6351 Register object = ToRegister(instr->value()); 6351 Register object = ToRegister(instr->value());
6352 __ cmp(ToRegister(instr->map()), 6352 __ cmp(ToRegister(instr->map()),
6353 FieldOperand(object, HeapObject::kMapOffset)); 6353 FieldOperand(object, HeapObject::kMapOffset));
6354 DeoptimizeIf(not_equal, instr->environment()); 6354 DeoptimizeIf(not_equal, instr->environment());
6355 } 6355 }
6356 6356
6357 6357
6358 void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) { 6358 void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) {
6359 Register object = ToRegister(instr->object()); 6359 Register object = ToRegister(instr->object());
6360 Register index = ToRegister(instr->index()); 6360 Register index = ToRegister(instr->index());
6361 6361
6362 Label out_of_object, done; 6362 Label out_of_object, done;
6363 __ cmp(index, Immediate(0)); 6363 __ cmp(index, Immediate(0));
6364 __ j(less, &out_of_object); 6364 __ j(less, &out_of_object, Label::kNear);
6365 __ mov(object, FieldOperand(object, 6365 __ mov(object, FieldOperand(object,
6366 index, 6366 index,
6367 times_half_pointer_size, 6367 times_half_pointer_size,
6368 JSObject::kHeaderSize)); 6368 JSObject::kHeaderSize));
6369 __ jmp(&done, Label::kNear); 6369 __ jmp(&done, Label::kNear);
6370 6370
6371 __ bind(&out_of_object); 6371 __ bind(&out_of_object);
6372 __ mov(object, FieldOperand(object, JSObject::kPropertiesOffset)); 6372 __ mov(object, FieldOperand(object, JSObject::kPropertiesOffset));
6373 __ neg(index); 6373 __ neg(index);
6374 // Index is now equal to out of object property index plus 1. 6374 // Index is now equal to out of object property index plus 1.
6375 __ mov(object, FieldOperand(object, 6375 __ mov(object, FieldOperand(object,
6376 index, 6376 index,
6377 times_half_pointer_size, 6377 times_half_pointer_size,
6378 FixedArray::kHeaderSize - kPointerSize)); 6378 FixedArray::kHeaderSize - kPointerSize));
6379 __ bind(&done); 6379 __ bind(&done);
6380 } 6380 }
6381 6381
6382 6382
6383 #undef __ 6383 #undef __
6384 6384
6385 } } // namespace v8::internal 6385 } } // namespace v8::internal
6386 6386
6387 #endif // V8_TARGET_ARCH_IA32 6387 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « no previous file | src/ia32/macro-assembler-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698