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

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

Issue 9227007: Version 3.8.6 (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: Created 8 years, 11 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/arm/lithium-codegen-arm.h ('k') | src/arm/lithium-gap-resolver-arm.cc » ('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 2011 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
11 // with the distribution. 11 // with the distribution.
(...skipping 1975 matching lines...) Expand 10 before | Expand all | Expand 10 after
1987 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1987 int false_block = chunk_->LookupDestination(instr->false_block_id());
1988 1988
1989 __ ldr(scratch, 1989 __ ldr(scratch,
1990 FieldMemOperand(input, String::kHashFieldOffset)); 1990 FieldMemOperand(input, String::kHashFieldOffset));
1991 __ tst(scratch, Operand(String::kContainsCachedArrayIndexMask)); 1991 __ tst(scratch, Operand(String::kContainsCachedArrayIndexMask));
1992 EmitBranch(true_block, false_block, eq); 1992 EmitBranch(true_block, false_block, eq);
1993 } 1993 }
1994 1994
1995 1995
1996 // Branches to a label or falls through with the answer in flags. Trashes 1996 // Branches to a label or falls through with the answer in flags. Trashes
1997 // the temp registers, but not the input. Only input and temp2 may alias. 1997 // the temp registers, but not the input.
1998 void LCodeGen::EmitClassOfTest(Label* is_true, 1998 void LCodeGen::EmitClassOfTest(Label* is_true,
1999 Label* is_false, 1999 Label* is_false,
2000 Handle<String>class_name, 2000 Handle<String>class_name,
2001 Register input, 2001 Register input,
2002 Register temp, 2002 Register temp,
2003 Register temp2) { 2003 Register temp2) {
2004 ASSERT(!input.is(temp)); 2004 ASSERT(!input.is(temp));
2005 ASSERT(!temp.is(temp2)); // But input and temp2 may be the same register. 2005 ASSERT(!input.is(temp2));
2006 ASSERT(!temp.is(temp2));
2007
2006 __ JumpIfSmi(input, is_false); 2008 __ JumpIfSmi(input, is_false);
2007 2009
2008 if (class_name->IsEqualTo(CStrVector("Function"))) { 2010 if (class_name->IsEqualTo(CStrVector("Function"))) {
2009 // Assuming the following assertions, we can use the same compares to test 2011 // Assuming the following assertions, we can use the same compares to test
2010 // for both being a function type and being in the object type range. 2012 // for both being a function type and being in the object type range.
2011 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); 2013 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
2012 STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE == 2014 STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
2013 FIRST_SPEC_OBJECT_TYPE + 1); 2015 FIRST_SPEC_OBJECT_TYPE + 1);
2014 STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == 2016 STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
2015 LAST_SPEC_OBJECT_TYPE - 1); 2017 LAST_SPEC_OBJECT_TYPE - 1);
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
2134 // This is the inlined call site instanceof cache. The two occurences of the 2136 // This is the inlined call site instanceof cache. The two occurences of the
2135 // hole value will be patched to the last map/result pair generated by the 2137 // hole value will be patched to the last map/result pair generated by the
2136 // instanceof stub. 2138 // instanceof stub.
2137 Label cache_miss; 2139 Label cache_miss;
2138 Register map = temp; 2140 Register map = temp;
2139 __ ldr(map, FieldMemOperand(object, HeapObject::kMapOffset)); 2141 __ ldr(map, FieldMemOperand(object, HeapObject::kMapOffset));
2140 __ bind(deferred->map_check()); // Label for calculating code patching. 2142 __ bind(deferred->map_check()); // Label for calculating code patching.
2141 // We use Factory::the_hole_value() on purpose instead of loading from the 2143 // We use Factory::the_hole_value() on purpose instead of loading from the
2142 // root array to force relocation to be able to later patch with 2144 // root array to force relocation to be able to later patch with
2143 // the cached map. 2145 // the cached map.
2144 __ mov(ip, Operand(factory()->the_hole_value())); 2146 Handle<JSGlobalPropertyCell> cell =
2147 factory()->NewJSGlobalPropertyCell(factory()->the_hole_value());
2148 __ mov(ip, Operand(Handle<Object>(cell)));
2149 __ ldr(ip, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset));
2145 __ cmp(map, Operand(ip)); 2150 __ cmp(map, Operand(ip));
2146 __ b(ne, &cache_miss); 2151 __ b(ne, &cache_miss);
2147 // We use Factory::the_hole_value() on purpose instead of loading from the 2152 // We use Factory::the_hole_value() on purpose instead of loading from the
2148 // root array to force relocation to be able to later patch 2153 // root array to force relocation to be able to later patch
2149 // with true or false. 2154 // with true or false.
2150 __ mov(result, Operand(factory()->the_hole_value())); 2155 __ mov(result, Operand(factory()->the_hole_value()));
2151 __ b(&done); 2156 __ b(&done);
2152 2157
2153 // The inlined call site cache did not match. Check null and string before 2158 // The inlined call site cache did not match. Check null and string before
2154 // calling the deferred code. 2159 // calling the deferred code.
(...skipping 739 matching lines...) Expand 10 before | Expand all | Expand 10 after
2894 } 2899 }
2895 2900
2896 LPointerMap* pointers = instr->pointer_map(); 2901 LPointerMap* pointers = instr->pointer_map();
2897 RecordPosition(pointers->position()); 2902 RecordPosition(pointers->position());
2898 2903
2899 // Invoke function. 2904 // Invoke function.
2900 __ SetCallKind(r5, call_kind); 2905 __ SetCallKind(r5, call_kind);
2901 __ ldr(ip, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); 2906 __ ldr(ip, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
2902 __ Call(ip); 2907 __ Call(ip);
2903 2908
2904 // Setup deoptimization. 2909 // Set up deoptimization.
2905 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); 2910 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
2906 2911
2907 // Restore context. 2912 // Restore context.
2908 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2913 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2909 } 2914 }
2910 2915
2911 2916
2912 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { 2917 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
2913 ASSERT(ToRegister(instr->result()).is(r0)); 2918 ASSERT(ToRegister(instr->result()).is(r0));
2914 __ LoadHeapObject(r1, instr->function()); 2919 __ LoadHeapObject(r1, instr->function());
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
3183 MathPowStub stub(MathPowStub::INTEGER); 3188 MathPowStub stub(MathPowStub::INTEGER);
3184 __ CallStub(&stub); 3189 __ CallStub(&stub);
3185 } else { 3190 } else {
3186 ASSERT(exponent_type.IsDouble()); 3191 ASSERT(exponent_type.IsDouble());
3187 MathPowStub stub(MathPowStub::DOUBLE); 3192 MathPowStub stub(MathPowStub::DOUBLE);
3188 __ CallStub(&stub); 3193 __ CallStub(&stub);
3189 } 3194 }
3190 } 3195 }
3191 3196
3192 3197
3198 void LCodeGen::DoRandom(LRandom* instr) {
3199 // Having marked this instruction as a call we can use any
3200 // registers.
3201 ASSERT(ToDoubleRegister(instr->result()).is(d7));
3202 ASSERT(ToRegister(instr->InputAt(0)).is(r0));
3203
3204 __ PrepareCallCFunction(1, scratch0());
3205 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalContextOffset));
3206 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
3207
3208 // 0x41300000 is the top half of 1.0 x 2^20 as a double.
3209 // Create this constant using mov/orr to avoid PC relative load.
3210 __ mov(r1, Operand(0x41000000));
3211 __ orr(r1, r1, Operand(0x300000));
3212 // Move 0x41300000xxxxxxxx (x = random bits) to VFP.
3213 __ vmov(d7, r0, r1);
3214 // Move 0x4130000000000000 to VFP.
3215 __ mov(r0, Operand(0, RelocInfo::NONE));
3216 __ vmov(d8, r0, r1);
3217 // Subtract and store the result in the heap number.
3218 __ vsub(d7, d7, d8);
3219 }
3220
3221
3193 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { 3222 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
3194 ASSERT(ToDoubleRegister(instr->result()).is(d2)); 3223 ASSERT(ToDoubleRegister(instr->result()).is(d2));
3195 TranscendentalCacheStub stub(TranscendentalCache::LOG, 3224 TranscendentalCacheStub stub(TranscendentalCache::LOG,
3196 TranscendentalCacheStub::UNTAGGED); 3225 TranscendentalCacheStub::UNTAGGED);
3197 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 3226 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
3198 } 3227 }
3199 3228
3200 3229
3201 void LCodeGen::DoMathTan(LUnaryMathOperation* instr) { 3230 void LCodeGen::DoMathTan(LUnaryMathOperation* instr) {
3202 ASSERT(ToDoubleRegister(instr->result()).is(d2)); 3231 ASSERT(ToDoubleRegister(instr->result()).is(d2));
(...skipping 664 matching lines...) Expand 10 before | Expand all | Expand 10 after
3867 DeoptimizeIf(cs, instr->environment()); 3896 DeoptimizeIf(cs, instr->environment());
3868 } else { 3897 } else {
3869 __ SmiUntag(ToRegister(input)); 3898 __ SmiUntag(ToRegister(input));
3870 } 3899 }
3871 } 3900 }
3872 3901
3873 3902
3874 void LCodeGen::EmitNumberUntagD(Register input_reg, 3903 void LCodeGen::EmitNumberUntagD(Register input_reg,
3875 DoubleRegister result_reg, 3904 DoubleRegister result_reg,
3876 bool deoptimize_on_undefined, 3905 bool deoptimize_on_undefined,
3906 bool deoptimize_on_minus_zero,
3877 LEnvironment* env) { 3907 LEnvironment* env) {
3878 Register scratch = scratch0(); 3908 Register scratch = scratch0();
3879 SwVfpRegister flt_scratch = double_scratch0().low(); 3909 SwVfpRegister flt_scratch = double_scratch0().low();
3880 ASSERT(!result_reg.is(double_scratch0())); 3910 ASSERT(!result_reg.is(double_scratch0()));
3881 3911
3882 Label load_smi, heap_number, done; 3912 Label load_smi, heap_number, done;
3883 3913
3884 // Smi check. 3914 // Smi check.
3885 __ JumpIfSmi(input_reg, &load_smi); 3915 __ JumpIfSmi(input_reg, &load_smi);
3886 3916
(...skipping 15 matching lines...) Expand all
3902 __ LoadRoot(ip, Heap::kNanValueRootIndex); 3932 __ LoadRoot(ip, Heap::kNanValueRootIndex);
3903 __ sub(ip, ip, Operand(kHeapObjectTag)); 3933 __ sub(ip, ip, Operand(kHeapObjectTag));
3904 __ vldr(result_reg, ip, HeapNumber::kValueOffset); 3934 __ vldr(result_reg, ip, HeapNumber::kValueOffset);
3905 __ jmp(&done); 3935 __ jmp(&done);
3906 3936
3907 __ bind(&heap_number); 3937 __ bind(&heap_number);
3908 } 3938 }
3909 // Heap number to double register conversion. 3939 // Heap number to double register conversion.
3910 __ sub(ip, input_reg, Operand(kHeapObjectTag)); 3940 __ sub(ip, input_reg, Operand(kHeapObjectTag));
3911 __ vldr(result_reg, ip, HeapNumber::kValueOffset); 3941 __ vldr(result_reg, ip, HeapNumber::kValueOffset);
3942 if (deoptimize_on_minus_zero) {
3943 __ vmov(ip, result_reg.low());
3944 __ cmp(ip, Operand(0));
3945 __ b(ne, &done);
3946 __ vmov(ip, result_reg.high());
3947 __ cmp(ip, Operand(HeapNumber::kSignMask));
3948 DeoptimizeIf(eq, env);
3949 }
3912 __ jmp(&done); 3950 __ jmp(&done);
3913 3951
3914 // Smi to double register conversion 3952 // Smi to double register conversion
3915 __ bind(&load_smi); 3953 __ bind(&load_smi);
3916 __ SmiUntag(input_reg); // Untag smi before converting to float. 3954 __ SmiUntag(input_reg); // Untag smi before converting to float.
3917 __ vmov(flt_scratch, input_reg); 3955 __ vmov(flt_scratch, input_reg);
3918 __ vcvt_f64_s32(result_reg, flt_scratch); 3956 __ vcvt_f64_s32(result_reg, flt_scratch);
3919 __ SmiTag(input_reg); // Retag smi. 3957 __ SmiTag(input_reg); // Retag smi.
3920 __ bind(&done); 3958 __ bind(&done);
3921 } 3959 }
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
4035 LOperand* input = instr->InputAt(0); 4073 LOperand* input = instr->InputAt(0);
4036 ASSERT(input->IsRegister()); 4074 ASSERT(input->IsRegister());
4037 LOperand* result = instr->result(); 4075 LOperand* result = instr->result();
4038 ASSERT(result->IsDoubleRegister()); 4076 ASSERT(result->IsDoubleRegister());
4039 4077
4040 Register input_reg = ToRegister(input); 4078 Register input_reg = ToRegister(input);
4041 DoubleRegister result_reg = ToDoubleRegister(result); 4079 DoubleRegister result_reg = ToDoubleRegister(result);
4042 4080
4043 EmitNumberUntagD(input_reg, result_reg, 4081 EmitNumberUntagD(input_reg, result_reg,
4044 instr->hydrogen()->deoptimize_on_undefined(), 4082 instr->hydrogen()->deoptimize_on_undefined(),
4083 instr->hydrogen()->deoptimize_on_minus_zero(),
4045 instr->environment()); 4084 instr->environment());
4046 } 4085 }
4047 4086
4048 4087
4049 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { 4088 void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
4050 Register result_reg = ToRegister(instr->result()); 4089 Register result_reg = ToRegister(instr->result());
4051 Register scratch1 = scratch0(); 4090 Register scratch1 = scratch0();
4052 Register scratch2 = ToRegister(instr->TempAt(0)); 4091 Register scratch2 = ToRegister(instr->TempAt(0));
4053 DwVfpRegister double_input = ToDoubleRegister(instr->InputAt(0)); 4092 DwVfpRegister double_input = ToDoubleRegister(instr->InputAt(0));
4054 SwVfpRegister single_scratch = double_scratch0().low(); 4093 SwVfpRegister single_scratch = double_scratch0().low();
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
4148 __ mov(ip, Operand(Handle<Object>(cell))); 4187 __ mov(ip, Operand(Handle<Object>(cell)));
4149 __ ldr(ip, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset)); 4188 __ ldr(ip, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset));
4150 __ cmp(reg, ip); 4189 __ cmp(reg, ip);
4151 } else { 4190 } else {
4152 __ cmp(reg, Operand(target)); 4191 __ cmp(reg, Operand(target));
4153 } 4192 }
4154 DeoptimizeIf(ne, instr->environment()); 4193 DeoptimizeIf(ne, instr->environment());
4155 } 4194 }
4156 4195
4157 4196
4197 void LCodeGen::DoCheckMapCommon(Register reg,
4198 Register scratch,
4199 Handle<Map> map,
4200 CompareMapMode mode,
4201 LEnvironment* env) {
4202 Label success;
4203 __ CompareMap(reg, scratch, map, &success, mode);
4204 DeoptimizeIf(ne, env);
4205 __ bind(&success);
4206 }
4207
4208
4158 void LCodeGen::DoCheckMap(LCheckMap* instr) { 4209 void LCodeGen::DoCheckMap(LCheckMap* instr) {
4159 Register scratch = scratch0(); 4210 Register scratch = scratch0();
4160 LOperand* input = instr->InputAt(0); 4211 LOperand* input = instr->InputAt(0);
4161 ASSERT(input->IsRegister()); 4212 ASSERT(input->IsRegister());
4162 Register reg = ToRegister(input); 4213 Register reg = ToRegister(input);
4163 __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); 4214 Handle<Map> map = instr->hydrogen()->map();
4164 __ cmp(scratch, Operand(instr->hydrogen()->map())); 4215 DoCheckMapCommon(reg, scratch, map, instr->hydrogen()->mode(),
4165 DeoptimizeIf(ne, instr->environment()); 4216 instr->environment());
4166 } 4217 }
4167 4218
4168 4219
4169 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { 4220 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
4170 DoubleRegister value_reg = ToDoubleRegister(instr->unclamped()); 4221 DoubleRegister value_reg = ToDoubleRegister(instr->unclamped());
4171 Register result_reg = ToRegister(instr->result()); 4222 Register result_reg = ToRegister(instr->result());
4172 DoubleRegister temp_reg = ToDoubleRegister(instr->TempAt(0)); 4223 DoubleRegister temp_reg = ToDoubleRegister(instr->TempAt(0));
4173 __ ClampDoubleToUint8(result_reg, value_reg, temp_reg); 4224 __ ClampDoubleToUint8(result_reg, value_reg, temp_reg);
4174 } 4225 }
4175 4226
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
4224 Register temp2 = ToRegister(instr->TempAt(1)); 4275 Register temp2 = ToRegister(instr->TempAt(1));
4225 4276
4226 Handle<JSObject> holder = instr->holder(); 4277 Handle<JSObject> holder = instr->holder();
4227 Handle<JSObject> current_prototype = instr->prototype(); 4278 Handle<JSObject> current_prototype = instr->prototype();
4228 4279
4229 // Load prototype object. 4280 // Load prototype object.
4230 __ LoadHeapObject(temp1, current_prototype); 4281 __ LoadHeapObject(temp1, current_prototype);
4231 4282
4232 // Check prototype maps up to the holder. 4283 // Check prototype maps up to the holder.
4233 while (!current_prototype.is_identical_to(holder)) { 4284 while (!current_prototype.is_identical_to(holder)) {
4234 __ ldr(temp2, FieldMemOperand(temp1, HeapObject::kMapOffset)); 4285 DoCheckMapCommon(temp1, temp2,
4235 __ cmp(temp2, Operand(Handle<Map>(current_prototype->map()))); 4286 Handle<Map>(current_prototype->map()),
4236 DeoptimizeIf(ne, instr->environment()); 4287 ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment());
4237 current_prototype = 4288 current_prototype =
4238 Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype())); 4289 Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype()));
4239 // Load next prototype object. 4290 // Load next prototype object.
4240 __ LoadHeapObject(temp1, current_prototype); 4291 __ LoadHeapObject(temp1, current_prototype);
4241 } 4292 }
4242 4293
4243 // Check the holder map. 4294 // Check the holder map.
4244 __ ldr(temp2, FieldMemOperand(temp1, HeapObject::kMapOffset)); 4295 DoCheckMapCommon(temp1, temp2,
4245 __ cmp(temp2, Operand(Handle<Map>(current_prototype->map()))); 4296 Handle<Map>(current_prototype->map()),
4297 ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment());
4246 DeoptimizeIf(ne, instr->environment()); 4298 DeoptimizeIf(ne, instr->environment());
4247 } 4299 }
4248 4300
4249 4301
4250 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { 4302 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
4251 Heap* heap = isolate()->heap(); 4303 Heap* heap = isolate()->heap();
4252 ElementsKind boilerplate_elements_kind = 4304 ElementsKind boilerplate_elements_kind =
4253 instr->hydrogen()->boilerplate_elements_kind(); 4305 instr->hydrogen()->boilerplate_elements_kind();
4254 4306
4255 // Deopt if the array literal boilerplate ElementsKind is of a type different 4307 // Deopt if the array literal boilerplate ElementsKind is of a type different
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after
4732 ASSERT(osr_pc_offset_ == -1); 4784 ASSERT(osr_pc_offset_ == -1);
4733 osr_pc_offset_ = masm()->pc_offset(); 4785 osr_pc_offset_ = masm()->pc_offset();
4734 } 4786 }
4735 4787
4736 4788
4737 4789
4738 4790
4739 #undef __ 4791 #undef __
4740 4792
4741 } } // namespace v8::internal 4793 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/lithium-codegen-arm.h ('k') | src/arm/lithium-gap-resolver-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698