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 18 matching lines...) Expand all Loading... |
29 | 29 |
30 #include "arm/lithium-codegen-arm.h" | 30 #include "arm/lithium-codegen-arm.h" |
31 #include "arm/lithium-gap-resolver-arm.h" | 31 #include "arm/lithium-gap-resolver-arm.h" |
32 #include "code-stubs.h" | 32 #include "code-stubs.h" |
33 #include "stub-cache.h" | 33 #include "stub-cache.h" |
34 | 34 |
35 namespace v8 { | 35 namespace v8 { |
36 namespace internal { | 36 namespace internal { |
37 | 37 |
38 | 38 |
| 39 static SaveFPRegsMode GetSaveFPRegsMode() { |
| 40 // We don't need to save floating point regs when generating the snapshot |
| 41 return !Serializer::enabled() ? kSaveFPRegs : kDontSaveFPRegs; |
| 42 } |
| 43 |
| 44 |
39 class SafepointGenerator : public CallWrapper { | 45 class SafepointGenerator : public CallWrapper { |
40 public: | 46 public: |
41 SafepointGenerator(LCodeGen* codegen, | 47 SafepointGenerator(LCodeGen* codegen, |
42 LPointerMap* pointers, | 48 LPointerMap* pointers, |
43 Safepoint::DeoptMode mode) | 49 Safepoint::DeoptMode mode) |
44 : codegen_(codegen), | 50 : codegen_(codegen), |
45 pointers_(pointers), | 51 pointers_(pointers), |
46 deopt_mode_(mode) { } | 52 deopt_mode_(mode) { } |
47 virtual ~SafepointGenerator() { } | 53 virtual ~SafepointGenerator() { } |
48 | 54 |
(...skipping 2887 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2936 while (!save_iterator.Done()) { | 2942 while (!save_iterator.Done()) { |
2937 __ vldr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()), | 2943 __ vldr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()), |
2938 MemOperand(sp, count * kDoubleSize)); | 2944 MemOperand(sp, count * kDoubleSize)); |
2939 save_iterator.Advance(); | 2945 save_iterator.Advance(); |
2940 count++; | 2946 count++; |
2941 } | 2947 } |
2942 } | 2948 } |
2943 if (NeedsEagerFrame()) { | 2949 if (NeedsEagerFrame()) { |
2944 __ mov(sp, fp); | 2950 __ mov(sp, fp); |
2945 __ ldm(ia_w, sp, fp.bit() | lr.bit()); | 2951 __ ldm(ia_w, sp, fp.bit() | lr.bit()); |
| 2952 } |
| 2953 if (instr->has_constant_parameter_count()) { |
| 2954 int parameter_count = ToInteger32(instr->constant_parameter_count()); |
| 2955 int32_t sp_delta = (parameter_count + 1) * kPointerSize; |
| 2956 if (sp_delta != 0) { |
| 2957 __ add(sp, sp, Operand(sp_delta)); |
| 2958 } |
| 2959 } else { |
| 2960 Register reg = ToRegister(instr->parameter_count()); |
| 2961 __ SmiUntag(reg); // it is a smi |
| 2962 __ add(sp, sp, Operand(reg, LSL, kPointerSizeLog2)); |
| 2963 } |
2946 | 2964 |
2947 if (instr->has_constant_parameter_count()) { | |
2948 int parameter_count = ToInteger32(instr->constant_parameter_count()); | |
2949 int32_t sp_delta = (parameter_count + 1) * kPointerSize; | |
2950 if (sp_delta != 0) { | |
2951 __ add(sp, sp, Operand(sp_delta)); | |
2952 } | |
2953 } else { | |
2954 Register reg = ToRegister(instr->parameter_count()); | |
2955 __ add(reg, reg, Operand(1)); | |
2956 __ add(sp, sp, Operand(reg, LSL, kPointerSizeLog2)); | |
2957 } | |
2958 } | |
2959 __ Jump(lr); | 2965 __ Jump(lr); |
2960 } | 2966 } |
2961 | 2967 |
2962 | 2968 |
2963 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { | 2969 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { |
2964 Register result = ToRegister(instr->result()); | 2970 Register result = ToRegister(instr->result()); |
2965 __ mov(ip, Operand(Handle<Object>(instr->hydrogen()->cell()))); | 2971 __ mov(ip, Operand(Handle<Object>(instr->hydrogen()->cell()))); |
2966 __ ldr(result, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset)); | 2972 __ ldr(result, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset)); |
2967 if (instr->hydrogen()->RequiresHoleCheck()) { | 2973 if (instr->hydrogen()->RequiresHoleCheck()) { |
2968 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 2974 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3059 __ str(value, target); | 3065 __ str(value, target); |
3060 if (instr->hydrogen()->NeedsWriteBarrier()) { | 3066 if (instr->hydrogen()->NeedsWriteBarrier()) { |
3061 HType type = instr->hydrogen()->value()->type(); | 3067 HType type = instr->hydrogen()->value()->type(); |
3062 SmiCheck check_needed = | 3068 SmiCheck check_needed = |
3063 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 3069 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
3064 __ RecordWriteContextSlot(context, | 3070 __ RecordWriteContextSlot(context, |
3065 target.offset(), | 3071 target.offset(), |
3066 value, | 3072 value, |
3067 scratch, | 3073 scratch, |
3068 GetLinkRegisterState(), | 3074 GetLinkRegisterState(), |
3069 kSaveFPRegs, | 3075 GetSaveFPRegsMode(), |
3070 EMIT_REMEMBERED_SET, | 3076 EMIT_REMEMBERED_SET, |
3071 check_needed); | 3077 check_needed); |
3072 } | 3078 } |
3073 | 3079 |
3074 __ bind(&skip_assignment); | 3080 __ bind(&skip_assignment); |
3075 } | 3081 } |
3076 | 3082 |
3077 | 3083 |
3078 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 3084 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
3079 Register object = ToRegister(instr->object()); | 3085 Register object = ToRegister(instr->object()); |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3266 LLoadExternalArrayPointer* instr) { | 3272 LLoadExternalArrayPointer* instr) { |
3267 Register to_reg = ToRegister(instr->result()); | 3273 Register to_reg = ToRegister(instr->result()); |
3268 Register from_reg = ToRegister(instr->object()); | 3274 Register from_reg = ToRegister(instr->object()); |
3269 __ ldr(to_reg, FieldMemOperand(from_reg, | 3275 __ ldr(to_reg, FieldMemOperand(from_reg, |
3270 ExternalArray::kExternalPointerOffset)); | 3276 ExternalArray::kExternalPointerOffset)); |
3271 } | 3277 } |
3272 | 3278 |
3273 | 3279 |
3274 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { | 3280 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { |
3275 Register arguments = ToRegister(instr->arguments()); | 3281 Register arguments = ToRegister(instr->arguments()); |
3276 Register length = ToRegister(instr->length()); | |
3277 Register index = ToRegister(instr->index()); | |
3278 Register result = ToRegister(instr->result()); | 3282 Register result = ToRegister(instr->result()); |
3279 // There are two words between the frame pointer and the last argument. | 3283 if (instr->length()->IsConstantOperand() && |
3280 // Subtracting from length accounts for one of them add one more. | 3284 instr->index()->IsConstantOperand()) { |
3281 __ sub(length, length, index); | 3285 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
3282 __ add(length, length, Operand(1)); | 3286 int const_length = ToInteger32(LConstantOperand::cast(instr->length())); |
3283 __ ldr(result, MemOperand(arguments, length, LSL, kPointerSizeLog2)); | 3287 int index = (const_length - const_index) + 1; |
| 3288 __ ldr(result, MemOperand(arguments, index * kPointerSize)); |
| 3289 } else { |
| 3290 Register length = ToRegister(instr->length()); |
| 3291 Register index = ToRegister(instr->index()); |
| 3292 // There are two words between the frame pointer and the last argument. |
| 3293 // Subtracting from length accounts for one of them add one more. |
| 3294 __ sub(length, length, index); |
| 3295 __ add(length, length, Operand(1)); |
| 3296 __ ldr(result, MemOperand(arguments, length, LSL, kPointerSizeLog2)); |
| 3297 } |
3284 } | 3298 } |
3285 | 3299 |
3286 | 3300 |
3287 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { | 3301 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { |
3288 Register external_pointer = ToRegister(instr->elements()); | 3302 Register external_pointer = ToRegister(instr->elements()); |
3289 Register key = no_reg; | 3303 Register key = no_reg; |
3290 ElementsKind elements_kind = instr->elements_kind(); | 3304 ElementsKind elements_kind = instr->elements_kind(); |
3291 bool key_is_constant = instr->key()->IsConstantOperand(); | 3305 bool key_is_constant = instr->key()->IsConstantOperand(); |
3292 int constant_key = 0; | 3306 int constant_key = 0; |
3293 if (key_is_constant) { | 3307 if (key_is_constant) { |
(...skipping 916 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4210 } | 4224 } |
4211 | 4225 |
4212 | 4226 |
4213 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { | 4227 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { |
4214 ASSERT(ToRegister(instr->constructor()).is(r1)); | 4228 ASSERT(ToRegister(instr->constructor()).is(r1)); |
4215 ASSERT(ToRegister(instr->result()).is(r0)); | 4229 ASSERT(ToRegister(instr->result()).is(r0)); |
4216 ASSERT(FLAG_optimize_constructed_arrays); | 4230 ASSERT(FLAG_optimize_constructed_arrays); |
4217 | 4231 |
4218 __ mov(r0, Operand(instr->arity())); | 4232 __ mov(r0, Operand(instr->arity())); |
4219 __ mov(r2, Operand(instr->hydrogen()->property_cell())); | 4233 __ mov(r2, Operand(instr->hydrogen()->property_cell())); |
4220 Handle<Code> array_construct_code = | 4234 Object* cell_value = instr->hydrogen()->property_cell()->value(); |
4221 isolate()->builtins()->ArrayConstructCode(); | 4235 ElementsKind kind = static_cast<ElementsKind>(Smi::cast(cell_value)->value()); |
4222 | 4236 if (instr->arity() == 0) { |
4223 CallCode(array_construct_code, RelocInfo::CONSTRUCT_CALL, instr); | 4237 ArrayNoArgumentConstructorStub stub(kind); |
| 4238 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 4239 } else if (instr->arity() == 1) { |
| 4240 ArraySingleArgumentConstructorStub stub(kind); |
| 4241 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 4242 } else { |
| 4243 ArrayNArgumentsConstructorStub stub(kind); |
| 4244 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 4245 } |
4224 } | 4246 } |
4225 | 4247 |
4226 | 4248 |
4227 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { | 4249 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
4228 CallRuntime(instr->function(), instr->arity(), instr); | 4250 CallRuntime(instr->function(), instr->arity(), instr); |
4229 } | 4251 } |
4230 | 4252 |
4231 | 4253 |
4232 void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) { | 4254 void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) { |
4233 Register result = ToRegister(instr->result()); | 4255 Register result = ToRegister(instr->result()); |
(...skipping 14 matching lines...) Expand all Loading... |
4248 __ mov(scratch, Operand(instr->transition())); | 4270 __ mov(scratch, Operand(instr->transition())); |
4249 __ str(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); | 4271 __ str(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); |
4250 if (instr->hydrogen()->NeedsWriteBarrierForMap()) { | 4272 if (instr->hydrogen()->NeedsWriteBarrierForMap()) { |
4251 Register temp = ToRegister(instr->temp()); | 4273 Register temp = ToRegister(instr->temp()); |
4252 // Update the write barrier for the map field. | 4274 // Update the write barrier for the map field. |
4253 __ RecordWriteField(object, | 4275 __ RecordWriteField(object, |
4254 HeapObject::kMapOffset, | 4276 HeapObject::kMapOffset, |
4255 scratch, | 4277 scratch, |
4256 temp, | 4278 temp, |
4257 GetLinkRegisterState(), | 4279 GetLinkRegisterState(), |
4258 kSaveFPRegs, | 4280 GetSaveFPRegsMode(), |
4259 OMIT_REMEMBERED_SET, | 4281 OMIT_REMEMBERED_SET, |
4260 OMIT_SMI_CHECK); | 4282 OMIT_SMI_CHECK); |
4261 } | 4283 } |
4262 } | 4284 } |
4263 | 4285 |
4264 // Do the store. | 4286 // Do the store. |
4265 HType type = instr->hydrogen()->value()->type(); | 4287 HType type = instr->hydrogen()->value()->type(); |
4266 SmiCheck check_needed = | 4288 SmiCheck check_needed = |
4267 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 4289 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
4268 if (instr->is_in_object()) { | 4290 if (instr->is_in_object()) { |
4269 __ str(value, FieldMemOperand(object, offset)); | 4291 __ str(value, FieldMemOperand(object, offset)); |
4270 if (instr->hydrogen()->NeedsWriteBarrier()) { | 4292 if (instr->hydrogen()->NeedsWriteBarrier()) { |
4271 // Update the write barrier for the object for in-object properties. | 4293 // Update the write barrier for the object for in-object properties. |
4272 __ RecordWriteField(object, | 4294 __ RecordWriteField(object, |
4273 offset, | 4295 offset, |
4274 value, | 4296 value, |
4275 scratch, | 4297 scratch, |
4276 GetLinkRegisterState(), | 4298 GetLinkRegisterState(), |
4277 kSaveFPRegs, | 4299 GetSaveFPRegsMode(), |
4278 EMIT_REMEMBERED_SET, | 4300 EMIT_REMEMBERED_SET, |
4279 check_needed); | 4301 check_needed); |
4280 } | 4302 } |
4281 } else { | 4303 } else { |
4282 __ ldr(scratch, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 4304 __ ldr(scratch, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
4283 __ str(value, FieldMemOperand(scratch, offset)); | 4305 __ str(value, FieldMemOperand(scratch, offset)); |
4284 if (instr->hydrogen()->NeedsWriteBarrier()) { | 4306 if (instr->hydrogen()->NeedsWriteBarrier()) { |
4285 // Update the write barrier for the properties array. | 4307 // Update the write barrier for the properties array. |
4286 // object is used as a scratch register. | 4308 // object is used as a scratch register. |
4287 __ RecordWriteField(scratch, | 4309 __ RecordWriteField(scratch, |
4288 offset, | 4310 offset, |
4289 value, | 4311 value, |
4290 object, | 4312 object, |
4291 GetLinkRegisterState(), | 4313 GetLinkRegisterState(), |
4292 kSaveFPRegs, | 4314 GetSaveFPRegsMode(), |
4293 EMIT_REMEMBERED_SET, | 4315 EMIT_REMEMBERED_SET, |
4294 check_needed); | 4316 check_needed); |
4295 } | 4317 } |
4296 } | 4318 } |
4297 } | 4319 } |
4298 | 4320 |
4299 | 4321 |
4300 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { | 4322 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { |
4301 ASSERT(ToRegister(instr->object()).is(r1)); | 4323 ASSERT(ToRegister(instr->object()).is(r1)); |
4302 ASSERT(ToRegister(instr->value()).is(r0)); | 4324 ASSERT(ToRegister(instr->value()).is(r0)); |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4477 if (instr->hydrogen()->NeedsWriteBarrier()) { | 4499 if (instr->hydrogen()->NeedsWriteBarrier()) { |
4478 HType type = instr->hydrogen()->value()->type(); | 4500 HType type = instr->hydrogen()->value()->type(); |
4479 SmiCheck check_needed = | 4501 SmiCheck check_needed = |
4480 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 4502 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
4481 // Compute address of modified element and store it into key register. | 4503 // Compute address of modified element and store it into key register. |
4482 __ add(key, store_base, Operand(offset - kHeapObjectTag)); | 4504 __ add(key, store_base, Operand(offset - kHeapObjectTag)); |
4483 __ RecordWrite(elements, | 4505 __ RecordWrite(elements, |
4484 key, | 4506 key, |
4485 value, | 4507 value, |
4486 GetLinkRegisterState(), | 4508 GetLinkRegisterState(), |
4487 kSaveFPRegs, | 4509 GetSaveFPRegsMode(), |
4488 EMIT_REMEMBERED_SET, | 4510 EMIT_REMEMBERED_SET, |
4489 check_needed); | 4511 check_needed); |
4490 } | 4512 } |
4491 } | 4513 } |
4492 | 4514 |
4493 | 4515 |
4494 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) { | 4516 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) { |
4495 // By cases: external, fast double | 4517 // By cases: external, fast double |
4496 if (instr->is_external()) { | 4518 if (instr->is_external()) { |
4497 DoStoreKeyedExternalArray(instr); | 4519 DoStoreKeyedExternalArray(instr); |
(...skipping 1498 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5996 __ sub(scratch, result, Operand(index, LSL, kPointerSizeLog2 - kSmiTagSize)); | 6018 __ sub(scratch, result, Operand(index, LSL, kPointerSizeLog2 - kSmiTagSize)); |
5997 __ ldr(result, FieldMemOperand(scratch, | 6019 __ ldr(result, FieldMemOperand(scratch, |
5998 FixedArray::kHeaderSize - kPointerSize)); | 6020 FixedArray::kHeaderSize - kPointerSize)); |
5999 __ bind(&done); | 6021 __ bind(&done); |
6000 } | 6022 } |
6001 | 6023 |
6002 | 6024 |
6003 #undef __ | 6025 #undef __ |
6004 | 6026 |
6005 } } // namespace v8::internal | 6027 } } // namespace v8::internal |
OLD | NEW |