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

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

Issue 8404030: Version 3.7.1 (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/lithium-codegen-arm.h ('k') | src/arm/macro-assembler-arm.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 392 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 403
404 int LCodeGen::ToInteger32(LConstantOperand* op) const { 404 int LCodeGen::ToInteger32(LConstantOperand* op) const {
405 Handle<Object> value = chunk_->LookupLiteral(op); 405 Handle<Object> value = chunk_->LookupLiteral(op);
406 ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32()); 406 ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32());
407 ASSERT(static_cast<double>(static_cast<int32_t>(value->Number())) == 407 ASSERT(static_cast<double>(static_cast<int32_t>(value->Number())) ==
408 value->Number()); 408 value->Number());
409 return static_cast<int32_t>(value->Number()); 409 return static_cast<int32_t>(value->Number());
410 } 410 }
411 411
412 412
413 double LCodeGen::ToDouble(LConstantOperand* op) const {
414 Handle<Object> value = chunk_->LookupLiteral(op);
415 return value->Number();
416 }
417
418
413 Operand LCodeGen::ToOperand(LOperand* op) { 419 Operand LCodeGen::ToOperand(LOperand* op) {
414 if (op->IsConstantOperand()) { 420 if (op->IsConstantOperand()) {
415 LConstantOperand* const_op = LConstantOperand::cast(op); 421 LConstantOperand* const_op = LConstantOperand::cast(op);
416 Handle<Object> literal = chunk_->LookupLiteral(const_op); 422 Handle<Object> literal = chunk_->LookupLiteral(const_op);
417 Representation r = chunk_->LookupLiteralRepresentation(const_op); 423 Representation r = chunk_->LookupLiteralRepresentation(const_op);
418 if (r.IsInteger32()) { 424 if (r.IsInteger32()) {
419 ASSERT(literal->IsNumber()); 425 ASSERT(literal->IsNumber());
420 return Operand(static_cast<int32_t>(literal->Number())); 426 return Operand(static_cast<int32_t>(literal->Number()));
421 } else if (r.IsDouble()) { 427 } else if (r.IsDouble()) {
422 Abort("ToOperand Unsupported double immediate."); 428 Abort("ToOperand Unsupported double immediate.");
(...skipping 1275 matching lines...) Expand 10 before | Expand all | Expand 10 after
1698 break; 1704 break;
1699 case Token::IN: 1705 case Token::IN:
1700 case Token::INSTANCEOF: 1706 case Token::INSTANCEOF:
1701 default: 1707 default:
1702 UNREACHABLE(); 1708 UNREACHABLE();
1703 } 1709 }
1704 return cond; 1710 return cond;
1705 } 1711 }
1706 1712
1707 1713
1708 void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) {
1709 __ cmp(ToRegister(left), ToRegister(right));
1710 }
1711
1712
1713 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { 1714 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
1714 LOperand* left = instr->InputAt(0); 1715 LOperand* left = instr->InputAt(0);
1715 LOperand* right = instr->InputAt(1); 1716 LOperand* right = instr->InputAt(1);
1716 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1717 int false_block = chunk_->LookupDestination(instr->false_block_id());
1717 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1718 int true_block = chunk_->LookupDestination(instr->true_block_id());
1719 Condition cond = TokenToCondition(instr->op(), false);
1718 1720
1719 if (instr->is_double()) { 1721 if (left->IsConstantOperand() && right->IsConstantOperand()) {
1720 // Compare left and right as doubles and load the 1722 // We can statically evaluate the comparison.
1721 // resulting flags into the normal status register. 1723 double left_val = ToDouble(LConstantOperand::cast(left));
1722 __ VFPCompareAndSetFlags(ToDoubleRegister(left), ToDoubleRegister(right)); 1724 double right_val = ToDouble(LConstantOperand::cast(right));
1723 // If a NaN is involved, i.e. the result is unordered (V set), 1725 int next_block =
1724 // jump to false block label. 1726 EvalComparison(instr->op(), left_val, right_val) ? true_block
1725 __ b(vs, chunk_->GetAssemblyLabel(false_block)); 1727 : false_block;
1728 EmitGoto(next_block);
1726 } else { 1729 } else {
1727 EmitCmpI(left, right); 1730 if (instr->is_double()) {
1731 // Compare left and right operands as doubles and load the
1732 // resulting flags into the normal status register.
1733 __ VFPCompareAndSetFlags(ToDoubleRegister(left), ToDoubleRegister(right));
1734 // If a NaN is involved, i.e. the result is unordered (V set),
1735 // jump to false block label.
1736 __ b(vs, chunk_->GetAssemblyLabel(false_block));
1737 } else {
1738 if (right->IsConstantOperand()) {
1739 __ cmp(ToRegister(left),
1740 Operand(ToInteger32(LConstantOperand::cast(right))));
1741 } else if (left->IsConstantOperand()) {
1742 __ cmp(ToRegister(right),
1743 Operand(ToInteger32(LConstantOperand::cast(left))));
1744 // We transposed the operands. Reverse the condition.
1745 cond = ReverseCondition(cond);
1746 } else {
1747 __ cmp(ToRegister(left), ToRegister(right));
1748 }
1749 }
1750 EmitBranch(true_block, false_block, cond);
1728 } 1751 }
1729
1730 Condition cc = TokenToCondition(instr->op(), instr->is_double());
1731 EmitBranch(true_block, false_block, cc);
1732 } 1752 }
1733 1753
1734 1754
1735 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) { 1755 void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) {
1736 Register left = ToRegister(instr->InputAt(0)); 1756 Register left = ToRegister(instr->InputAt(0));
1737 Register right = ToRegister(instr->InputAt(1)); 1757 Register right = ToRegister(instr->InputAt(1));
1738 int false_block = chunk_->LookupDestination(instr->false_block_id()); 1758 int false_block = chunk_->LookupDestination(instr->false_block_id());
1739 int true_block = chunk_->LookupDestination(instr->true_block_id()); 1759 int true_block = chunk_->LookupDestination(instr->true_block_id());
1740 1760
1741 __ cmp(left, Operand(right)); 1761 __ cmp(left, Operand(right));
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after
2169 2189
2170 2190
2171 void LCodeGen::DoCmpT(LCmpT* instr) { 2191 void LCodeGen::DoCmpT(LCmpT* instr) {
2172 Token::Value op = instr->op(); 2192 Token::Value op = instr->op();
2173 2193
2174 Handle<Code> ic = CompareIC::GetUninitialized(op); 2194 Handle<Code> ic = CompareIC::GetUninitialized(op);
2175 CallCode(ic, RelocInfo::CODE_TARGET, instr); 2195 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2176 __ cmp(r0, Operand(0)); // This instruction also signals no smi code inlined. 2196 __ cmp(r0, Operand(0)); // This instruction also signals no smi code inlined.
2177 2197
2178 Condition condition = ComputeCompareCondition(op); 2198 Condition condition = ComputeCompareCondition(op);
2179 if (op == Token::GT || op == Token::LTE) {
2180 condition = ReverseCondition(condition);
2181 }
2182 __ LoadRoot(ToRegister(instr->result()), 2199 __ LoadRoot(ToRegister(instr->result()),
2183 Heap::kTrueValueRootIndex, 2200 Heap::kTrueValueRootIndex,
2184 condition); 2201 condition);
2185 __ LoadRoot(ToRegister(instr->result()), 2202 __ LoadRoot(ToRegister(instr->result()),
2186 Heap::kFalseValueRootIndex, 2203 Heap::kFalseValueRootIndex,
2187 NegateCondition(condition)); 2204 NegateCondition(condition));
2188 } 2205 }
2189 2206
2190 2207
2191 void LCodeGen::DoReturn(LReturn* instr) { 2208 void LCodeGen::DoReturn(LReturn* instr) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2244 FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); 2261 FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset));
2245 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 2262 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
2246 __ cmp(scratch2, ip); 2263 __ cmp(scratch2, ip);
2247 DeoptimizeIf(eq, instr->environment()); 2264 DeoptimizeIf(eq, instr->environment());
2248 } 2265 }
2249 2266
2250 // Store the value. 2267 // Store the value.
2251 __ str(value, FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); 2268 __ str(value, FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset));
2252 2269
2253 // Cells are always in the remembered set. 2270 // Cells are always in the remembered set.
2254 __ RecordWriteField(scratch, 2271 if (instr->hydrogen()->NeedsWriteBarrier()) {
2255 JSGlobalPropertyCell::kValueOffset, 2272 HType type = instr->hydrogen()->value()->type();
2256 value, 2273 SmiCheck check_needed =
2257 scratch2, 2274 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
2258 kLRHasBeenSaved, 2275 __ RecordWriteField(scratch,
2259 kSaveFPRegs, 2276 JSGlobalPropertyCell::kValueOffset,
2260 OMIT_REMEMBERED_SET); 2277 value,
2278 scratch2,
2279 kLRHasBeenSaved,
2280 kSaveFPRegs,
2281 OMIT_REMEMBERED_SET,
2282 check_needed);
2283 }
2261 } 2284 }
2262 2285
2263 2286
2264 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { 2287 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) {
2265 ASSERT(ToRegister(instr->global_object()).is(r1)); 2288 ASSERT(ToRegister(instr->global_object()).is(r1));
2266 ASSERT(ToRegister(instr->value()).is(r0)); 2289 ASSERT(ToRegister(instr->value()).is(r0));
2267 2290
2268 __ mov(r2, Operand(instr->name())); 2291 __ mov(r2, Operand(instr->name()));
2269 Handle<Code> ic = instr->strict_mode() 2292 Handle<Code> ic = instr->strict_mode()
2270 ? isolate()->builtins()->StoreIC_Initialize_Strict() 2293 ? isolate()->builtins()->StoreIC_Initialize_Strict()
2271 : isolate()->builtins()->StoreIC_Initialize(); 2294 : isolate()->builtins()->StoreIC_Initialize();
2272 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); 2295 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr);
2273 } 2296 }
2274 2297
2275 2298
2276 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { 2299 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
2277 Register context = ToRegister(instr->context()); 2300 Register context = ToRegister(instr->context());
2278 Register result = ToRegister(instr->result()); 2301 Register result = ToRegister(instr->result());
2279 __ ldr(result, ContextOperand(context, instr->slot_index())); 2302 __ ldr(result, ContextOperand(context, instr->slot_index()));
2280 } 2303 }
2281 2304
2282 2305
2283 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { 2306 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
2284 Register context = ToRegister(instr->context()); 2307 Register context = ToRegister(instr->context());
2285 Register value = ToRegister(instr->value()); 2308 Register value = ToRegister(instr->value());
2286 MemOperand target = ContextOperand(context, instr->slot_index()); 2309 MemOperand target = ContextOperand(context, instr->slot_index());
2287 __ str(value, target); 2310 __ str(value, target);
2288 if (instr->needs_write_barrier()) { 2311 if (instr->hydrogen()->NeedsWriteBarrier()) {
2312 HType type = instr->hydrogen()->value()->type();
2313 SmiCheck check_needed =
2314 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
2289 __ RecordWriteContextSlot(context, 2315 __ RecordWriteContextSlot(context,
2290 target.offset(), 2316 target.offset(),
2291 value, 2317 value,
2292 scratch0(), 2318 scratch0(),
2293 kLRHasBeenSaved, 2319 kLRHasBeenSaved,
2294 kSaveFPRegs); 2320 kSaveFPRegs,
2321 EMIT_REMEMBERED_SET,
2322 check_needed);
2295 } 2323 }
2296 } 2324 }
2297 2325
2298 2326
2299 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { 2327 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
2300 Register object = ToRegister(instr->InputAt(0)); 2328 Register object = ToRegister(instr->InputAt(0));
2301 Register result = ToRegister(instr->result()); 2329 Register result = ToRegister(instr->result());
2302 if (instr->hydrogen()->is_in_object()) { 2330 if (instr->hydrogen()->is_in_object()) {
2303 __ ldr(result, FieldMemOperand(object, instr->hydrogen()->offset())); 2331 __ ldr(result, FieldMemOperand(object, instr->hydrogen()->offset()));
2304 } else { 2332 } else {
2305 __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); 2333 __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
2306 __ ldr(result, FieldMemOperand(result, instr->hydrogen()->offset())); 2334 __ ldr(result, FieldMemOperand(result, instr->hydrogen()->offset()));
2307 } 2335 }
2308 } 2336 }
2309 2337
2310 2338
2311 void LCodeGen::EmitLoadFieldOrConstantFunction(Register result, 2339 void LCodeGen::EmitLoadFieldOrConstantFunction(Register result,
2312 Register object, 2340 Register object,
2313 Handle<Map> type, 2341 Handle<Map> type,
2314 Handle<String> name) { 2342 Handle<String> name) {
2315 LookupResult lookup; 2343 LookupResult lookup(isolate());
2316 type->LookupInDescriptors(NULL, *name, &lookup); 2344 type->LookupInDescriptors(NULL, *name, &lookup);
2317 ASSERT(lookup.IsProperty() && 2345 ASSERT(lookup.IsProperty() &&
2318 (lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION)); 2346 (lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION));
2319 if (lookup.type() == FIELD) { 2347 if (lookup.type() == FIELD) {
2320 int index = lookup.GetLocalFieldIndexFromMap(*type); 2348 int index = lookup.GetLocalFieldIndexFromMap(*type);
2321 int offset = index * kPointerSize; 2349 int offset = index * kPointerSize;
2322 if (index < 0) { 2350 if (index < 0) {
2323 // Negative property indices are in-object properties, indexed 2351 // Negative property indices are in-object properties, indexed
2324 // from the end of the fixed part of the object. 2352 // from the end of the fixed part of the object.
2325 __ ldr(result, FieldMemOperand(object, offset + type->instance_size())); 2353 __ ldr(result, FieldMemOperand(object, offset + type->instance_size()));
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after
2771 Abort("DoPushArgument not implemented for double type."); 2799 Abort("DoPushArgument not implemented for double type.");
2772 } else { 2800 } else {
2773 Register argument_reg = EmitLoadRegister(argument, ip); 2801 Register argument_reg = EmitLoadRegister(argument, ip);
2774 __ push(argument_reg); 2802 __ push(argument_reg);
2775 } 2803 }
2776 } 2804 }
2777 2805
2778 2806
2779 void LCodeGen::DoThisFunction(LThisFunction* instr) { 2807 void LCodeGen::DoThisFunction(LThisFunction* instr) {
2780 Register result = ToRegister(instr->result()); 2808 Register result = ToRegister(instr->result());
2781 __ ldr(result, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 2809 LoadHeapObject(result, instr->hydrogen()->closure());
2782 } 2810 }
2783 2811
2784 2812
2785 void LCodeGen::DoContext(LContext* instr) { 2813 void LCodeGen::DoContext(LContext* instr) {
2786 Register result = ToRegister(instr->result()); 2814 Register result = ToRegister(instr->result());
2787 __ mov(result, cp); 2815 __ mov(result, cp);
2788 } 2816 }
2789 2817
2790 2818
2791 void LCodeGen::DoOuterContext(LOuterContext* instr) { 2819 void LCodeGen::DoOuterContext(LOuterContext* instr) {
(...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after
3290 int offset = instr->offset(); 3318 int offset = instr->offset();
3291 3319
3292 ASSERT(!object.is(value)); 3320 ASSERT(!object.is(value));
3293 3321
3294 if (!instr->transition().is_null()) { 3322 if (!instr->transition().is_null()) {
3295 __ mov(scratch, Operand(instr->transition())); 3323 __ mov(scratch, Operand(instr->transition()));
3296 __ str(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); 3324 __ str(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
3297 } 3325 }
3298 3326
3299 // Do the store. 3327 // Do the store.
3328 HType type = instr->hydrogen()->value()->type();
3329 SmiCheck check_needed =
3330 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
3300 if (instr->is_in_object()) { 3331 if (instr->is_in_object()) {
3301 __ str(value, FieldMemOperand(object, offset)); 3332 __ str(value, FieldMemOperand(object, offset));
3302 if (instr->needs_write_barrier()) { 3333 if (instr->hydrogen()->NeedsWriteBarrier()) {
3303 // Update the write barrier for the object for in-object properties. 3334 // Update the write barrier for the object for in-object properties.
3304 __ RecordWriteField( 3335 __ RecordWriteField(object,
3305 object, offset, value, scratch, kLRHasBeenSaved, kSaveFPRegs); 3336 offset,
3337 value,
3338 scratch,
3339 kLRHasBeenSaved,
3340 kSaveFPRegs,
3341 EMIT_REMEMBERED_SET,
3342 check_needed);
3306 } 3343 }
3307 } else { 3344 } else {
3308 __ ldr(scratch, FieldMemOperand(object, JSObject::kPropertiesOffset)); 3345 __ ldr(scratch, FieldMemOperand(object, JSObject::kPropertiesOffset));
3309 __ str(value, FieldMemOperand(scratch, offset)); 3346 __ str(value, FieldMemOperand(scratch, offset));
3310 if (instr->needs_write_barrier()) { 3347 if (instr->hydrogen()->NeedsWriteBarrier()) {
3311 // Update the write barrier for the properties array. 3348 // Update the write barrier for the properties array.
3312 // object is used as a scratch register. 3349 // object is used as a scratch register.
3313 __ RecordWriteField( 3350 __ RecordWriteField(scratch,
3314 scratch, offset, value, object, kLRHasBeenSaved, kSaveFPRegs); 3351 offset,
3352 value,
3353 object,
3354 kLRHasBeenSaved,
3355 kSaveFPRegs,
3356 EMIT_REMEMBERED_SET,
3357 check_needed);
3315 } 3358 }
3316 } 3359 }
3317 } 3360 }
3318 3361
3319 3362
3320 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { 3363 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
3321 ASSERT(ToRegister(instr->object()).is(r1)); 3364 ASSERT(ToRegister(instr->object()).is(r1));
3322 ASSERT(ToRegister(instr->value()).is(r0)); 3365 ASSERT(ToRegister(instr->value()).is(r0));
3323 3366
3324 // Name is always in r2. 3367 // Name is always in r2.
(...skipping 30 matching lines...) Expand all
3355 LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); 3398 LConstantOperand* const_operand = LConstantOperand::cast(instr->key());
3356 int offset = 3399 int offset =
3357 ToInteger32(const_operand) * kPointerSize + FixedArray::kHeaderSize; 3400 ToInteger32(const_operand) * kPointerSize + FixedArray::kHeaderSize;
3358 __ str(value, FieldMemOperand(elements, offset)); 3401 __ str(value, FieldMemOperand(elements, offset));
3359 } else { 3402 } else {
3360 __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); 3403 __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2));
3361 __ str(value, FieldMemOperand(scratch, FixedArray::kHeaderSize)); 3404 __ str(value, FieldMemOperand(scratch, FixedArray::kHeaderSize));
3362 } 3405 }
3363 3406
3364 if (instr->hydrogen()->NeedsWriteBarrier()) { 3407 if (instr->hydrogen()->NeedsWriteBarrier()) {
3408 HType type = instr->hydrogen()->value()->type();
3409 SmiCheck check_needed =
3410 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
3365 // Compute address of modified element and store it into key register. 3411 // Compute address of modified element and store it into key register.
3366 __ add(key, scratch, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 3412 __ add(key, scratch, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
3367 __ RecordWrite(elements, key, value, kLRHasBeenSaved, kSaveFPRegs); 3413 __ RecordWrite(elements,
3414 key,
3415 value,
3416 kLRHasBeenSaved,
3417 kSaveFPRegs,
3418 EMIT_REMEMBERED_SET,
3419 check_needed);
3368 } 3420 }
3369 } 3421 }
3370 3422
3371 3423
3372 void LCodeGen::DoStoreKeyedFastDoubleElement( 3424 void LCodeGen::DoStoreKeyedFastDoubleElement(
3373 LStoreKeyedFastDoubleElement* instr) { 3425 LStoreKeyedFastDoubleElement* instr) {
3374 DwVfpRegister value = ToDoubleRegister(instr->value()); 3426 DwVfpRegister value = ToDoubleRegister(instr->value());
3375 Register elements = ToRegister(instr->elements()); 3427 Register elements = ToRegister(instr->elements());
3376 Register key = no_reg; 3428 Register key = no_reg;
3377 Register scratch = scratch0(); 3429 Register scratch = scratch0();
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
3480 ASSERT(ToRegister(instr->key()).is(r1)); 3532 ASSERT(ToRegister(instr->key()).is(r1));
3481 ASSERT(ToRegister(instr->value()).is(r0)); 3533 ASSERT(ToRegister(instr->value()).is(r0));
3482 3534
3483 Handle<Code> ic = instr->strict_mode() 3535 Handle<Code> ic = instr->strict_mode()
3484 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() 3536 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
3485 : isolate()->builtins()->KeyedStoreIC_Initialize(); 3537 : isolate()->builtins()->KeyedStoreIC_Initialize();
3486 CallCode(ic, RelocInfo::CODE_TARGET, instr); 3538 CallCode(ic, RelocInfo::CODE_TARGET, instr);
3487 } 3539 }
3488 3540
3489 3541
3542 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
3543 Register object_reg = ToRegister(instr->object());
3544 Register new_map_reg = ToRegister(instr->new_map_reg());
3545 Register scratch = scratch0();
3546
3547 Handle<Map> from_map = instr->original_map();
3548 Handle<Map> to_map = instr->transitioned_map();
3549 ElementsKind from_kind = from_map->elements_kind();
3550 ElementsKind to_kind = to_map->elements_kind();
3551
3552 Label not_applicable;
3553 __ ldr(scratch, FieldMemOperand(object_reg, HeapObject::kMapOffset));
3554 __ cmp(scratch, Operand(from_map));
3555 __ b(ne, &not_applicable);
3556 __ mov(new_map_reg, Operand(to_map));
3557 if (from_kind == FAST_SMI_ONLY_ELEMENTS && to_kind == FAST_ELEMENTS) {
3558 __ str(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset));
3559 // Write barrier.
3560 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg,
3561 scratch, kLRHasBeenSaved, kDontSaveFPRegs);
3562 } else if (from_kind == FAST_SMI_ONLY_ELEMENTS &&
3563 to_kind == FAST_DOUBLE_ELEMENTS) {
3564 Register fixed_object_reg = ToRegister(instr->temp_reg());
3565 ASSERT(fixed_object_reg.is(r2));
3566 ASSERT(new_map_reg.is(r3));
3567 __ mov(fixed_object_reg, object_reg);
3568 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(),
3569 RelocInfo::CODE_TARGET, instr);
3570 } else if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) {
3571 Register fixed_object_reg = ToRegister(instr->temp_reg());
3572 ASSERT(fixed_object_reg.is(r2));
3573 ASSERT(new_map_reg.is(r3));
3574 __ mov(fixed_object_reg, object_reg);
3575 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(),
3576 RelocInfo::CODE_TARGET, instr);
3577 } else {
3578 UNREACHABLE();
3579 }
3580 __ bind(&not_applicable);
3581 }
3582
3583
3490 void LCodeGen::DoStringAdd(LStringAdd* instr) { 3584 void LCodeGen::DoStringAdd(LStringAdd* instr) {
3491 __ push(ToRegister(instr->left())); 3585 __ push(ToRegister(instr->left()));
3492 __ push(ToRegister(instr->right())); 3586 __ push(ToRegister(instr->right()));
3493 StringAddStub stub(NO_STRING_CHECK_IN_STUB); 3587 StringAddStub stub(NO_STRING_CHECK_IN_STUB);
3494 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 3588 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
3495 } 3589 }
3496 3590
3497 3591
3498 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { 3592 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
3499 class DeferredStringCharCodeAt: public LDeferredCode { 3593 class DeferredStringCharCodeAt: public LDeferredCode {
(...skipping 696 matching lines...) Expand 10 before | Expand all | Expand 10 after
4196 } 4290 }
4197 4291
4198 // Check the holder map. 4292 // Check the holder map.
4199 __ ldr(temp2, FieldMemOperand(temp1, HeapObject::kMapOffset)); 4293 __ ldr(temp2, FieldMemOperand(temp1, HeapObject::kMapOffset));
4200 __ cmp(temp2, Operand(Handle<Map>(current_prototype->map()))); 4294 __ cmp(temp2, Operand(Handle<Map>(current_prototype->map())));
4201 DeoptimizeIf(ne, instr->environment()); 4295 DeoptimizeIf(ne, instr->environment());
4202 } 4296 }
4203 4297
4204 4298
4205 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { 4299 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
4300 Handle<FixedArray> constant_elements = instr->hydrogen()->constant_elements();
4301 ASSERT_EQ(2, constant_elements->length());
4302 ElementsKind constant_elements_kind =
4303 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
4304
4206 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 4305 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
4207 __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); 4306 __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
4208 __ mov(r2, Operand(Smi::FromInt(instr->hydrogen()->literal_index()))); 4307 __ mov(r2, Operand(Smi::FromInt(instr->hydrogen()->literal_index())));
4209 __ mov(r1, Operand(instr->hydrogen()->constant_elements())); 4308 __ mov(r1, Operand(constant_elements));
4210 __ Push(r3, r2, r1); 4309 __ Push(r3, r2, r1);
4211 4310
4212 // Pick the right runtime function or stub to call. 4311 // Pick the right runtime function or stub to call.
4213 int length = instr->hydrogen()->length(); 4312 int length = instr->hydrogen()->length();
4214 if (instr->hydrogen()->IsCopyOnWrite()) { 4313 if (instr->hydrogen()->IsCopyOnWrite()) {
4215 ASSERT(instr->hydrogen()->depth() == 1); 4314 ASSERT(instr->hydrogen()->depth() == 1);
4216 FastCloneShallowArrayStub::Mode mode = 4315 FastCloneShallowArrayStub::Mode mode =
4217 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS; 4316 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS;
4218 FastCloneShallowArrayStub stub(mode, length); 4317 FastCloneShallowArrayStub stub(mode, length);
4219 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 4318 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4220 } else if (instr->hydrogen()->depth() > 1) { 4319 } else if (instr->hydrogen()->depth() > 1) {
4221 CallRuntime(Runtime::kCreateArrayLiteral, 3, instr); 4320 CallRuntime(Runtime::kCreateArrayLiteral, 3, instr);
4222 } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { 4321 } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
4223 CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr); 4322 CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr);
4224 } else { 4323 } else {
4225 FastCloneShallowArrayStub::Mode mode = 4324 FastCloneShallowArrayStub::Mode mode =
4226 FastCloneShallowArrayStub::CLONE_ELEMENTS; 4325 constant_elements_kind == FAST_DOUBLE_ELEMENTS
4326 ? FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS
4327 : FastCloneShallowArrayStub::CLONE_ELEMENTS;
4227 FastCloneShallowArrayStub stub(mode, length); 4328 FastCloneShallowArrayStub stub(mode, length);
4228 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 4329 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4229 } 4330 }
4230 } 4331 }
4231 4332
4232 4333
4233 void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) { 4334 void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) {
4234 __ ldr(r4, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 4335 __ ldr(r4, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
4235 __ ldr(r4, FieldMemOperand(r4, JSFunction::kLiteralsOffset)); 4336 __ ldr(r4, FieldMemOperand(r4, JSFunction::kLiteralsOffset));
4236 __ mov(r3, Operand(Smi::FromInt(instr->hydrogen()->literal_index()))); 4337 __ mov(r3, Operand(Smi::FromInt(instr->hydrogen()->literal_index())));
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
4308 } 4409 }
4309 } 4410 }
4310 4411
4311 4412
4312 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { 4413 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
4313 // Use the fast case closure allocation code that allocates in new 4414 // Use the fast case closure allocation code that allocates in new
4314 // space for nested functions that don't need literals cloning. 4415 // space for nested functions that don't need literals cloning.
4315 Handle<SharedFunctionInfo> shared_info = instr->shared_info(); 4416 Handle<SharedFunctionInfo> shared_info = instr->shared_info();
4316 bool pretenure = instr->hydrogen()->pretenure(); 4417 bool pretenure = instr->hydrogen()->pretenure();
4317 if (!pretenure && shared_info->num_literals() == 0) { 4418 if (!pretenure && shared_info->num_literals() == 0) {
4318 FastNewClosureStub stub( 4419 FastNewClosureStub stub(shared_info->strict_mode_flag());
4319 shared_info->strict_mode() ? kStrictMode : kNonStrictMode);
4320 __ mov(r1, Operand(shared_info)); 4420 __ mov(r1, Operand(shared_info));
4321 __ push(r1); 4421 __ push(r1);
4322 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 4422 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4323 } else { 4423 } else {
4324 __ mov(r2, Operand(shared_info)); 4424 __ mov(r2, Operand(shared_info));
4325 __ mov(r1, Operand(pretenure 4425 __ mov(r1, Operand(pretenure
4326 ? factory()->true_value() 4426 ? factory()->true_value()
4327 : factory()->false_value())); 4427 : factory()->false_value()));
4328 __ Push(cp, r2, r1); 4428 __ Push(cp, r2, r1);
4329 CallRuntime(Runtime::kNewClosure, 3, instr); 4429 CallRuntime(Runtime::kNewClosure, 3, instr);
(...skipping 12 matching lines...) Expand all
4342 Register input = ToRegister(instr->InputAt(0)); 4442 Register input = ToRegister(instr->InputAt(0));
4343 int true_block = chunk_->LookupDestination(instr->true_block_id()); 4443 int true_block = chunk_->LookupDestination(instr->true_block_id());
4344 int false_block = chunk_->LookupDestination(instr->false_block_id()); 4444 int false_block = chunk_->LookupDestination(instr->false_block_id());
4345 Label* true_label = chunk_->GetAssemblyLabel(true_block); 4445 Label* true_label = chunk_->GetAssemblyLabel(true_block);
4346 Label* false_label = chunk_->GetAssemblyLabel(false_block); 4446 Label* false_label = chunk_->GetAssemblyLabel(false_block);
4347 4447
4348 Condition final_branch_condition = EmitTypeofIs(true_label, 4448 Condition final_branch_condition = EmitTypeofIs(true_label,
4349 false_label, 4449 false_label,
4350 input, 4450 input,
4351 instr->type_literal()); 4451 instr->type_literal());
4352 4452 if (final_branch_condition != kNoCondition) {
4353 EmitBranch(true_block, false_block, final_branch_condition); 4453 EmitBranch(true_block, false_block, final_branch_condition);
4454 }
4354 } 4455 }
4355 4456
4356 4457
4357 Condition LCodeGen::EmitTypeofIs(Label* true_label, 4458 Condition LCodeGen::EmitTypeofIs(Label* true_label,
4358 Label* false_label, 4459 Label* false_label,
4359 Register input, 4460 Register input,
4360 Handle<String> type_name) { 4461 Handle<String> type_name) {
4361 Condition final_branch_condition = kNoCondition; 4462 Condition final_branch_condition = kNoCondition;
4362 Register scratch = scratch0(); 4463 Register scratch = scratch0();
4363 if (type_name->Equals(heap()->number_symbol())) { 4464 if (type_name->Equals(heap()->number_symbol())) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
4413 FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); 4514 FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
4414 __ b(lt, false_label); 4515 __ b(lt, false_label);
4415 __ CompareInstanceType(input, scratch, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); 4516 __ CompareInstanceType(input, scratch, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
4416 __ b(gt, false_label); 4517 __ b(gt, false_label);
4417 // Check for undetectable objects => false. 4518 // Check for undetectable objects => false.
4418 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset)); 4519 __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
4419 __ tst(ip, Operand(1 << Map::kIsUndetectable)); 4520 __ tst(ip, Operand(1 << Map::kIsUndetectable));
4420 final_branch_condition = eq; 4521 final_branch_condition = eq;
4421 4522
4422 } else { 4523 } else {
4423 final_branch_condition = ne;
4424 __ b(false_label); 4524 __ b(false_label);
4425 // A dead branch instruction will be generated after this point.
4426 } 4525 }
4427 4526
4428 return final_branch_condition; 4527 return final_branch_condition;
4429 } 4528 }
4430 4529
4431 4530
4432 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { 4531 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
4433 Register temp1 = ToRegister(instr->TempAt(0)); 4532 Register temp1 = ToRegister(instr->TempAt(0));
4434 int true_block = chunk_->LookupDestination(instr->true_block_id()); 4533 int true_block = chunk_->LookupDestination(instr->true_block_id());
4435 int false_block = chunk_->LookupDestination(instr->false_block_id()); 4534 int false_block = chunk_->LookupDestination(instr->false_block_id());
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
4566 ASSERT(osr_pc_offset_ == -1); 4665 ASSERT(osr_pc_offset_ == -1);
4567 osr_pc_offset_ = masm()->pc_offset(); 4666 osr_pc_offset_ = masm()->pc_offset();
4568 } 4667 }
4569 4668
4570 4669
4571 4670
4572 4671
4573 #undef __ 4672 #undef __
4574 4673
4575 } } // namespace v8::internal 4674 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/lithium-codegen-arm.h ('k') | src/arm/macro-assembler-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698