OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 771 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
782 code->set_stack_slots(GetStackSlotCount()); | 782 code->set_stack_slots(GetStackSlotCount()); |
783 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); | 783 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); |
784 if (FLAG_weak_embedded_maps_in_optimized_code) { | 784 if (FLAG_weak_embedded_maps_in_optimized_code) { |
785 RegisterDependentCodeForEmbeddedMaps(code); | 785 RegisterDependentCodeForEmbeddedMaps(code); |
786 } | 786 } |
787 PopulateDeoptimizationData(code); | 787 PopulateDeoptimizationData(code); |
788 info()->CommitDependencies(code); | 788 info()->CommitDependencies(code); |
789 } | 789 } |
790 | 790 |
791 | 791 |
792 void LCodeGen::Abort(const char* reason) { | 792 void LCodeGen::Abort(BailoutReason reason) { |
793 info()->set_bailout_reason(reason); | 793 info()->set_bailout_reason(reason); |
794 status_ = ABORTED; | 794 status_ = ABORTED; |
795 } | 795 } |
796 | 796 |
797 | 797 |
798 void LCodeGen::Comment(const char* format, ...) { | 798 void LCodeGen::Comment(const char* format, ...) { |
799 if (!FLAG_code_comments) return; | 799 if (!FLAG_code_comments) return; |
800 char buffer[4 * KB]; | 800 char buffer[4 * KB]; |
801 StringBuilder builder(buffer, ARRAY_SIZE(buffer)); | 801 StringBuilder builder(buffer, ARRAY_SIZE(buffer)); |
802 va_list arguments; | 802 va_list arguments; |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
893 void LCodeGen::Deoptimize(LEnvironment* environment, | 893 void LCodeGen::Deoptimize(LEnvironment* environment, |
894 Deoptimizer::BailoutType bailout_type) { | 894 Deoptimizer::BailoutType bailout_type) { |
895 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 895 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
896 ASSERT(environment->HasBeenRegistered()); | 896 ASSERT(environment->HasBeenRegistered()); |
897 ASSERT(info()->IsOptimizing() || info()->IsStub()); | 897 ASSERT(info()->IsOptimizing() || info()->IsStub()); |
898 int id = environment->deoptimization_index(); | 898 int id = environment->deoptimization_index(); |
899 Address entry = | 899 Address entry = |
900 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); | 900 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); |
901 | 901 |
902 if (entry == NULL) { | 902 if (entry == NULL) { |
903 Abort("bailout was not prepared"); | 903 Abort(kBailoutWasNotPrepared); |
904 return; | 904 return; |
905 } | 905 } |
906 | 906 |
907 ASSERT(FLAG_deopt_every_n_times < 2); // Other values not supported on A64. | 907 ASSERT(FLAG_deopt_every_n_times < 2); // Other values not supported on A64. |
908 if (FLAG_deopt_every_n_times == 1 && | 908 if (FLAG_deopt_every_n_times == 1 && |
909 !info()->IsStub() && | 909 !info()->IsStub() && |
910 info()->opt_count() == id) { | 910 info()->opt_count() == id) { |
911 ASSERT(frame_is_built_); | 911 ASSERT(frame_is_built_); |
912 __ Call(entry, RelocInfo::RUNTIME_ENTRY); | 912 __ Call(entry, RelocInfo::RUNTIME_ENTRY); |
913 return; | 913 return; |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1064 LConstantOperand* const_op = LConstantOperand::cast(op); | 1064 LConstantOperand* const_op = LConstantOperand::cast(op); |
1065 HConstant* constant = chunk()->LookupConstant(const_op); | 1065 HConstant* constant = chunk()->LookupConstant(const_op); |
1066 Representation r = chunk_->LookupLiteralRepresentation(const_op); | 1066 Representation r = chunk_->LookupLiteralRepresentation(const_op); |
1067 if (r.IsSmi()) { | 1067 if (r.IsSmi()) { |
1068 ASSERT(constant->HasSmiValue()); | 1068 ASSERT(constant->HasSmiValue()); |
1069 return Operand(Smi::FromInt(constant->Integer32Value())); | 1069 return Operand(Smi::FromInt(constant->Integer32Value())); |
1070 } else if (r.IsInteger32()) { | 1070 } else if (r.IsInteger32()) { |
1071 ASSERT(constant->HasInteger32Value()); | 1071 ASSERT(constant->HasInteger32Value()); |
1072 return Operand(constant->Integer32Value()); | 1072 return Operand(constant->Integer32Value()); |
1073 } else if (r.IsDouble()) { | 1073 } else if (r.IsDouble()) { |
1074 Abort("ToOperand unsupported double immediate."); | 1074 Abort(kToOperandUnsupportedDoubleImmediate); |
1075 } | 1075 } |
1076 ASSERT(r.IsTagged()); | 1076 ASSERT(r.IsTagged()); |
1077 return Operand(constant->handle()); | 1077 return Operand(constant->handle()); |
1078 } else if (op->IsRegister()) { | 1078 } else if (op->IsRegister()) { |
1079 return Operand(ToRegister(op)); | 1079 return Operand(ToRegister(op)); |
1080 } else if (op->IsDoubleRegister()) { | 1080 } else if (op->IsDoubleRegister()) { |
1081 Abort("ToOperand IsDoubleRegister unimplemented"); | 1081 Abort(kToOperandIsDoubleRegisterUnimplemented); |
1082 return Operand(0); | 1082 return Operand(0); |
1083 } | 1083 } |
1084 // Stack slots not implemented, use ToMemOperand instead. | 1084 // Stack slots not implemented, use ToMemOperand instead. |
1085 UNREACHABLE(); | 1085 UNREACHABLE(); |
1086 return Operand(0); | 1086 return Operand(0); |
1087 } | 1087 } |
1088 | 1088 |
1089 | 1089 |
1090 Operand LCodeGen::ToOperand32I(LOperand* op) { | 1090 Operand LCodeGen::ToOperand32I(LOperand* op) { |
1091 return ToOperand32(op, SIGNED_INT32); | 1091 return ToOperand32(op, SIGNED_INT32); |
(...skipping 13 matching lines...) Expand all Loading... |
1105 LConstantOperand* const_op = LConstantOperand::cast(op); | 1105 LConstantOperand* const_op = LConstantOperand::cast(op); |
1106 HConstant* constant = chunk()->LookupConstant(const_op); | 1106 HConstant* constant = chunk()->LookupConstant(const_op); |
1107 Representation r = chunk_->LookupLiteralRepresentation(const_op); | 1107 Representation r = chunk_->LookupLiteralRepresentation(const_op); |
1108 if (r.IsInteger32()) { | 1108 if (r.IsInteger32()) { |
1109 ASSERT(constant->HasInteger32Value()); | 1109 ASSERT(constant->HasInteger32Value()); |
1110 return Operand(signedness == SIGNED_INT32 | 1110 return Operand(signedness == SIGNED_INT32 |
1111 ? constant->Integer32Value() | 1111 ? constant->Integer32Value() |
1112 : static_cast<uint32_t>(constant->Integer32Value())); | 1112 : static_cast<uint32_t>(constant->Integer32Value())); |
1113 } else { | 1113 } else { |
1114 // Other constants not implemented. | 1114 // Other constants not implemented. |
1115 Abort("ToOperand32 unsupported immediate."); | 1115 // TODO(all): Add this error code to objects.h. |
| 1116 // Abort(kToOperand32UnsupportedImmediate); |
| 1117 Abort(kUnknown); |
1116 } | 1118 } |
1117 } | 1119 } |
1118 // Other cases are not implemented. | 1120 // Other cases are not implemented. |
1119 UNREACHABLE(); | 1121 UNREACHABLE(); |
1120 return Operand(0); | 1122 return Operand(0); |
1121 } | 1123 } |
1122 | 1124 |
1123 | 1125 |
1124 MemOperand LCodeGen::ToMemOperand(LOperand* op) const { | 1126 MemOperand LCodeGen::ToMemOperand(LOperand* op) const { |
1125 ASSERT(op != NULL); | 1127 ASSERT(op != NULL); |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1339 Register result = ToRegister(instr->result()); | 1341 Register result = ToRegister(instr->result()); |
1340 Register temp1 = ToRegister(instr->temp1()); | 1342 Register temp1 = ToRegister(instr->temp1()); |
1341 Register temp2 = ToRegister(instr->temp2()); | 1343 Register temp2 = ToRegister(instr->temp2()); |
1342 | 1344 |
1343 // Allocate memory for the object. | 1345 // Allocate memory for the object. |
1344 AllocationFlags flags = TAG_OBJECT; | 1346 AllocationFlags flags = TAG_OBJECT; |
1345 if (instr->hydrogen()->MustAllocateDoubleAligned()) { | 1347 if (instr->hydrogen()->MustAllocateDoubleAligned()) { |
1346 flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT); | 1348 flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT); |
1347 } | 1349 } |
1348 | 1350 |
1349 if (instr->hydrogen()->CanAllocateInOldPointerSpace()) { | 1351 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { |
1350 ASSERT(!instr->hydrogen()->CanAllocateInOldDataSpace()); | 1352 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); |
| 1353 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
1351 flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE); | 1354 flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE); |
1352 } else if (instr->hydrogen()->CanAllocateInOldDataSpace()) { | 1355 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { |
| 1356 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
1353 flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_DATA_SPACE); | 1357 flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_DATA_SPACE); |
1354 } | 1358 } |
1355 | 1359 |
1356 if (instr->size()->IsConstantOperand()) { | 1360 if (instr->size()->IsConstantOperand()) { |
1357 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); | 1361 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); |
1358 __ Allocate(size, result, temp1, temp2, deferred->entry(), flags); | 1362 __ Allocate(size, result, temp1, temp2, deferred->entry(), flags); |
1359 } else { | 1363 } else { |
1360 Register size = ToRegister(instr->size()); | 1364 Register size = ToRegister(instr->size()); |
1361 __ Allocate(size, result, temp1, temp2, deferred->entry(), flags); | 1365 __ Allocate(size, result, temp1, temp2, deferred->entry(), flags); |
1362 } | 1366 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1397 if (instr->size()->IsConstantOperand()) { | 1401 if (instr->size()->IsConstantOperand()) { |
1398 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); | 1402 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); |
1399 // Use result as a scratch register. | 1403 // Use result as a scratch register. |
1400 __ Mov(result, Operand(Smi::FromInt(size))); | 1404 __ Mov(result, Operand(Smi::FromInt(size))); |
1401 __ Push(result); | 1405 __ Push(result); |
1402 } else { | 1406 } else { |
1403 Register size = ToRegister(instr->size()); | 1407 Register size = ToRegister(instr->size()); |
1404 __ SmiTag(size); | 1408 __ SmiTag(size); |
1405 __ Push(size); | 1409 __ Push(size); |
1406 } | 1410 } |
1407 if (instr->hydrogen()->CanAllocateInOldPointerSpace()) { | 1411 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { |
1408 ASSERT(!instr->hydrogen()->CanAllocateInOldDataSpace()); | 1412 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); |
| 1413 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
1409 CallRuntimeFromDeferred(Runtime::kAllocateInOldPointerSpace, 1, instr); | 1414 CallRuntimeFromDeferred(Runtime::kAllocateInOldPointerSpace, 1, instr); |
1410 } else if (instr->hydrogen()->CanAllocateInOldDataSpace()) { | 1415 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { |
| 1416 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
1411 CallRuntimeFromDeferred(Runtime::kAllocateInOldDataSpace, 1, instr); | 1417 CallRuntimeFromDeferred(Runtime::kAllocateInOldDataSpace, 1, instr); |
1412 } else { | 1418 } else { |
1413 CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr); | 1419 CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr); |
1414 } | 1420 } |
1415 __ StoreToSafepointRegisterSlot(x0, result); | 1421 __ StoreToSafepointRegisterSlot(x0, result); |
1416 } | 1422 } |
1417 | 1423 |
1418 | 1424 |
1419 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { | 1425 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { |
1420 Register receiver = ToRegister(instr->receiver()); | 1426 Register receiver = ToRegister(instr->receiver()); |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1595 | 1601 |
1596 void LCodeGen::DoBitNotI(LBitNotI* instr) { | 1602 void LCodeGen::DoBitNotI(LBitNotI* instr) { |
1597 Register input = ToRegister(instr->value()).W(); | 1603 Register input = ToRegister(instr->value()).W(); |
1598 Register result = ToRegister(instr->result()).W(); | 1604 Register result = ToRegister(instr->result()).W(); |
1599 __ Mvn(result, input); | 1605 __ Mvn(result, input); |
1600 } | 1606 } |
1601 | 1607 |
1602 | 1608 |
1603 void LCodeGen::ApplyCheckIf(Condition cc, LBoundsCheck* check) { | 1609 void LCodeGen::ApplyCheckIf(Condition cc, LBoundsCheck* check) { |
1604 if (FLAG_debug_code && check->hydrogen()->skip_check()) { | 1610 if (FLAG_debug_code && check->hydrogen()->skip_check()) { |
1605 __ Assert(InvertCondition(cc), "eliminated bounds check failed"); | 1611 // TODO(all): Add this error code to objects.h. |
| 1612 // __ Assert(InvertCondition(cc), kEliminatedBoundsCheckFailed); |
| 1613 __ Assert(InvertCondition(cc), kUnknown); |
1606 } else { | 1614 } else { |
1607 DeoptimizeIf(cc, check->environment()); | 1615 DeoptimizeIf(cc, check->environment()); |
1608 } | 1616 } |
1609 } | 1617 } |
1610 | 1618 |
1611 | 1619 |
1612 void LCodeGen::DoBoundsCheck(LBoundsCheck *instr) { | 1620 void LCodeGen::DoBoundsCheck(LBoundsCheck *instr) { |
1613 if (instr->hydrogen()->skip_check()) return; | 1621 if (instr->hydrogen()->skip_check()) return; |
1614 | 1622 |
1615 Register length = ToRegister(instr->length()); | 1623 Register length = ToRegister(instr->length()); |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1795 // If necessary, load the function object. | 1803 // If necessary, load the function object. |
1796 if (function_reg.IsNone()) { | 1804 if (function_reg.IsNone()) { |
1797 function_reg = x1; | 1805 function_reg = x1; |
1798 __ LoadHeapObject(function_reg, function); | 1806 __ LoadHeapObject(function_reg, function); |
1799 } | 1807 } |
1800 | 1808 |
1801 if (FLAG_debug_code) { | 1809 if (FLAG_debug_code) { |
1802 Label is_not_smi; | 1810 Label is_not_smi; |
1803 // Try to confirm that function_reg (x1) is a tagged pointer. | 1811 // Try to confirm that function_reg (x1) is a tagged pointer. |
1804 __ JumpIfNotSmi(function_reg, &is_not_smi); | 1812 __ JumpIfNotSmi(function_reg, &is_not_smi); |
1805 __ Abort("In CallKnownFunction, a function object is expected in x1."); | 1813 // TODO(all): Add this error code to objects.h. |
| 1814 // __ Abort(kExpectedFunctionObject); |
| 1815 __ Abort(kUnknown); |
1806 __ Bind(&is_not_smi); | 1816 __ Bind(&is_not_smi); |
1807 } | 1817 } |
1808 | 1818 |
1809 if (can_invoke_directly) { | 1819 if (can_invoke_directly) { |
1810 // Change context. | 1820 // Change context. |
1811 __ Ldr(cp, FieldMemOperand(function_reg, JSFunction::kContextOffset)); | 1821 __ Ldr(cp, FieldMemOperand(function_reg, JSFunction::kContextOffset)); |
1812 | 1822 |
1813 // Set the arguments count if adaption is not needed. Assumes that x0 is | 1823 // Set the arguments count if adaption is not needed. Assumes that x0 is |
1814 // available to write to at this point. | 1824 // available to write to at this point. |
1815 if (dont_adapt_arguments) { | 1825 if (dont_adapt_arguments) { |
(...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2281 } | 2291 } |
2282 | 2292 |
2283 | 2293 |
2284 void LCodeGen::DoConstantD(LConstantD* instr) { | 2294 void LCodeGen::DoConstantD(LConstantD* instr) { |
2285 ASSERT(instr->result()->IsDoubleRegister()); | 2295 ASSERT(instr->result()->IsDoubleRegister()); |
2286 DoubleRegister result = ToDoubleRegister(instr->result()); | 2296 DoubleRegister result = ToDoubleRegister(instr->result()); |
2287 __ Fmov(result, instr->value()); | 2297 __ Fmov(result, instr->value()); |
2288 } | 2298 } |
2289 | 2299 |
2290 | 2300 |
| 2301 void LCodeGen::DoConstantE(LConstantE* instr) { |
| 2302 __ Mov(ToRegister(instr->result()), Operand(instr->value())); |
| 2303 } |
| 2304 |
| 2305 |
2291 void LCodeGen::DoConstantI(LConstantI* instr) { | 2306 void LCodeGen::DoConstantI(LConstantI* instr) { |
2292 __ Mov(ToRegister(instr->result()), instr->value()); | 2307 __ Mov(ToRegister(instr->result()), instr->value()); |
2293 } | 2308 } |
2294 | 2309 |
2295 | 2310 |
2296 void LCodeGen::DoConstantS(LConstantS* instr) { | 2311 void LCodeGen::DoConstantS(LConstantS* instr) { |
2297 __ Mov(ToRegister(instr->result()), Operand(instr->value())); | 2312 __ Mov(ToRegister(instr->result()), Operand(instr->value())); |
2298 } | 2313 } |
2299 | 2314 |
2300 | 2315 |
(...skipping 791 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3092 label->hydrogen_value()->id(), | 3107 label->hydrogen_value()->id(), |
3093 label->block_id(), | 3108 label->block_id(), |
3094 LabelType(label)); | 3109 LabelType(label)); |
3095 | 3110 |
3096 __ Bind(label->label()); | 3111 __ Bind(label->label()); |
3097 current_block_ = label->block_id(); | 3112 current_block_ = label->block_id(); |
3098 DoGap(label); | 3113 DoGap(label); |
3099 } | 3114 } |
3100 | 3115 |
3101 | 3116 |
3102 void LCodeGen::DoLinkObjectInList(LLinkObjectInList* instr) { | |
3103 Register object = ToRegister(instr->object()); | |
3104 Register temp = ToRegister(instr->temp()); | |
3105 ExternalReference sites_list_address = instr->GetReference(isolate()); | |
3106 | |
3107 __ Mov(temp, Operand(sites_list_address)); | |
3108 __ Ldr(temp, MemOperand(temp)); | |
3109 __ Str(temp, FieldMemOperand(object, | |
3110 instr->hydrogen()->store_field().offset())); | |
3111 __ Mov(temp, Operand(sites_list_address)); | |
3112 __ Str(object, MemOperand(temp)); | |
3113 } | |
3114 | |
3115 | |
3116 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { | 3117 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { |
3117 Register context = ToRegister(instr->context()); | 3118 Register context = ToRegister(instr->context()); |
3118 Register result = ToRegister(instr->result()); | 3119 Register result = ToRegister(instr->result()); |
3119 __ Ldr(result, ContextMemOperand(context, instr->slot_index())); | 3120 __ Ldr(result, ContextMemOperand(context, instr->slot_index())); |
3120 if (instr->hydrogen()->RequiresHoleCheck()) { | 3121 if (instr->hydrogen()->RequiresHoleCheck()) { |
3121 if (instr->hydrogen()->DeoptimizesOnHole()) { | 3122 if (instr->hydrogen()->DeoptimizesOnHole()) { |
3122 DeoptimizeIfRoot(result, Heap::kTheHoleValueRootIndex, | 3123 DeoptimizeIfRoot(result, Heap::kTheHoleValueRootIndex, |
3123 instr->environment()); | 3124 instr->environment()); |
3124 } else { | 3125 } else { |
3125 Label not_the_hole; | 3126 Label not_the_hole; |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3247 ElementsKind elements_kind = instr->elements_kind(); | 3248 ElementsKind elements_kind = instr->elements_kind(); |
3248 | 3249 |
3249 bool key_is_smi = instr->hydrogen()->key()->representation().IsSmi(); | 3250 bool key_is_smi = instr->hydrogen()->key()->representation().IsSmi(); |
3250 bool key_is_constant = instr->key()->IsConstantOperand(); | 3251 bool key_is_constant = instr->key()->IsConstantOperand(); |
3251 Register key = no_reg; | 3252 Register key = no_reg; |
3252 int constant_key = 0; | 3253 int constant_key = 0; |
3253 if (key_is_constant) { | 3254 if (key_is_constant) { |
3254 ASSERT(instr->temp() == NULL); | 3255 ASSERT(instr->temp() == NULL); |
3255 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); | 3256 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); |
3256 if (constant_key & 0xf0000000) { | 3257 if (constant_key & 0xf0000000) { |
3257 Abort("Array index constant value too big."); | 3258 Abort(kArrayIndexConstantValueTooBig); |
3258 } | 3259 } |
3259 } else { | 3260 } else { |
3260 scratch = ToRegister(instr->temp()); | 3261 scratch = ToRegister(instr->temp()); |
3261 key = ToRegister(instr->key()); | 3262 key = ToRegister(instr->key()); |
3262 } | 3263 } |
3263 | 3264 |
3264 int element_size_shift = ElementsKindToShiftSize(elements_kind); | 3265 int element_size_shift = ElementsKindToShiftSize(elements_kind); |
3265 MemOperand mem_op = | 3266 MemOperand mem_op = |
3266 PrepareKeyedExternalArrayOperand(key, ext_ptr, scratch, key_is_smi, | 3267 PrepareKeyedExternalArrayOperand(key, ext_ptr, scratch, key_is_smi, |
3267 key_is_constant, constant_key, | 3268 key_is_constant, constant_key, |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3337 DoubleRegister result = ToDoubleRegister(instr->result()); | 3338 DoubleRegister result = ToDoubleRegister(instr->result()); |
3338 Register load_base; | 3339 Register load_base; |
3339 int offset = 0; | 3340 int offset = 0; |
3340 | 3341 |
3341 if (instr->key()->IsConstantOperand()) { | 3342 if (instr->key()->IsConstantOperand()) { |
3342 ASSERT(instr->hydrogen()->RequiresHoleCheck() || | 3343 ASSERT(instr->hydrogen()->RequiresHoleCheck() || |
3343 (instr->temp() == NULL)); | 3344 (instr->temp() == NULL)); |
3344 | 3345 |
3345 int constant_key = ToInteger32(LConstantOperand::cast(instr->key())); | 3346 int constant_key = ToInteger32(LConstantOperand::cast(instr->key())); |
3346 if (constant_key & 0xf0000000) { | 3347 if (constant_key & 0xf0000000) { |
3347 Abort("Array index constant value too big."); | 3348 Abort(kArrayIndexConstantValueTooBig); |
3348 } | 3349 } |
3349 offset = FixedDoubleArray::OffsetOfElementAt(constant_key + | 3350 offset = FixedDoubleArray::OffsetOfElementAt(constant_key + |
3350 instr->additional_index()); | 3351 instr->additional_index()); |
3351 load_base = elements; | 3352 load_base = elements; |
3352 } else { | 3353 } else { |
3353 load_base = ToRegister(instr->temp()); | 3354 load_base = ToRegister(instr->temp()); |
3354 Register key = ToRegister(instr->key()); | 3355 Register key = ToRegister(instr->key()); |
3355 bool key_is_tagged = instr->hydrogen()->key()->representation().IsSmi(); | 3356 bool key_is_tagged = instr->hydrogen()->key()->representation().IsSmi(); |
3356 CalcKeyedArrayBaseRegister(load_base, elements, key, key_is_tagged, | 3357 CalcKeyedArrayBaseRegister(load_base, elements, key, key_is_tagged, |
3357 instr->hydrogen()->elements_kind()); | 3358 instr->hydrogen()->elements_kind()); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3413 | 3414 |
3414 ASSERT(ToRegister(instr->result()).Is(x0)); | 3415 ASSERT(ToRegister(instr->result()).Is(x0)); |
3415 } | 3416 } |
3416 | 3417 |
3417 | 3418 |
3418 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 3419 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
3419 HObjectAccess access = instr->hydrogen()->access(); | 3420 HObjectAccess access = instr->hydrogen()->access(); |
3420 int offset = access.offset(); | 3421 int offset = access.offset(); |
3421 Register object = ToRegister(instr->object()); | 3422 Register object = ToRegister(instr->object()); |
3422 | 3423 |
| 3424 if (access.IsExternalMemory()) { |
| 3425 Register result = ToRegister(instr->result()); |
| 3426 __ Ldr(result, MemOperand(object, offset)); |
| 3427 return; |
| 3428 } |
| 3429 |
3423 if (instr->hydrogen()->representation().IsDouble()) { | 3430 if (instr->hydrogen()->representation().IsDouble()) { |
3424 FPRegister result = ToDoubleRegister(instr->result()); | 3431 FPRegister result = ToDoubleRegister(instr->result()); |
3425 __ Ldr(result, FieldMemOperand(object, offset)); | 3432 __ Ldr(result, FieldMemOperand(object, offset)); |
3426 } else { | 3433 } else { |
3427 Register result = ToRegister(instr->result()); | 3434 Register result = ToRegister(instr->result()); |
3428 if (access.IsInobject()) { | 3435 if (access.IsInobject()) { |
3429 __ Ldr(result, FieldMemOperand(object, offset)); | 3436 __ Ldr(result, FieldMemOperand(object, offset)); |
3430 } else { | 3437 } else { |
3431 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 3438 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
3432 __ Ldr(result, FieldMemOperand(result, offset)); | 3439 __ Ldr(result, FieldMemOperand(result, offset)); |
(...skipping 919 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4352 __ Bind(&slow); | 4359 __ Bind(&slow); |
4353 | 4360 |
4354 // Check that the dst register contains new space allocation top, which is a | 4361 // Check that the dst register contains new space allocation top, which is a |
4355 // valid address for the GC. | 4362 // valid address for the GC. |
4356 if (FLAG_debug_code) { | 4363 if (FLAG_debug_code) { |
4357 ExternalReference new_space_allocation_top = | 4364 ExternalReference new_space_allocation_top = |
4358 ExternalReference::new_space_allocation_top_address(isolate()); | 4365 ExternalReference::new_space_allocation_top_address(isolate()); |
4359 __ Mov(scratch1, Operand(new_space_allocation_top)); | 4366 __ Mov(scratch1, Operand(new_space_allocation_top)); |
4360 __ Ldr(scratch1, MemOperand(scratch1)); | 4367 __ Ldr(scratch1, MemOperand(scratch1)); |
4361 __ Cmp(dst, scratch1); | 4368 __ Cmp(dst, scratch1); |
4362 __ Check(eq, "Register dst does not contain allocation top."); | 4369 // TODO(all): Add this error code to objects.h. |
| 4370 // __ Check(eq, kRegisterDstDoesNotContainAllocationTop); |
| 4371 __ Check(eq, kUnknown); |
4363 } | 4372 } |
4364 | 4373 |
4365 { | 4374 { |
4366 // Preserve the value of all registers. | 4375 // Preserve the value of all registers. |
4367 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 4376 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
4368 | 4377 |
4369 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 4378 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); |
4370 __ StoreToSafepointRegisterSlot(x0, dst); | 4379 __ StoreToSafepointRegisterSlot(x0, dst); |
4371 } | 4380 } |
4372 | 4381 |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4507 | 4516 |
4508 | 4517 |
4509 void LCodeGen::DoParameter(LParameter* instr) { | 4518 void LCodeGen::DoParameter(LParameter* instr) { |
4510 // Nothing to do. | 4519 // Nothing to do. |
4511 } | 4520 } |
4512 | 4521 |
4513 | 4522 |
4514 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 4523 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
4515 LOperand* argument = instr->value(); | 4524 LOperand* argument = instr->value(); |
4516 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { | 4525 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { |
4517 Abort("DoPushArgument not implemented for double types."); | 4526 // TODO(all): Add this error code to objects.h. |
| 4527 // Abort(kDoPushArgumentNotImplementedForDoubleTypes); |
| 4528 Abort(kUnknown); |
4518 } else { | 4529 } else { |
4519 __ Push(ToRegister(argument)); | 4530 __ Push(ToRegister(argument)); |
4520 } | 4531 } |
4521 } | 4532 } |
4522 | 4533 |
4523 | 4534 |
4524 void LCodeGen::DoReturn(LReturn* instr) { | 4535 void LCodeGen::DoReturn(LReturn* instr) { |
4525 if (FLAG_trace && info()->IsOptimizing()) { | 4536 if (FLAG_trace && info()->IsOptimizing()) { |
4526 // Push the return value on the stack as the parameter. | 4537 // Push the return value on the stack as the parameter. |
4527 // Runtime::TraceExit returns its parameter in x0. | 4538 // Runtime::TraceExit returns its parameter in x0. |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4572 Register value = ToRegister(instr->value()); | 4583 Register value = ToRegister(instr->value()); |
4573 Register temp = ToRegister(instr->temp()); | 4584 Register temp = ToRegister(instr->temp()); |
4574 | 4585 |
4575 if (FLAG_debug_code) { | 4586 if (FLAG_debug_code) { |
4576 __ Ldr(temp, FieldMemOperand(string, HeapObject::kMapOffset)); | 4587 __ Ldr(temp, FieldMemOperand(string, HeapObject::kMapOffset)); |
4577 __ Ldrb(temp, FieldMemOperand(temp, Map::kInstanceTypeOffset)); | 4588 __ Ldrb(temp, FieldMemOperand(temp, Map::kInstanceTypeOffset)); |
4578 __ And(temp, temp, kStringRepresentationMask | kStringEncodingMask); | 4589 __ And(temp, temp, kStringRepresentationMask | kStringEncodingMask); |
4579 | 4590 |
4580 if (encoding == String::ONE_BYTE_ENCODING) { | 4591 if (encoding == String::ONE_BYTE_ENCODING) { |
4581 __ Cmp(temp, kSeqStringTag | kOneByteStringTag); | 4592 __ Cmp(temp, kSeqStringTag | kOneByteStringTag); |
4582 __ Check(eq, "Unexpected string type"); | 4593 __ Check(eq, kUnexpectedStringType); |
4583 } else { | 4594 } else { |
4584 ASSERT(encoding == String::TWO_BYTE_ENCODING); | 4595 ASSERT(encoding == String::TWO_BYTE_ENCODING); |
4585 __ Cmp(temp, kSeqStringTag | kTwoByteStringTag); | 4596 __ Cmp(temp, kSeqStringTag | kTwoByteStringTag); |
4586 __ Check(eq, "Unexpected string type"); | 4597 __ Check(eq, kUnexpectedStringType); |
4587 } | 4598 } |
4588 } | 4599 } |
4589 | 4600 |
4590 __ Add(temp, string, SeqString::kHeaderSize - kHeapObjectTag); | 4601 __ Add(temp, string, SeqString::kHeaderSize - kHeapObjectTag); |
4591 if (encoding == String::ONE_BYTE_ENCODING) { | 4602 if (encoding == String::ONE_BYTE_ENCODING) { |
4592 __ Strb(value, MemOperand(temp, index)); | 4603 __ Strb(value, MemOperand(temp, index)); |
4593 } else { | 4604 } else { |
4594 __ Strh(value, MemOperand(temp, index, LSL, 1)); | 4605 __ Strh(value, MemOperand(temp, index, LSL, 1)); |
4595 } | 4606 } |
4596 } | 4607 } |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4829 Register scratch; | 4840 Register scratch; |
4830 ElementsKind elements_kind = instr->elements_kind(); | 4841 ElementsKind elements_kind = instr->elements_kind(); |
4831 | 4842 |
4832 bool key_is_smi = instr->hydrogen()->key()->representation().IsSmi(); | 4843 bool key_is_smi = instr->hydrogen()->key()->representation().IsSmi(); |
4833 bool key_is_constant = instr->key()->IsConstantOperand(); | 4844 bool key_is_constant = instr->key()->IsConstantOperand(); |
4834 int constant_key = 0; | 4845 int constant_key = 0; |
4835 if (key_is_constant) { | 4846 if (key_is_constant) { |
4836 ASSERT(instr->temp() == NULL); | 4847 ASSERT(instr->temp() == NULL); |
4837 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); | 4848 constant_key = ToInteger32(LConstantOperand::cast(instr->key())); |
4838 if (constant_key & 0xf0000000) { | 4849 if (constant_key & 0xf0000000) { |
4839 Abort("Array index constant value too big."); | 4850 Abort(kArrayIndexConstantValueTooBig); |
4840 } | 4851 } |
4841 } else { | 4852 } else { |
4842 key = ToRegister(instr->key()); | 4853 key = ToRegister(instr->key()); |
4843 scratch = ToRegister(instr->temp()); | 4854 scratch = ToRegister(instr->temp()); |
4844 } | 4855 } |
4845 | 4856 |
4846 int element_size_shift = ElementsKindToShiftSize(elements_kind); | 4857 int element_size_shift = ElementsKindToShiftSize(elements_kind); |
4847 MemOperand dst = | 4858 MemOperand dst = |
4848 PrepareKeyedExternalArrayOperand(key, ext_ptr, scratch, key_is_smi, | 4859 PrepareKeyedExternalArrayOperand(key, ext_ptr, scratch, key_is_smi, |
4849 key_is_constant, constant_key, | 4860 key_is_constant, constant_key, |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4888 | 4899 |
4889 void LCodeGen::DoStoreKeyedFixedDouble(LStoreKeyedFixedDouble* instr) { | 4900 void LCodeGen::DoStoreKeyedFixedDouble(LStoreKeyedFixedDouble* instr) { |
4890 Register elements = ToRegister(instr->elements()); | 4901 Register elements = ToRegister(instr->elements()); |
4891 DoubleRegister value = ToDoubleRegister(instr->value()); | 4902 DoubleRegister value = ToDoubleRegister(instr->value()); |
4892 Register store_base = ToRegister(instr->temp()); | 4903 Register store_base = ToRegister(instr->temp()); |
4893 int offset = 0; | 4904 int offset = 0; |
4894 | 4905 |
4895 if (instr->key()->IsConstantOperand()) { | 4906 if (instr->key()->IsConstantOperand()) { |
4896 int constant_key = ToInteger32(LConstantOperand::cast(instr->key())); | 4907 int constant_key = ToInteger32(LConstantOperand::cast(instr->key())); |
4897 if (constant_key & 0xf0000000) { | 4908 if (constant_key & 0xf0000000) { |
4898 Abort("Array index constant value too big."); | 4909 Abort(kArrayIndexConstantValueTooBig); |
4899 } | 4910 } |
4900 offset = FixedDoubleArray::OffsetOfElementAt(constant_key + | 4911 offset = FixedDoubleArray::OffsetOfElementAt(constant_key + |
4901 instr->additional_index()); | 4912 instr->additional_index()); |
4902 store_base = elements; | 4913 store_base = elements; |
4903 } else { | 4914 } else { |
4904 Register key = ToRegister(instr->key()); | 4915 Register key = ToRegister(instr->key()); |
4905 bool key_is_tagged = instr->hydrogen()->key()->representation().IsSmi(); | 4916 bool key_is_tagged = instr->hydrogen()->key()->representation().IsSmi(); |
4906 CalcKeyedArrayBaseRegister(store_base, elements, key, key_is_tagged, | 4917 CalcKeyedArrayBaseRegister(store_base, elements, key, key_is_tagged, |
4907 instr->hydrogen()->elements_kind()); | 4918 instr->hydrogen()->elements_kind()); |
4908 offset = FixedDoubleArray::OffsetOfElementAt(instr->additional_index()); | 4919 offset = FixedDoubleArray::OffsetOfElementAt(instr->additional_index()); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4970 // to tidy up this function. | 4981 // to tidy up this function. |
4971 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { | 4982 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { |
4972 Representation representation = instr->representation(); | 4983 Representation representation = instr->representation(); |
4973 | 4984 |
4974 Register object = ToRegister(instr->object()); | 4985 Register object = ToRegister(instr->object()); |
4975 Register temp0 = ToRegister(instr->temp0()); | 4986 Register temp0 = ToRegister(instr->temp0()); |
4976 Register temp1 = ToRegister(instr->temp1()); | 4987 Register temp1 = ToRegister(instr->temp1()); |
4977 HObjectAccess access = instr->hydrogen()->access(); | 4988 HObjectAccess access = instr->hydrogen()->access(); |
4978 int offset = access.offset(); | 4989 int offset = access.offset(); |
4979 | 4990 |
| 4991 if (access.IsExternalMemory()) { |
| 4992 Register value = ToRegister(instr->value()); |
| 4993 __ Str(value, MemOperand(object, offset)); |
| 4994 return; |
| 4995 } |
| 4996 |
4980 Handle<Map> transition = instr->transition(); | 4997 Handle<Map> transition = instr->transition(); |
4981 | 4998 |
4982 if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { | 4999 if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { |
4983 Register value = ToRegister(instr->value()); | 5000 Register value = ToRegister(instr->value()); |
4984 if (!instr->hydrogen()->value()->type().IsHeapObject()) { | 5001 if (!instr->hydrogen()->value()->type().IsHeapObject()) { |
4985 DeoptimizeIfSmi(value, instr->environment()); | 5002 DeoptimizeIfSmi(value, instr->environment()); |
4986 } | 5003 } |
4987 } else if (FLAG_track_double_fields && representation.IsDouble()) { | 5004 } else if (FLAG_track_double_fields && representation.IsDouble()) { |
4988 ASSERT(transition.is_null()); | 5005 ASSERT(transition.is_null()); |
4989 ASSERT(access.IsInobject()); | 5006 ASSERT(access.IsInobject()); |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5168 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 5185 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
5169 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 5186 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
5170 InlineSmiCheckInfo::EmitNotInlined(masm()); | 5187 InlineSmiCheckInfo::EmitNotInlined(masm()); |
5171 | 5188 |
5172 Condition condition = TokenToCondition(op, false); | 5189 Condition condition = TokenToCondition(op, false); |
5173 | 5190 |
5174 EmitBranch(instr, condition); | 5191 EmitBranch(instr, condition); |
5175 } | 5192 } |
5176 | 5193 |
5177 | 5194 |
5178 void LCodeGen::DoStringLength(LStringLength* instr) { | |
5179 Register string = ToRegister(instr->string()); | |
5180 Register result = ToRegister(instr->result()); | |
5181 __ Ldr(result, FieldMemOperand(string, String::kLengthOffset)); | |
5182 } | |
5183 | |
5184 | |
5185 void LCodeGen::DoSubI(LSubI* instr) { | 5195 void LCodeGen::DoSubI(LSubI* instr) { |
5186 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 5196 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
5187 Register result = ToRegister32(instr->result()); | 5197 Register result = ToRegister32(instr->result()); |
5188 Register left = ToRegister32(instr->left()); | 5198 Register left = ToRegister32(instr->left()); |
5189 Operand right = ToOperand32I(instr->right()); | 5199 Operand right = ToOperand32I(instr->right()); |
5190 if (can_overflow) { | 5200 if (can_overflow) { |
5191 __ Subs(result, left, right); | 5201 __ Subs(result, left, right); |
5192 DeoptimizeIf(vs, instr->environment()); | 5202 DeoptimizeIf(vs, instr->environment()); |
5193 } else { | 5203 } else { |
5194 __ Sub(result, left, right); | 5204 __ Sub(result, left, right); |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5344 __ CopyFields(x0, x1, CPURegList(x10, x11, x12), size / kPointerSize); | 5354 __ CopyFields(x0, x1, CPURegList(x10, x11, x12), size / kPointerSize); |
5345 } | 5355 } |
5346 | 5356 |
5347 | 5357 |
5348 void LCodeGen::DoThrow(LThrow* instr) { | 5358 void LCodeGen::DoThrow(LThrow* instr) { |
5349 Register value = ToRegister(instr->value()); | 5359 Register value = ToRegister(instr->value()); |
5350 __ Push(value); | 5360 __ Push(value); |
5351 CallRuntime(Runtime::kThrow, 1, instr); | 5361 CallRuntime(Runtime::kThrow, 1, instr); |
5352 | 5362 |
5353 if (FLAG_debug_code) { | 5363 if (FLAG_debug_code) { |
5354 __ Abort("Unreachable code in Throw."); | 5364 __ Unreachable(); |
5355 } | 5365 } |
5356 } | 5366 } |
5357 | 5367 |
5358 | 5368 |
5359 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { | 5369 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { |
5360 Register object = ToRegister(instr->object()); | 5370 Register object = ToRegister(instr->object()); |
5361 Register temp1 = ToRegister(instr->temp1()); | 5371 Register temp1 = ToRegister(instr->temp1()); |
5362 | 5372 |
5363 Handle<Map> from_map = instr->original_map(); | 5373 Handle<Map> from_map = instr->original_map(); |
5364 Handle<Map> to_map = instr->transitioned_map(); | 5374 Handle<Map> to_map = instr->transitioned_map(); |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5611 __ Bind(&out_of_object); | 5621 __ Bind(&out_of_object); |
5612 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); | 5622 __ Ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
5613 // Index is equal to negated out of object property index plus 1. | 5623 // Index is equal to negated out of object property index plus 1. |
5614 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); | 5624 __ Sub(result, result, Operand::UntagSmiAndScale(index, kPointerSizeLog2)); |
5615 __ Ldr(result, FieldMemOperand(result, | 5625 __ Ldr(result, FieldMemOperand(result, |
5616 FixedArray::kHeaderSize - kPointerSize)); | 5626 FixedArray::kHeaderSize - kPointerSize)); |
5617 __ Bind(&done); | 5627 __ Bind(&done); |
5618 } | 5628 } |
5619 | 5629 |
5620 } } // namespace v8::internal | 5630 } } // namespace v8::internal |
OLD | NEW |