| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |