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

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

Issue 132373011: A64: Synchronize with r17635. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 months 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 | Annotate | Revision Log
« no previous file with comments | « src/ia32/lithium-codegen-ia32.h ('k') | src/ia32/lithium-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 1025 matching lines...) Expand 10 before | Expand all | Expand 10 after
1036 ASSERT(environment->HasBeenRegistered()); 1036 ASSERT(environment->HasBeenRegistered());
1037 int id = environment->deoptimization_index(); 1037 int id = environment->deoptimization_index();
1038 ASSERT(info()->IsOptimizing() || info()->IsStub()); 1038 ASSERT(info()->IsOptimizing() || info()->IsStub());
1039 Address entry = 1039 Address entry =
1040 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); 1040 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type);
1041 if (entry == NULL) { 1041 if (entry == NULL) {
1042 Abort(kBailoutWasNotPrepared); 1042 Abort(kBailoutWasNotPrepared);
1043 return; 1043 return;
1044 } 1044 }
1045 1045
1046 if (FLAG_deopt_every_n_times != 0 && !info()->IsStub()) { 1046 if (DeoptEveryNTimes()) {
1047 ExternalReference count = ExternalReference::stress_deopt_count(isolate()); 1047 ExternalReference count = ExternalReference::stress_deopt_count(isolate());
1048 Label no_deopt; 1048 Label no_deopt;
1049 __ pushfd(); 1049 __ pushfd();
1050 __ push(eax); 1050 __ push(eax);
1051 __ mov(eax, Operand::StaticVariable(count)); 1051 __ mov(eax, Operand::StaticVariable(count));
1052 __ sub(eax, Immediate(1)); 1052 __ sub(eax, Immediate(1));
1053 __ j(not_zero, &no_deopt, Label::kNear); 1053 __ j(not_zero, &no_deopt, Label::kNear);
1054 if (FLAG_trap_on_deopt) __ int3(); 1054 if (FLAG_trap_on_deopt) __ int3();
1055 __ mov(eax, Immediate(FLAG_deopt_every_n_times)); 1055 __ mov(eax, Immediate(FLAG_deopt_every_n_times));
1056 __ mov(Operand::StaticVariable(count), eax); 1056 __ mov(Operand::StaticVariable(count), eax);
(...skipping 983 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 10 matching lines...) Expand all
2071 STATIC_ASSERT(kCharSize == 1); 2071 STATIC_ASSERT(kCharSize == 1);
2072 return FieldOperand(string, SeqString::kHeaderSize + offset); 2072 return FieldOperand(string, SeqString::kHeaderSize + offset);
2073 } 2073 }
2074 return FieldOperand( 2074 return FieldOperand(
2075 string, ToRegister(index), 2075 string, ToRegister(index),
2076 encoding == String::ONE_BYTE_ENCODING ? times_1 : times_2, 2076 encoding == String::ONE_BYTE_ENCODING ? times_1 : times_2,
2077 SeqString::kHeaderSize); 2077 SeqString::kHeaderSize);
2078 } 2078 }
2079 2079
2080 2080
2081 void LCodeGen::DoSeqStringGetChar(LSeqStringGetChar* instr) {
2082 String::Encoding encoding = instr->hydrogen()->encoding();
2083 Register result = ToRegister(instr->result());
2084 Register string = ToRegister(instr->string());
2085
2086 if (FLAG_debug_code) {
2087 __ push(string);
2088 __ mov(string, FieldOperand(string, HeapObject::kMapOffset));
2089 __ movzx_b(string, FieldOperand(string, Map::kInstanceTypeOffset));
2090
2091 __ and_(string, Immediate(kStringRepresentationMask | kStringEncodingMask));
2092 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
2093 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
2094 __ cmp(string, Immediate(encoding == String::ONE_BYTE_ENCODING
2095 ? one_byte_seq_type : two_byte_seq_type));
2096 __ Check(equal, kUnexpectedStringType);
2097 __ pop(string);
2098 }
2099
2100 Operand operand = BuildSeqStringOperand(string, instr->index(), encoding);
2101 if (encoding == String::ONE_BYTE_ENCODING) {
2102 __ movzx_b(result, operand);
2103 } else {
2104 __ movzx_w(result, operand);
2105 }
2106 }
2107
2108
2081 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) { 2109 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
2082 String::Encoding encoding = instr->hydrogen()->encoding(); 2110 String::Encoding encoding = instr->hydrogen()->encoding();
2083 Register string = ToRegister(instr->string()); 2111 Register string = ToRegister(instr->string());
2084 2112
2085 if (FLAG_debug_code) { 2113 if (FLAG_debug_code) {
2086 __ push(string); 2114 __ push(string);
2087 __ mov(string, FieldOperand(string, HeapObject::kMapOffset)); 2115 __ mov(string, FieldOperand(string, HeapObject::kMapOffset));
2088 __ movzx_b(string, FieldOperand(string, Map::kInstanceTypeOffset)); 2116 __ movzx_b(string, FieldOperand(string, Map::kInstanceTypeOffset));
2089 2117
2090 __ and_(string, Immediate(kStringRepresentationMask | kStringEncodingMask)); 2118 __ and_(string, Immediate(kStringRepresentationMask | kStringEncodingMask));
(...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after
2612 __ ucomisd(input_reg, input_reg); 2640 __ ucomisd(input_reg, input_reg);
2613 EmitFalseBranch(instr, parity_odd); 2641 EmitFalseBranch(instr, parity_odd);
2614 } else { 2642 } else {
2615 // Put the value to the top of stack 2643 // Put the value to the top of stack
2616 X87Register src = ToX87Register(instr->object()); 2644 X87Register src = ToX87Register(instr->object());
2617 X87LoadForUsage(src); 2645 X87LoadForUsage(src);
2618 __ fld(0); 2646 __ fld(0);
2619 __ fld(0); 2647 __ fld(0);
2620 __ FCmp(); 2648 __ FCmp();
2621 Label ok; 2649 Label ok;
2622 __ j(parity_even, &ok); 2650 __ j(parity_even, &ok, Label::kNear);
2623 __ fstp(0); 2651 __ fstp(0);
2624 EmitFalseBranch(instr, no_condition); 2652 EmitFalseBranch(instr, no_condition);
2625 __ bind(&ok); 2653 __ bind(&ok);
2626 } 2654 }
2627 2655
2628 2656
2629 __ sub(esp, Immediate(kDoubleSize)); 2657 __ sub(esp, Immediate(kDoubleSize));
2630 if (use_sse2) { 2658 if (use_sse2) {
2631 CpuFeatureScope scope(masm(), SSE2); 2659 CpuFeatureScope scope(masm(), SSE2);
2632 XMMRegister input_reg = ToDoubleRegister(instr->object()); 2660 XMMRegister input_reg = ToDoubleRegister(instr->object());
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after
2936 }; 2964 };
2937 2965
2938 DeferredInstanceOfKnownGlobal* deferred; 2966 DeferredInstanceOfKnownGlobal* deferred;
2939 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr, x87_stack_); 2967 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr, x87_stack_);
2940 2968
2941 Label done, false_result; 2969 Label done, false_result;
2942 Register object = ToRegister(instr->value()); 2970 Register object = ToRegister(instr->value());
2943 Register temp = ToRegister(instr->temp()); 2971 Register temp = ToRegister(instr->temp());
2944 2972
2945 // A Smi is not an instance of anything. 2973 // A Smi is not an instance of anything.
2946 __ JumpIfSmi(object, &false_result); 2974 __ JumpIfSmi(object, &false_result, Label::kNear);
2947 2975
2948 // This is the inlined call site instanceof cache. The two occurences of the 2976 // This is the inlined call site instanceof cache. The two occurences of the
2949 // hole value will be patched to the last map/result pair generated by the 2977 // hole value will be patched to the last map/result pair generated by the
2950 // instanceof stub. 2978 // instanceof stub.
2951 Label cache_miss; 2979 Label cache_miss;
2952 Register map = ToRegister(instr->temp()); 2980 Register map = ToRegister(instr->temp());
2953 __ mov(map, FieldOperand(object, HeapObject::kMapOffset)); 2981 __ mov(map, FieldOperand(object, HeapObject::kMapOffset));
2954 __ bind(deferred->map_check()); // Label for calculating code patching. 2982 __ bind(deferred->map_check()); // Label for calculating code patching.
2955 Handle<Cell> cache_cell = factory()->NewCell(factory()->the_hole_value()); 2983 Handle<Cell> cache_cell = factory()->NewCell(factory()->the_hole_value());
2956 __ cmp(map, Operand::ForCell(cache_cell)); // Patched to cached map. 2984 __ cmp(map, Operand::ForCell(cache_cell)); // Patched to cached map.
2957 __ j(not_equal, &cache_miss, Label::kNear); 2985 __ j(not_equal, &cache_miss, Label::kNear);
2958 __ mov(eax, factory()->the_hole_value()); // Patched to either true or false. 2986 __ mov(eax, factory()->the_hole_value()); // Patched to either true or false.
2959 __ jmp(&done); 2987 __ jmp(&done, Label::kNear);
2960 2988
2961 // The inlined call site cache did not match. Check for null and string 2989 // The inlined call site cache did not match. Check for null and string
2962 // before calling the deferred code. 2990 // before calling the deferred code.
2963 __ bind(&cache_miss); 2991 __ bind(&cache_miss);
2964 // Null is not an instance of anything. 2992 // Null is not an instance of anything.
2965 __ cmp(object, factory()->null_value()); 2993 __ cmp(object, factory()->null_value());
2966 __ j(equal, &false_result); 2994 __ j(equal, &false_result, Label::kNear);
2967 2995
2968 // String values are not instances of anything. 2996 // String values are not instances of anything.
2969 Condition is_string = masm_->IsObjectStringType(object, temp, temp); 2997 Condition is_string = masm_->IsObjectStringType(object, temp, temp);
2970 __ j(is_string, &false_result); 2998 __ j(is_string, &false_result, Label::kNear);
2971 2999
2972 // Go to the deferred code. 3000 // Go to the deferred code.
2973 __ jmp(deferred->entry()); 3001 __ jmp(deferred->entry());
2974 3002
2975 __ bind(&false_result); 3003 __ bind(&false_result);
2976 __ mov(ToRegister(instr->result()), factory()->false_value()); 3004 __ mov(ToRegister(instr->result()), factory()->false_value());
2977 3005
2978 // Here result has either true or false. Deferred code also produces true or 3006 // Here result has either true or false. Deferred code also produces true or
2979 // false object. 3007 // false object.
2980 __ bind(deferred->exit()); 3008 __ bind(deferred->exit());
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
3105 } 3133 }
3106 int no_frame_start = -1; 3134 int no_frame_start = -1;
3107 if (NeedsEagerFrame()) { 3135 if (NeedsEagerFrame()) {
3108 __ mov(esp, ebp); 3136 __ mov(esp, ebp);
3109 __ pop(ebp); 3137 __ pop(ebp);
3110 no_frame_start = masm_->pc_offset(); 3138 no_frame_start = masm_->pc_offset();
3111 } 3139 }
3112 if (dynamic_frame_alignment_) { 3140 if (dynamic_frame_alignment_) {
3113 Label no_padding; 3141 Label no_padding;
3114 __ cmp(edx, Immediate(kNoAlignmentPadding)); 3142 __ cmp(edx, Immediate(kNoAlignmentPadding));
3115 __ j(equal, &no_padding); 3143 __ j(equal, &no_padding, Label::kNear);
3116 3144
3117 EmitReturn(instr, true); 3145 EmitReturn(instr, true);
3118 __ bind(&no_padding); 3146 __ bind(&no_padding);
3119 } 3147 }
3120 3148
3121 EmitReturn(instr, false); 3149 EmitReturn(instr, false);
3122 if (no_frame_start != -1) { 3150 if (no_frame_start != -1) {
3123 info()->AddNoFrameRange(no_frame_start, masm_->pc_offset()); 3151 info()->AddNoFrameRange(no_frame_start, masm_->pc_offset());
3124 } 3152 }
3125 } 3153 }
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
3238 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { 3266 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
3239 HObjectAccess access = instr->hydrogen()->access(); 3267 HObjectAccess access = instr->hydrogen()->access();
3240 int offset = access.offset(); 3268 int offset = access.offset();
3241 3269
3242 if (access.IsExternalMemory()) { 3270 if (access.IsExternalMemory()) {
3243 Register result = ToRegister(instr->result()); 3271 Register result = ToRegister(instr->result());
3244 MemOperand operand = instr->object()->IsConstantOperand() 3272 MemOperand operand = instr->object()->IsConstantOperand()
3245 ? MemOperand::StaticVariable(ToExternalReference( 3273 ? MemOperand::StaticVariable(ToExternalReference(
3246 LConstantOperand::cast(instr->object()))) 3274 LConstantOperand::cast(instr->object())))
3247 : MemOperand(ToRegister(instr->object()), offset); 3275 : MemOperand(ToRegister(instr->object()), offset);
3248 if (access.representation().IsByte()) { 3276 __ Load(result, operand, access.representation());
3249 ASSERT(instr->hydrogen()->representation().IsInteger32());
3250 __ movzx_b(result, operand);
3251 } else {
3252 __ mov(result, operand);
3253 }
3254 return; 3277 return;
3255 } 3278 }
3256 3279
3257 Register object = ToRegister(instr->object()); 3280 Register object = ToRegister(instr->object());
3258 if (FLAG_track_double_fields && 3281 if (FLAG_track_double_fields &&
3259 instr->hydrogen()->representation().IsDouble()) { 3282 instr->hydrogen()->representation().IsDouble()) {
3260 if (CpuFeatures::IsSupported(SSE2)) { 3283 if (CpuFeatures::IsSupported(SSE2)) {
3261 CpuFeatureScope scope(masm(), SSE2); 3284 CpuFeatureScope scope(masm(), SSE2);
3262 XMMRegister result = ToDoubleRegister(instr->result()); 3285 XMMRegister result = ToDoubleRegister(instr->result());
3263 __ movsd(result, FieldOperand(object, offset)); 3286 __ movsd(result, FieldOperand(object, offset));
3264 } else { 3287 } else {
3265 X87Mov(ToX87Register(instr->result()), FieldOperand(object, offset)); 3288 X87Mov(ToX87Register(instr->result()), FieldOperand(object, offset));
3266 } 3289 }
3267 return; 3290 return;
3268 } 3291 }
3269 3292
3270 Register result = ToRegister(instr->result()); 3293 Register result = ToRegister(instr->result());
3271 if (!access.IsInobject()) { 3294 if (!access.IsInobject()) {
3272 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset)); 3295 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset));
3273 object = result; 3296 object = result;
3274 } 3297 }
3275 if (access.representation().IsByte()) { 3298 __ Load(result, FieldOperand(object, offset), access.representation());
3276 ASSERT(instr->hydrogen()->representation().IsInteger32());
3277 __ movzx_b(result, FieldOperand(object, offset));
3278 } else {
3279 __ mov(result, FieldOperand(object, offset));
3280 }
3281 } 3299 }
3282 3300
3283 3301
3284 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { 3302 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) {
3285 ASSERT(!operand->IsDoubleRegister()); 3303 ASSERT(!operand->IsDoubleRegister());
3286 if (operand->IsConstantOperand()) { 3304 if (operand->IsConstantOperand()) {
3287 Handle<Object> object = ToHandle(LConstantOperand::cast(operand)); 3305 Handle<Object> object = ToHandle(LConstantOperand::cast(operand));
3288 AllowDeferredHandleDereference smi_check; 3306 AllowDeferredHandleDereference smi_check;
3289 if (object->IsSmi()) { 3307 if (object->IsSmi()) {
3290 __ Push(Handle<Smi>::cast(object)); 3308 __ Push(Handle<Smi>::cast(object));
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after
3623 3641
3624 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { 3642 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
3625 Register receiver = ToRegister(instr->receiver()); 3643 Register receiver = ToRegister(instr->receiver());
3626 Register function = ToRegister(instr->function()); 3644 Register function = ToRegister(instr->function());
3627 Register scratch = ToRegister(instr->temp()); 3645 Register scratch = ToRegister(instr->temp());
3628 3646
3629 // If the receiver is null or undefined, we have to pass the global 3647 // If the receiver is null or undefined, we have to pass the global
3630 // object as a receiver to normal functions. Values have to be 3648 // object as a receiver to normal functions. Values have to be
3631 // passed unchanged to builtins and strict-mode functions. 3649 // passed unchanged to builtins and strict-mode functions.
3632 Label global_object, receiver_ok; 3650 Label global_object, receiver_ok;
3651 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
3633 3652
3634 // Do not transform the receiver to object for strict mode 3653 // Do not transform the receiver to object for strict mode
3635 // functions. 3654 // functions.
3636 __ mov(scratch, 3655 __ mov(scratch,
3637 FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); 3656 FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
3638 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset), 3657 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset),
3639 1 << SharedFunctionInfo::kStrictModeBitWithinByte); 3658 1 << SharedFunctionInfo::kStrictModeBitWithinByte);
3640 __ j(not_equal, &receiver_ok); // A near jump is not sufficient here! 3659 __ j(not_equal, &receiver_ok, dist);
3641 3660
3642 // Do not transform the receiver to object for builtins. 3661 // Do not transform the receiver to object for builtins.
3643 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kNativeByteOffset), 3662 __ test_b(FieldOperand(scratch, SharedFunctionInfo::kNativeByteOffset),
3644 1 << SharedFunctionInfo::kNativeBitWithinByte); 3663 1 << SharedFunctionInfo::kNativeBitWithinByte);
3645 __ j(not_equal, &receiver_ok); 3664 __ j(not_equal, &receiver_ok, dist);
3646 3665
3647 // Normal function. Replace undefined or null with global receiver. 3666 // Normal function. Replace undefined or null with global receiver.
3648 __ cmp(receiver, factory()->null_value()); 3667 __ cmp(receiver, factory()->null_value());
3649 __ j(equal, &global_object, Label::kNear); 3668 __ j(equal, &global_object, Label::kNear);
3650 __ cmp(receiver, factory()->undefined_value()); 3669 __ cmp(receiver, factory()->undefined_value());
3651 __ j(equal, &global_object, Label::kNear); 3670 __ j(equal, &global_object, Label::kNear);
3652 3671
3653 // The receiver should be a JS object. 3672 // The receiver should be a JS object.
3654 __ test(receiver, Immediate(kSmiTagMask)); 3673 __ test(receiver, Immediate(kSmiTagMask));
3655 DeoptimizeIf(equal, instr->environment()); 3674 DeoptimizeIf(equal, instr->environment());
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
3844 3863
3845 // Preserve the value of all registers. 3864 // Preserve the value of all registers.
3846 PushSafepointRegistersScope scope(this); 3865 PushSafepointRegistersScope scope(this);
3847 3866
3848 __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 3867 __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset));
3849 // Check the sign of the argument. If the argument is positive, just 3868 // Check the sign of the argument. If the argument is positive, just
3850 // return it. We do not need to patch the stack since |input| and 3869 // return it. We do not need to patch the stack since |input| and
3851 // |result| are the same register and |input| will be restored 3870 // |result| are the same register and |input| will be restored
3852 // unchanged by popping safepoint registers. 3871 // unchanged by popping safepoint registers.
3853 __ test(tmp, Immediate(HeapNumber::kSignMask)); 3872 __ test(tmp, Immediate(HeapNumber::kSignMask));
3854 __ j(zero, &done); 3873 __ j(zero, &done, Label::kNear);
3855 3874
3856 __ AllocateHeapNumber(tmp, tmp2, no_reg, &slow); 3875 __ AllocateHeapNumber(tmp, tmp2, no_reg, &slow);
3857 __ jmp(&allocated, Label::kNear); 3876 __ jmp(&allocated, Label::kNear);
3858 3877
3859 // Slow case: Call the runtime system to do the number allocation. 3878 // Slow case: Call the runtime system to do the number allocation.
3860 __ bind(&slow); 3879 __ bind(&slow);
3861 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, 3880 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0,
3862 instr, instr->context()); 3881 instr, instr->context());
3863 // Set the pointer to the new heap number in tmp. 3882 // Set the pointer to the new heap number in tmp.
3864 if (!tmp.is(eax)) __ mov(tmp, eax); 3883 if (!tmp.is(eax)) __ mov(tmp, eax);
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
3998 CpuFeatureScope scope(masm(), SSE2); 4017 CpuFeatureScope scope(masm(), SSE2);
3999 Register output_reg = ToRegister(instr->result()); 4018 Register output_reg = ToRegister(instr->result());
4000 XMMRegister input_reg = ToDoubleRegister(instr->value()); 4019 XMMRegister input_reg = ToDoubleRegister(instr->value());
4001 XMMRegister xmm_scratch = double_scratch0(); 4020 XMMRegister xmm_scratch = double_scratch0();
4002 XMMRegister input_temp = ToDoubleRegister(instr->temp()); 4021 XMMRegister input_temp = ToDoubleRegister(instr->temp());
4003 ExternalReference one_half = ExternalReference::address_of_one_half(); 4022 ExternalReference one_half = ExternalReference::address_of_one_half();
4004 ExternalReference minus_one_half = 4023 ExternalReference minus_one_half =
4005 ExternalReference::address_of_minus_one_half(); 4024 ExternalReference::address_of_minus_one_half();
4006 4025
4007 Label done, round_to_zero, below_one_half, do_not_compensate; 4026 Label done, round_to_zero, below_one_half, do_not_compensate;
4027 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
4028
4008 __ movsd(xmm_scratch, Operand::StaticVariable(one_half)); 4029 __ movsd(xmm_scratch, Operand::StaticVariable(one_half));
4009 __ ucomisd(xmm_scratch, input_reg); 4030 __ ucomisd(xmm_scratch, input_reg);
4010 __ j(above, &below_one_half); 4031 __ j(above, &below_one_half, Label::kNear);
4011 4032
4012 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). 4033 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x).
4013 __ addsd(xmm_scratch, input_reg); 4034 __ addsd(xmm_scratch, input_reg);
4014 __ cvttsd2si(output_reg, Operand(xmm_scratch)); 4035 __ cvttsd2si(output_reg, Operand(xmm_scratch));
4015 // Overflow is signalled with minint. 4036 // Overflow is signalled with minint.
4016 __ cmp(output_reg, 0x80000000u); 4037 __ cmp(output_reg, 0x80000000u);
4017 __ RecordComment("D2I conversion overflow"); 4038 __ RecordComment("D2I conversion overflow");
4018 DeoptimizeIf(equal, instr->environment()); 4039 DeoptimizeIf(equal, instr->environment());
4019 __ jmp(&done); 4040 __ jmp(&done, dist);
4020 4041
4021 __ bind(&below_one_half); 4042 __ bind(&below_one_half);
4022 __ movsd(xmm_scratch, Operand::StaticVariable(minus_one_half)); 4043 __ movsd(xmm_scratch, Operand::StaticVariable(minus_one_half));
4023 __ ucomisd(xmm_scratch, input_reg); 4044 __ ucomisd(xmm_scratch, input_reg);
4024 __ j(below_equal, &round_to_zero); 4045 __ j(below_equal, &round_to_zero, Label::kNear);
4025 4046
4026 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then 4047 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then
4027 // compare and compensate. 4048 // compare and compensate.
4028 __ movaps(input_temp, input_reg); // Do not alter input_reg. 4049 __ movaps(input_temp, input_reg); // Do not alter input_reg.
4029 __ subsd(input_temp, xmm_scratch); 4050 __ subsd(input_temp, xmm_scratch);
4030 __ cvttsd2si(output_reg, Operand(input_temp)); 4051 __ cvttsd2si(output_reg, Operand(input_temp));
4031 // Catch minint due to overflow, and to prevent overflow when compensating. 4052 // Catch minint due to overflow, and to prevent overflow when compensating.
4032 __ cmp(output_reg, 0x80000000u); 4053 __ cmp(output_reg, 0x80000000u);
4033 __ RecordComment("D2I conversion overflow"); 4054 __ RecordComment("D2I conversion overflow");
4034 DeoptimizeIf(equal, instr->environment()); 4055 DeoptimizeIf(equal, instr->environment());
4035 4056
4036 __ Cvtsi2sd(xmm_scratch, output_reg); 4057 __ Cvtsi2sd(xmm_scratch, output_reg);
4037 __ ucomisd(xmm_scratch, input_temp); 4058 __ ucomisd(xmm_scratch, input_temp);
4038 __ j(equal, &done); 4059 __ j(equal, &done, dist);
4039 __ sub(output_reg, Immediate(1)); 4060 __ sub(output_reg, Immediate(1));
4040 // No overflow because we already ruled out minint. 4061 // No overflow because we already ruled out minint.
4041 __ jmp(&done); 4062 __ jmp(&done, dist);
4042 4063
4043 __ bind(&round_to_zero); 4064 __ bind(&round_to_zero);
4044 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if 4065 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if
4045 // we can ignore the difference between a result of -0 and +0. 4066 // we can ignore the difference between a result of -0 and +0.
4046 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 4067 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
4047 // If the sign is positive, we return +0. 4068 // If the sign is positive, we return +0.
4048 __ movmskpd(output_reg, input_reg); 4069 __ movmskpd(output_reg, input_reg);
4049 __ test(output_reg, Immediate(1)); 4070 __ test(output_reg, Immediate(1));
4050 __ RecordComment("Minus zero"); 4071 __ RecordComment("Minus zero");
4051 DeoptimizeIf(not_zero, instr->environment()); 4072 DeoptimizeIf(not_zero, instr->environment());
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after
4386 ArrayNoArgumentConstructorStub stub(kind, context_mode, override_mode); 4407 ArrayNoArgumentConstructorStub stub(kind, context_mode, override_mode);
4387 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); 4408 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
4388 } else if (instr->arity() == 1) { 4409 } else if (instr->arity() == 1) {
4389 Label done; 4410 Label done;
4390 if (IsFastPackedElementsKind(kind)) { 4411 if (IsFastPackedElementsKind(kind)) {
4391 Label packed_case; 4412 Label packed_case;
4392 // We might need a change here 4413 // We might need a change here
4393 // look at the first argument 4414 // look at the first argument
4394 __ mov(ecx, Operand(esp, 0)); 4415 __ mov(ecx, Operand(esp, 0));
4395 __ test(ecx, ecx); 4416 __ test(ecx, ecx);
4396 __ j(zero, &packed_case); 4417 __ j(zero, &packed_case, Label::kNear);
4397 4418
4398 ElementsKind holey_kind = GetHoleyElementsKind(kind); 4419 ElementsKind holey_kind = GetHoleyElementsKind(kind);
4399 ArraySingleArgumentConstructorStub stub(holey_kind, context_mode, 4420 ArraySingleArgumentConstructorStub stub(holey_kind, context_mode,
4400 override_mode); 4421 override_mode);
4401 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); 4422 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
4402 __ jmp(&done); 4423 __ jmp(&done, Label::kNear);
4403 __ bind(&packed_case); 4424 __ bind(&packed_case);
4404 } 4425 }
4405 4426
4406 ArraySingleArgumentConstructorStub stub(kind, context_mode, override_mode); 4427 ArraySingleArgumentConstructorStub stub(kind, context_mode, override_mode);
4407 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); 4428 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
4408 __ bind(&done); 4429 __ bind(&done);
4409 } else { 4430 } else {
4410 ArrayNArgumentsConstructorStub stub(kind, context_mode, override_mode); 4431 ArrayNArgumentsConstructorStub stub(kind, context_mode, override_mode);
4411 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); 4432 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
4412 } 4433 }
4413 } 4434 }
4414 4435
4415 4436
4416 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { 4437 void LCodeGen::DoCallRuntime(LCallRuntime* instr) {
4438 ASSERT(ToRegister(instr->context()).is(esi));
4417 CallRuntime(instr->function(), instr->arity(), instr, instr->save_doubles()); 4439 CallRuntime(instr->function(), instr->arity(), instr, instr->save_doubles());
4418 } 4440 }
4419 4441
4420 4442
4421 void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) { 4443 void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) {
4422 Register function = ToRegister(instr->function()); 4444 Register function = ToRegister(instr->function());
4423 Register code_object = ToRegister(instr->code_object()); 4445 Register code_object = ToRegister(instr->code_object());
4424 __ lea(code_object, FieldOperand(code_object, Code::kHeaderSize)); 4446 __ lea(code_object, FieldOperand(code_object, Code::kHeaderSize));
4425 __ mov(FieldOperand(function, JSFunction::kCodeEntryOffset), code_object); 4447 __ mov(FieldOperand(function, JSFunction::kCodeEntryOffset), code_object);
4426 } 4448 }
(...skipping 12 matching lines...) Expand all
4439 HObjectAccess access = instr->hydrogen()->access(); 4461 HObjectAccess access = instr->hydrogen()->access();
4440 int offset = access.offset(); 4462 int offset = access.offset();
4441 4463
4442 if (access.IsExternalMemory()) { 4464 if (access.IsExternalMemory()) {
4443 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); 4465 ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
4444 MemOperand operand = instr->object()->IsConstantOperand() 4466 MemOperand operand = instr->object()->IsConstantOperand()
4445 ? MemOperand::StaticVariable( 4467 ? MemOperand::StaticVariable(
4446 ToExternalReference(LConstantOperand::cast(instr->object()))) 4468 ToExternalReference(LConstantOperand::cast(instr->object())))
4447 : MemOperand(ToRegister(instr->object()), offset); 4469 : MemOperand(ToRegister(instr->object()), offset);
4448 if (instr->value()->IsConstantOperand()) { 4470 if (instr->value()->IsConstantOperand()) {
4449 ASSERT(!representation.IsByte());
4450 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); 4471 LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
4451 __ mov(operand, Immediate(ToInteger32(operand_value))); 4472 __ mov(operand, Immediate(ToInteger32(operand_value)));
4452 } else { 4473 } else {
4453 Register value = ToRegister(instr->value()); 4474 Register value = ToRegister(instr->value());
4454 if (representation.IsByte()) { 4475 __ Store(value, operand, representation);
4455 __ mov_b(operand, value);
4456 } else {
4457 __ mov(operand, value);
4458 }
4459 } 4476 }
4460 return; 4477 return;
4461 } 4478 }
4462 4479
4463 Register object = ToRegister(instr->object()); 4480 Register object = ToRegister(instr->object());
4464 Handle<Map> transition = instr->transition(); 4481 Handle<Map> transition = instr->transition();
4465 4482
4466 if (FLAG_track_fields && representation.IsSmi()) { 4483 if (FLAG_track_fields && representation.IsSmi()) {
4467 if (instr->value()->IsConstantOperand()) { 4484 if (instr->value()->IsConstantOperand()) {
4468 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); 4485 LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
4526 if (!access.IsInobject()) { 4543 if (!access.IsInobject()) {
4527 write_register = ToRegister(instr->temp()); 4544 write_register = ToRegister(instr->temp());
4528 __ mov(write_register, FieldOperand(object, JSObject::kPropertiesOffset)); 4545 __ mov(write_register, FieldOperand(object, JSObject::kPropertiesOffset));
4529 } 4546 }
4530 4547
4531 MemOperand operand = FieldOperand(write_register, offset); 4548 MemOperand operand = FieldOperand(write_register, offset);
4532 if (instr->value()->IsConstantOperand()) { 4549 if (instr->value()->IsConstantOperand()) {
4533 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); 4550 LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
4534 if (operand_value->IsRegister()) { 4551 if (operand_value->IsRegister()) {
4535 Register value = ToRegister(operand_value); 4552 Register value = ToRegister(operand_value);
4536 if (representation.IsByte()) { 4553 __ Store(value, operand, representation);
4537 __ mov_b(operand, value); 4554 } else if (representation.IsInteger32()) {
4538 } else { 4555 Immediate immediate = ToImmediate(operand_value, representation);
4539 __ mov(operand, value); 4556 ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
4540 } 4557 __ mov(operand, immediate);
4541 } else { 4558 } else {
4542 Handle<Object> handle_value = ToHandle(operand_value); 4559 Handle<Object> handle_value = ToHandle(operand_value);
4543 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); 4560 ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
4544 __ mov(operand, handle_value); 4561 __ mov(operand, handle_value);
4545 } 4562 }
4546 } else { 4563 } else {
4547 Register value = ToRegister(instr->value()); 4564 Register value = ToRegister(instr->value());
4548 if (representation.IsByte()) { 4565 __ Store(value, operand, representation);
4549 __ mov_b(operand, value);
4550 } else {
4551 __ mov(operand, value);
4552 }
4553 } 4566 }
4554 4567
4555 if (instr->hydrogen()->NeedsWriteBarrier()) { 4568 if (instr->hydrogen()->NeedsWriteBarrier()) {
4556 Register value = ToRegister(instr->value()); 4569 Register value = ToRegister(instr->value());
4557 Register temp = access.IsInobject() ? ToRegister(instr->temp()) : object; 4570 Register temp = access.IsInobject() ? ToRegister(instr->temp()) : object;
4558 // Update the write barrier for the object for in-object properties. 4571 // Update the write barrier for the object for in-object properties.
4559 __ RecordWriteField(write_register, 4572 __ RecordWriteField(write_register,
4560 offset, 4573 offset,
4561 value, 4574 value,
4562 temp, 4575 temp,
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
4689 instr->additional_index()); 4702 instr->additional_index());
4690 4703
4691 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { 4704 if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
4692 CpuFeatureScope scope(masm(), SSE2); 4705 CpuFeatureScope scope(masm(), SSE2);
4693 XMMRegister value = ToDoubleRegister(instr->value()); 4706 XMMRegister value = ToDoubleRegister(instr->value());
4694 4707
4695 if (instr->NeedsCanonicalization()) { 4708 if (instr->NeedsCanonicalization()) {
4696 Label have_value; 4709 Label have_value;
4697 4710
4698 __ ucomisd(value, value); 4711 __ ucomisd(value, value);
4699 __ j(parity_odd, &have_value); // NaN. 4712 __ j(parity_odd, &have_value, Label::kNear); // NaN.
4700 4713
4701 __ movsd(value, Operand::StaticVariable(canonical_nan_reference)); 4714 __ movsd(value, Operand::StaticVariable(canonical_nan_reference));
4702 __ bind(&have_value); 4715 __ bind(&have_value);
4703 } 4716 }
4704 4717
4705 __ movsd(double_store_operand, value); 4718 __ movsd(double_store_operand, value);
4706 } else { 4719 } else {
4707 // Can't use SSE2 in the serializer 4720 // Can't use SSE2 in the serializer
4708 if (instr->hydrogen()->IsConstantHoleStore()) { 4721 if (instr->hydrogen()->IsConstantHoleStore()) {
4709 // This means we should store the (double) hole. No floating point 4722 // This means we should store the (double) hole. No floating point
(...skipping 15 matching lines...) Expand all
4725 } else { 4738 } else {
4726 Label no_special_nan_handling; 4739 Label no_special_nan_handling;
4727 X87Register value = ToX87Register(instr->value()); 4740 X87Register value = ToX87Register(instr->value());
4728 X87Fxch(value); 4741 X87Fxch(value);
4729 4742
4730 if (instr->NeedsCanonicalization()) { 4743 if (instr->NeedsCanonicalization()) {
4731 __ fld(0); 4744 __ fld(0);
4732 __ fld(0); 4745 __ fld(0);
4733 __ FCmp(); 4746 __ FCmp();
4734 4747
4735 __ j(parity_odd, &no_special_nan_handling); 4748 __ j(parity_odd, &no_special_nan_handling, Label::kNear);
4736 __ sub(esp, Immediate(kDoubleSize)); 4749 __ sub(esp, Immediate(kDoubleSize));
4737 __ fst_d(MemOperand(esp, 0)); 4750 __ fst_d(MemOperand(esp, 0));
4738 __ cmp(MemOperand(esp, sizeof(kHoleNanLower32)), 4751 __ cmp(MemOperand(esp, sizeof(kHoleNanLower32)),
4739 Immediate(kHoleNanUpper32)); 4752 Immediate(kHoleNanUpper32));
4740 __ add(esp, Immediate(kDoubleSize)); 4753 __ add(esp, Immediate(kDoubleSize));
4741 Label canonicalize; 4754 Label canonicalize;
4742 __ j(not_equal, &canonicalize); 4755 __ j(not_equal, &canonicalize, Label::kNear);
4743 __ jmp(&no_special_nan_handling); 4756 __ jmp(&no_special_nan_handling, Label::kNear);
4744 __ bind(&canonicalize); 4757 __ bind(&canonicalize);
4745 __ fstp(0); 4758 __ fstp(0);
4746 __ fld_d(Operand::StaticVariable(canonical_nan_reference)); 4759 __ fld_d(Operand::StaticVariable(canonical_nan_reference));
4747 } 4760 }
4748 4761
4749 __ bind(&no_special_nan_handling); 4762 __ bind(&no_special_nan_handling);
4750 __ fst_d(double_store_operand); 4763 __ fst_d(double_store_operand);
4751 } 4764 }
4752 } 4765 }
4753 } 4766 }
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
4980 4993
4981 PushSafepointRegistersScope scope(this); 4994 PushSafepointRegistersScope scope(this);
4982 __ SmiTag(char_code); 4995 __ SmiTag(char_code);
4983 __ push(char_code); 4996 __ push(char_code);
4984 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context()); 4997 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context());
4985 __ StoreToSafepointRegisterSlot(result, eax); 4998 __ StoreToSafepointRegisterSlot(result, eax);
4986 } 4999 }
4987 5000
4988 5001
4989 void LCodeGen::DoStringAdd(LStringAdd* instr) { 5002 void LCodeGen::DoStringAdd(LStringAdd* instr) {
4990 EmitPushTaggedOperand(instr->left()); 5003 ASSERT(ToRegister(instr->context()).is(esi));
4991 EmitPushTaggedOperand(instr->right()); 5004 if (FLAG_new_string_add) {
4992 StringAddStub stub(instr->hydrogen()->flags()); 5005 ASSERT(ToRegister(instr->left()).is(edx));
4993 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); 5006 ASSERT(ToRegister(instr->right()).is(eax));
5007 NewStringAddStub stub(instr->hydrogen()->flags(),
5008 isolate()->heap()->GetPretenureMode());
5009 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
5010 } else {
5011 EmitPushTaggedOperand(instr->left());
5012 EmitPushTaggedOperand(instr->right());
5013 StringAddStub stub(instr->hydrogen()->flags());
5014 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
5015 }
4994 } 5016 }
4995 5017
4996 5018
4997 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { 5019 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
4998 LOperand* input = instr->value(); 5020 LOperand* input = instr->value();
4999 LOperand* output = instr->result(); 5021 LOperand* output = instr->result();
5000 ASSERT(input->IsRegister() || input->IsStackSlot()); 5022 ASSERT(input->IsRegister() || input->IsStackSlot());
5001 ASSERT(output->IsDoubleRegister()); 5023 ASSERT(output->IsDoubleRegister());
5002 if (CpuFeatures::IsSupported(SSE2)) { 5024 if (CpuFeatures::IsSupported(SSE2)) {
5003 CpuFeatureScope scope(masm(), SSE2); 5025 CpuFeatureScope scope(masm(), SSE2);
(...skipping 709 matching lines...) Expand 10 before | Expand all | Expand 10 after
5713 DeferredCheckMaps* deferred = NULL; 5735 DeferredCheckMaps* deferred = NULL;
5714 if (instr->hydrogen()->has_migration_target()) { 5736 if (instr->hydrogen()->has_migration_target()) {
5715 deferred = new(zone()) DeferredCheckMaps(this, instr, reg, x87_stack_); 5737 deferred = new(zone()) DeferredCheckMaps(this, instr, reg, x87_stack_);
5716 __ bind(deferred->check_maps()); 5738 __ bind(deferred->check_maps());
5717 } 5739 }
5718 5740
5719 UniqueSet<Map> map_set = instr->hydrogen()->map_set(); 5741 UniqueSet<Map> map_set = instr->hydrogen()->map_set();
5720 Label success; 5742 Label success;
5721 for (int i = 0; i < map_set.size() - 1; i++) { 5743 for (int i = 0; i < map_set.size() - 1; i++) {
5722 Handle<Map> map = map_set.at(i).handle(); 5744 Handle<Map> map = map_set.at(i).handle();
5723 __ CompareMap(reg, map, &success); 5745 __ CompareMap(reg, map);
5724 __ j(equal, &success); 5746 __ j(equal, &success, Label::kNear);
5725 } 5747 }
5726 5748
5727 Handle<Map> map = map_set.at(map_set.size() - 1).handle(); 5749 Handle<Map> map = map_set.at(map_set.size() - 1).handle();
5728 __ CompareMap(reg, map, &success); 5750 __ CompareMap(reg, map);
5729 if (instr->hydrogen()->has_migration_target()) { 5751 if (instr->hydrogen()->has_migration_target()) {
5730 __ j(not_equal, deferred->entry()); 5752 __ j(not_equal, deferred->entry());
5731 } else { 5753 } else {
5732 DeoptimizeIf(not_equal, instr->environment()); 5754 DeoptimizeIf(not_equal, instr->environment());
5733 } 5755 }
5734 5756
5735 __ bind(&success); 5757 __ bind(&success);
5736 } 5758 }
5737 5759
5738 5760
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
5796 Register scratch2 = ToRegister(instr->scratch2()); 5818 Register scratch2 = ToRegister(instr->scratch2());
5797 Register scratch3 = ToRegister(instr->scratch3()); 5819 Register scratch3 = ToRegister(instr->scratch3());
5798 Label is_smi, done, heap_number, valid_exponent, 5820 Label is_smi, done, heap_number, valid_exponent,
5799 largest_value, zero_result, maybe_nan_or_infinity; 5821 largest_value, zero_result, maybe_nan_or_infinity;
5800 5822
5801 __ JumpIfSmi(input_reg, &is_smi); 5823 __ JumpIfSmi(input_reg, &is_smi);
5802 5824
5803 // Check for heap number 5825 // Check for heap number
5804 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 5826 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5805 factory()->heap_number_map()); 5827 factory()->heap_number_map());
5806 __ j(equal, &heap_number, Label::kFar); 5828 __ j(equal, &heap_number, Label::kNear);
5807 5829
5808 // Check for undefined. Undefined is converted to zero for clamping 5830 // Check for undefined. Undefined is converted to zero for clamping
5809 // conversions. 5831 // conversions.
5810 __ cmp(input_reg, factory()->undefined_value()); 5832 __ cmp(input_reg, factory()->undefined_value());
5811 DeoptimizeIf(not_equal, instr->environment()); 5833 DeoptimizeIf(not_equal, instr->environment());
5812 __ jmp(&zero_result); 5834 __ jmp(&zero_result, Label::kNear);
5813 5835
5814 // Heap number 5836 // Heap number
5815 __ bind(&heap_number); 5837 __ bind(&heap_number);
5816 5838
5817 // Surprisingly, all of the hand-crafted bit-manipulations below are much 5839 // Surprisingly, all of the hand-crafted bit-manipulations below are much
5818 // faster than the x86 FPU built-in instruction, especially since "banker's 5840 // faster than the x86 FPU built-in instruction, especially since "banker's
5819 // rounding" would be additionally very expensive 5841 // rounding" would be additionally very expensive
5820 5842
5821 // Get exponent word. 5843 // Get exponent word.
5822 __ mov(scratch, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 5844 __ mov(scratch, FieldOperand(input_reg, HeapNumber::kExponentOffset));
5823 __ mov(scratch3, FieldOperand(input_reg, HeapNumber::kMantissaOffset)); 5845 __ mov(scratch3, FieldOperand(input_reg, HeapNumber::kMantissaOffset));
5824 5846
5825 // Test for negative values --> clamp to zero 5847 // Test for negative values --> clamp to zero
5826 __ test(scratch, scratch); 5848 __ test(scratch, scratch);
5827 __ j(negative, &zero_result); 5849 __ j(negative, &zero_result, Label::kNear);
5828 5850
5829 // Get exponent alone in scratch2. 5851 // Get exponent alone in scratch2.
5830 __ mov(scratch2, scratch); 5852 __ mov(scratch2, scratch);
5831 __ and_(scratch2, HeapNumber::kExponentMask); 5853 __ and_(scratch2, HeapNumber::kExponentMask);
5832 __ shr(scratch2, HeapNumber::kExponentShift); 5854 __ shr(scratch2, HeapNumber::kExponentShift);
5833 __ j(zero, &zero_result); 5855 __ j(zero, &zero_result, Label::kNear);
5834 __ sub(scratch2, Immediate(HeapNumber::kExponentBias - 1)); 5856 __ sub(scratch2, Immediate(HeapNumber::kExponentBias - 1));
5835 __ j(negative, &zero_result); 5857 __ j(negative, &zero_result, Label::kNear);
5836 5858
5837 const uint32_t non_int8_exponent = 7; 5859 const uint32_t non_int8_exponent = 7;
5838 __ cmp(scratch2, Immediate(non_int8_exponent + 1)); 5860 __ cmp(scratch2, Immediate(non_int8_exponent + 1));
5839 // If the exponent is too big, check for special values. 5861 // If the exponent is too big, check for special values.
5840 __ j(greater, &maybe_nan_or_infinity, Label::kNear); 5862 __ j(greater, &maybe_nan_or_infinity, Label::kNear);
5841 5863
5842 __ bind(&valid_exponent); 5864 __ bind(&valid_exponent);
5843 // Exponent word in scratch, exponent in scratch2. We know that 0 <= exponent 5865 // Exponent word in scratch, exponent in scratch2. We know that 0 <= exponent
5844 // < 7. The shift bias is the number of bits to shift the mantissa such that 5866 // < 7. The shift bias is the number of bits to shift the mantissa such that
5845 // with an exponent of 7 such the that top-most one is in bit 30, allowing 5867 // with an exponent of 7 such the that top-most one is in bit 30, allowing
(...skipping 10 matching lines...) Expand all
5856 __ shl_cl(scratch); 5878 __ shl_cl(scratch);
5857 // Use "banker's rounding" to spec: If fractional part of number is 0.5, then 5879 // Use "banker's rounding" to spec: If fractional part of number is 0.5, then
5858 // use the bit in the "ones" place and add it to the "halves" place, which has 5880 // use the bit in the "ones" place and add it to the "halves" place, which has
5859 // the effect of rounding to even. 5881 // the effect of rounding to even.
5860 __ mov(scratch2, scratch); 5882 __ mov(scratch2, scratch);
5861 const uint32_t one_half_bit_shift = 30 - sizeof(uint8_t) * 8; 5883 const uint32_t one_half_bit_shift = 30 - sizeof(uint8_t) * 8;
5862 const uint32_t one_bit_shift = one_half_bit_shift + 1; 5884 const uint32_t one_bit_shift = one_half_bit_shift + 1;
5863 __ and_(scratch2, Immediate((1 << one_bit_shift) - 1)); 5885 __ and_(scratch2, Immediate((1 << one_bit_shift) - 1));
5864 __ cmp(scratch2, Immediate(1 << one_half_bit_shift)); 5886 __ cmp(scratch2, Immediate(1 << one_half_bit_shift));
5865 Label no_round; 5887 Label no_round;
5866 __ j(less, &no_round); 5888 __ j(less, &no_round, Label::kNear);
5867 Label round_up; 5889 Label round_up;
5868 __ mov(scratch2, Immediate(1 << one_half_bit_shift)); 5890 __ mov(scratch2, Immediate(1 << one_half_bit_shift));
5869 __ j(greater, &round_up); 5891 __ j(greater, &round_up, Label::kNear);
5870 __ test(scratch3, scratch3); 5892 __ test(scratch3, scratch3);
5871 __ j(not_zero, &round_up); 5893 __ j(not_zero, &round_up, Label::kNear);
5872 __ mov(scratch2, scratch); 5894 __ mov(scratch2, scratch);
5873 __ and_(scratch2, Immediate(1 << one_bit_shift)); 5895 __ and_(scratch2, Immediate(1 << one_bit_shift));
5874 __ shr(scratch2, 1); 5896 __ shr(scratch2, 1);
5875 __ bind(&round_up); 5897 __ bind(&round_up);
5876 __ add(scratch, scratch2); 5898 __ add(scratch, scratch2);
5877 __ j(overflow, &largest_value); 5899 __ j(overflow, &largest_value, Label::kNear);
5878 __ bind(&no_round); 5900 __ bind(&no_round);
5879 __ shr(scratch, 23); 5901 __ shr(scratch, 23);
5880 __ mov(result_reg, scratch); 5902 __ mov(result_reg, scratch);
5881 __ jmp(&done, Label::kNear); 5903 __ jmp(&done, Label::kNear);
5882 5904
5883 __ bind(&maybe_nan_or_infinity); 5905 __ bind(&maybe_nan_or_infinity);
5884 // Check for NaN/Infinity, all other values map to 255 5906 // Check for NaN/Infinity, all other values map to 255
5885 __ cmp(scratch2, Immediate(HeapNumber::kInfinityOrNanExponent + 1)); 5907 __ cmp(scratch2, Immediate(HeapNumber::kInfinityOrNanExponent + 1));
5886 __ j(not_equal, &largest_value, Label::kNear); 5908 __ j(not_equal, &largest_value, Label::kNear);
5887 5909
5888 // Check for NaN, which differs from Infinity in that at least one mantissa 5910 // Check for NaN, which differs from Infinity in that at least one mantissa
5889 // bit is set. 5911 // bit is set.
5890 __ and_(scratch, HeapNumber::kMantissaMask); 5912 __ and_(scratch, HeapNumber::kMantissaMask);
5891 __ or_(scratch, FieldOperand(input_reg, HeapNumber::kMantissaOffset)); 5913 __ or_(scratch, FieldOperand(input_reg, HeapNumber::kMantissaOffset));
5892 __ j(not_zero, &zero_result); // M!=0 --> NaN 5914 __ j(not_zero, &zero_result, Label::kNear); // M!=0 --> NaN
5893 // Infinity -> Fall through to map to 255. 5915 // Infinity -> Fall through to map to 255.
5894 5916
5895 __ bind(&largest_value); 5917 __ bind(&largest_value);
5896 __ mov(result_reg, Immediate(255)); 5918 __ mov(result_reg, Immediate(255));
5897 __ jmp(&done, Label::kNear); 5919 __ jmp(&done, Label::kNear);
5898 5920
5899 __ bind(&zero_result); 5921 __ bind(&zero_result);
5900 __ xor_(result_reg, result_reg); 5922 __ xor_(result_reg, result_reg);
5901 __ jmp(&done); 5923 __ jmp(&done, Label::kNear);
5902 5924
5903 // smi 5925 // smi
5904 __ bind(&is_smi); 5926 __ bind(&is_smi);
5905 if (!input_reg.is(result_reg)) { 5927 if (!input_reg.is(result_reg)) {
5906 __ mov(result_reg, input_reg); 5928 __ mov(result_reg, input_reg);
5907 } 5929 }
5908 __ SmiUntag(result_reg); 5930 __ SmiUntag(result_reg);
5909 __ ClampUint8(result_reg); 5931 __ ClampUint8(result_reg);
5910 __ bind(&done); 5932 __ bind(&done);
5911 } 5933 }
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
6039 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); 6061 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index())));
6040 __ push(Immediate(instr->hydrogen()->pattern())); 6062 __ push(Immediate(instr->hydrogen()->pattern()));
6041 __ push(Immediate(instr->hydrogen()->flags())); 6063 __ push(Immediate(instr->hydrogen()->flags()));
6042 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); 6064 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr);
6043 __ mov(ebx, eax); 6065 __ mov(ebx, eax);
6044 6066
6045 __ bind(&materialized); 6067 __ bind(&materialized);
6046 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; 6068 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
6047 Label allocated, runtime_allocate; 6069 Label allocated, runtime_allocate;
6048 __ Allocate(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT); 6070 __ Allocate(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT);
6049 __ jmp(&allocated); 6071 __ jmp(&allocated, Label::kNear);
6050 6072
6051 __ bind(&runtime_allocate); 6073 __ bind(&runtime_allocate);
6052 __ push(ebx); 6074 __ push(ebx);
6053 __ push(Immediate(Smi::FromInt(size))); 6075 __ push(Immediate(Smi::FromInt(size)));
6054 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); 6076 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr);
6055 __ pop(ebx); 6077 __ pop(ebx);
6056 6078
6057 __ bind(&allocated); 6079 __ bind(&allocated);
6058 // Copy the content into the newly allocated memory. 6080 // Copy the content into the newly allocated memory.
6059 // (Unroll copy loop once for better throughput). 6081 // (Unroll copy loop once for better throughput).
(...skipping 24 matching lines...) Expand all
6084 __ push(esi); 6106 __ push(esi);
6085 __ push(Immediate(instr->hydrogen()->shared_info())); 6107 __ push(Immediate(instr->hydrogen()->shared_info()));
6086 __ push(Immediate(pretenure ? factory()->true_value() 6108 __ push(Immediate(pretenure ? factory()->true_value()
6087 : factory()->false_value())); 6109 : factory()->false_value()));
6088 CallRuntime(Runtime::kNewClosure, 3, instr); 6110 CallRuntime(Runtime::kNewClosure, 3, instr);
6089 } 6111 }
6090 } 6112 }
6091 6113
6092 6114
6093 void LCodeGen::DoTypeof(LTypeof* instr) { 6115 void LCodeGen::DoTypeof(LTypeof* instr) {
6116 ASSERT(ToRegister(instr->context()).is(esi));
6094 LOperand* input = instr->value(); 6117 LOperand* input = instr->value();
6095 EmitPushTaggedOperand(input); 6118 EmitPushTaggedOperand(input);
6096 CallRuntime(Runtime::kTypeof, 1, instr); 6119 CallRuntime(Runtime::kTypeof, 1, instr);
6097 } 6120 }
6098 6121
6099 6122
6100 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { 6123 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
6101 Register input = ToRegister(instr->value()); 6124 Register input = ToRegister(instr->value());
6102 6125
6103 Condition final_branch_condition = 6126 Condition final_branch_condition =
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
6239 // now identical. When LAZY is eventually completely folded into EAGER, remove 6262 // now identical. When LAZY is eventually completely folded into EAGER, remove
6240 // the special case below. 6263 // the special case below.
6241 if (info()->IsStub() && type == Deoptimizer::EAGER) { 6264 if (info()->IsStub() && type == Deoptimizer::EAGER) {
6242 type = Deoptimizer::LAZY; 6265 type = Deoptimizer::LAZY;
6243 } 6266 }
6244 Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); 6267 Comment(";;; deoptimize: %s", instr->hydrogen()->reason());
6245 DeoptimizeIf(no_condition, instr->environment(), type); 6268 DeoptimizeIf(no_condition, instr->environment(), type);
6246 } 6269 }
6247 6270
6248 6271
6272 void LCodeGen::DoDummy(LDummy* instr) {
6273 // Nothing to see here, move on!
6274 }
6275
6276
6249 void LCodeGen::DoDummyUse(LDummyUse* instr) { 6277 void LCodeGen::DoDummyUse(LDummyUse* instr) {
6250 // Nothing to see here, move on! 6278 // Nothing to see here, move on!
6251 } 6279 }
6252 6280
6253 6281
6254 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { 6282 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
6255 PushSafepointRegistersScope scope(this); 6283 PushSafepointRegistersScope scope(this);
6256 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 6284 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
6257 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); 6285 __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
6258 RecordSafepointWithLazyDeopt( 6286 RecordSafepointWithLazyDeopt(
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
6328 // If the environment were already registered, we would have no way of 6356 // If the environment were already registered, we would have no way of
6329 // backpatching it with the spill slot operands. 6357 // backpatching it with the spill slot operands.
6330 ASSERT(!environment->HasBeenRegistered()); 6358 ASSERT(!environment->HasBeenRegistered());
6331 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); 6359 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
6332 6360
6333 GenerateOsrPrologue(); 6361 GenerateOsrPrologue();
6334 } 6362 }
6335 6363
6336 6364
6337 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { 6365 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
6366 ASSERT(ToRegister(instr->context()).is(esi));
6338 __ cmp(eax, isolate()->factory()->undefined_value()); 6367 __ cmp(eax, isolate()->factory()->undefined_value());
6339 DeoptimizeIf(equal, instr->environment()); 6368 DeoptimizeIf(equal, instr->environment());
6340 6369
6341 __ cmp(eax, isolate()->factory()->null_value()); 6370 __ cmp(eax, isolate()->factory()->null_value());
6342 DeoptimizeIf(equal, instr->environment()); 6371 DeoptimizeIf(equal, instr->environment());
6343 6372
6344 __ test(eax, Immediate(kSmiTagMask)); 6373 __ test(eax, Immediate(kSmiTagMask));
6345 DeoptimizeIf(zero, instr->environment()); 6374 DeoptimizeIf(zero, instr->environment());
6346 6375
6347 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 6376 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
(...skipping 17 matching lines...) Expand all
6365 __ bind(&use_cache); 6394 __ bind(&use_cache);
6366 } 6395 }
6367 6396
6368 6397
6369 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { 6398 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
6370 Register map = ToRegister(instr->map()); 6399 Register map = ToRegister(instr->map());
6371 Register result = ToRegister(instr->result()); 6400 Register result = ToRegister(instr->result());
6372 Label load_cache, done; 6401 Label load_cache, done;
6373 __ EnumLength(result, map); 6402 __ EnumLength(result, map);
6374 __ cmp(result, Immediate(Smi::FromInt(0))); 6403 __ cmp(result, Immediate(Smi::FromInt(0)));
6375 __ j(not_equal, &load_cache); 6404 __ j(not_equal, &load_cache, Label::kNear);
6376 __ mov(result, isolate()->factory()->empty_fixed_array()); 6405 __ mov(result, isolate()->factory()->empty_fixed_array());
6377 __ jmp(&done); 6406 __ jmp(&done, Label::kNear);
6378 6407
6379 __ bind(&load_cache); 6408 __ bind(&load_cache);
6380 __ LoadInstanceDescriptors(map, result); 6409 __ LoadInstanceDescriptors(map, result);
6381 __ mov(result, 6410 __ mov(result,
6382 FieldOperand(result, DescriptorArray::kEnumCacheOffset)); 6411 FieldOperand(result, DescriptorArray::kEnumCacheOffset));
6383 __ mov(result, 6412 __ mov(result,
6384 FieldOperand(result, FixedArray::SizeFor(instr->idx()))); 6413 FieldOperand(result, FixedArray::SizeFor(instr->idx())));
6385 __ bind(&done); 6414 __ bind(&done);
6386 __ test(result, result); 6415 __ test(result, result);
6387 DeoptimizeIf(equal, instr->environment()); 6416 DeoptimizeIf(equal, instr->environment());
6388 } 6417 }
6389 6418
6390 6419
6391 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { 6420 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
6392 Register object = ToRegister(instr->value()); 6421 Register object = ToRegister(instr->value());
6393 __ cmp(ToRegister(instr->map()), 6422 __ cmp(ToRegister(instr->map()),
6394 FieldOperand(object, HeapObject::kMapOffset)); 6423 FieldOperand(object, HeapObject::kMapOffset));
6395 DeoptimizeIf(not_equal, instr->environment()); 6424 DeoptimizeIf(not_equal, instr->environment());
6396 } 6425 }
6397 6426
6398 6427
6399 void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) { 6428 void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) {
6400 Register object = ToRegister(instr->object()); 6429 Register object = ToRegister(instr->object());
6401 Register index = ToRegister(instr->index()); 6430 Register index = ToRegister(instr->index());
6402 6431
6403 Label out_of_object, done; 6432 Label out_of_object, done;
6404 __ cmp(index, Immediate(0)); 6433 __ cmp(index, Immediate(0));
6405 __ j(less, &out_of_object); 6434 __ j(less, &out_of_object, Label::kNear);
6406 __ mov(object, FieldOperand(object, 6435 __ mov(object, FieldOperand(object,
6407 index, 6436 index,
6408 times_half_pointer_size, 6437 times_half_pointer_size,
6409 JSObject::kHeaderSize)); 6438 JSObject::kHeaderSize));
6410 __ jmp(&done, Label::kNear); 6439 __ jmp(&done, Label::kNear);
6411 6440
6412 __ bind(&out_of_object); 6441 __ bind(&out_of_object);
6413 __ mov(object, FieldOperand(object, JSObject::kPropertiesOffset)); 6442 __ mov(object, FieldOperand(object, JSObject::kPropertiesOffset));
6414 __ neg(index); 6443 __ neg(index);
6415 // Index is now equal to out of object property index plus 1. 6444 // Index is now equal to out of object property index plus 1.
6416 __ mov(object, FieldOperand(object, 6445 __ mov(object, FieldOperand(object,
6417 index, 6446 index,
6418 times_half_pointer_size, 6447 times_half_pointer_size,
6419 FixedArray::kHeaderSize - kPointerSize)); 6448 FixedArray::kHeaderSize - kPointerSize));
6420 __ bind(&done); 6449 __ bind(&done);
6421 } 6450 }
6422 6451
6423 6452
6424 #undef __ 6453 #undef __
6425 6454
6426 } } // namespace v8::internal 6455 } } // namespace v8::internal
6427 6456
6428 #endif // V8_TARGET_ARCH_IA32 6457 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/lithium-codegen-ia32.h ('k') | src/ia32/lithium-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698