| 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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 GenerateDeferredCode() && | 77 GenerateDeferredCode() && |
| 78 GenerateDeoptJumpTable() && | 78 GenerateDeoptJumpTable() && |
| 79 GenerateSafepointTable(); | 79 GenerateSafepointTable(); |
| 80 } | 80 } |
| 81 | 81 |
| 82 | 82 |
| 83 void LCodeGen::FinishCode(Handle<Code> code) { | 83 void LCodeGen::FinishCode(Handle<Code> code) { |
| 84 ASSERT(is_done()); | 84 ASSERT(is_done()); |
| 85 code->set_stack_slots(GetStackSlotCount()); | 85 code->set_stack_slots(GetStackSlotCount()); |
| 86 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); | 86 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); |
| 87 RegisterDependentCodeForEmbeddedMaps(code); | 87 if (code->is_optimized_code()) RegisterWeakObjectsInOptimizedCode(code); |
| 88 PopulateDeoptimizationData(code); | 88 PopulateDeoptimizationData(code); |
| 89 info()->CommitDependencies(code); | 89 info()->CommitDependencies(code); |
| 90 } | 90 } |
| 91 | 91 |
| 92 | 92 |
| 93 void LCodeGen::Abort(BailoutReason reason) { | 93 void LCodeGen::Abort(BailoutReason reason) { |
| 94 info()->set_bailout_reason(reason); | 94 info()->set_bailout_reason(reason); |
| 95 status_ = ABORTED; | 95 status_ = ABORTED; |
| 96 } | 96 } |
| 97 | 97 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 | 200 |
| 201 if (info()->saves_caller_doubles()) { | 201 if (info()->saves_caller_doubles()) { |
| 202 SaveCallerDoubles(); | 202 SaveCallerDoubles(); |
| 203 } | 203 } |
| 204 | 204 |
| 205 // Possibly allocate a local context. | 205 // Possibly allocate a local context. |
| 206 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 206 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
| 207 if (heap_slots > 0) { | 207 if (heap_slots > 0) { |
| 208 Comment(";;; Allocate local context"); | 208 Comment(";;; Allocate local context"); |
| 209 // Argument to NewContext is the function, which is in r1. | 209 // Argument to NewContext is the function, which is in r1. |
| 210 __ push(r1); | |
| 211 if (heap_slots <= FastNewContextStub::kMaximumSlots) { | 210 if (heap_slots <= FastNewContextStub::kMaximumSlots) { |
| 212 FastNewContextStub stub(heap_slots); | 211 FastNewContextStub stub(heap_slots); |
| 213 __ CallStub(&stub); | 212 __ CallStub(&stub); |
| 214 } else { | 213 } else { |
| 214 __ push(r1); |
| 215 __ CallRuntime(Runtime::kNewFunctionContext, 1); | 215 __ CallRuntime(Runtime::kNewFunctionContext, 1); |
| 216 } | 216 } |
| 217 RecordSafepoint(Safepoint::kNoLazyDeopt); | 217 RecordSafepoint(Safepoint::kNoLazyDeopt); |
| 218 // Context is returned in both r0 and cp. It replaces the context | 218 // Context is returned in both r0 and cp. It replaces the context |
| 219 // passed to us. It's saved in the stack and kept live in cp. | 219 // passed to us. It's saved in the stack and kept live in cp. |
| 220 __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 220 __ mov(cp, r0); |
| 221 __ str(r0, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 221 // Copy any necessary parameters into the context. | 222 // Copy any necessary parameters into the context. |
| 222 int num_parameters = scope()->num_parameters(); | 223 int num_parameters = scope()->num_parameters(); |
| 223 for (int i = 0; i < num_parameters; i++) { | 224 for (int i = 0; i < num_parameters; i++) { |
| 224 Variable* var = scope()->parameter(i); | 225 Variable* var = scope()->parameter(i); |
| 225 if (var->IsContextSlot()) { | 226 if (var->IsContextSlot()) { |
| 226 int parameter_offset = StandardFrameConstants::kCallerSPOffset + | 227 int parameter_offset = StandardFrameConstants::kCallerSPOffset + |
| 227 (num_parameters - 1 - i) * kPointerSize; | 228 (num_parameters - 1 - i) * kPointerSize; |
| 228 // Load parameter from stack. | 229 // Load parameter from stack. |
| 229 __ ldr(r0, MemOperand(fp, parameter_offset)); | 230 __ ldr(r0, MemOperand(fp, parameter_offset)); |
| 230 // Store it in the context. | 231 // Store it in the context. |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 269 | 270 |
| 270 | 271 |
| 271 bool LCodeGen::GenerateDeferredCode() { | 272 bool LCodeGen::GenerateDeferredCode() { |
| 272 ASSERT(is_generating()); | 273 ASSERT(is_generating()); |
| 273 if (deferred_.length() > 0) { | 274 if (deferred_.length() > 0) { |
| 274 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { | 275 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { |
| 275 LDeferredCode* code = deferred_[i]; | 276 LDeferredCode* code = deferred_[i]; |
| 276 | 277 |
| 277 HValue* value = | 278 HValue* value = |
| 278 instructions_->at(code->instruction_index())->hydrogen_value(); | 279 instructions_->at(code->instruction_index())->hydrogen_value(); |
| 279 RecordAndWritePosition(value->position()); | 280 RecordAndWritePosition( |
| 281 chunk()->graph()->SourcePositionToScriptPosition(value->position())); |
| 280 | 282 |
| 281 Comment(";;; <@%d,#%d> " | 283 Comment(";;; <@%d,#%d> " |
| 282 "-------------------- Deferred %s --------------------", | 284 "-------------------- Deferred %s --------------------", |
| 283 code->instruction_index(), | 285 code->instruction_index(), |
| 284 code->instr()->hydrogen_value()->id(), | 286 code->instr()->hydrogen_value()->id(), |
| 285 code->instr()->Mnemonic()); | 287 code->instr()->Mnemonic()); |
| 286 __ bind(code->entry()); | 288 __ bind(code->entry()); |
| 287 if (NeedsDeferredFrame()) { | 289 if (NeedsDeferredFrame()) { |
| 288 Comment(";;; Build frame"); | 290 Comment(";;; Build frame"); |
| 289 ASSERT(!frame_is_built_); | 291 ASSERT(!frame_is_built_); |
| (...skipping 608 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 898 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { | 900 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { |
| 899 int length = deoptimizations_.length(); | 901 int length = deoptimizations_.length(); |
| 900 if (length == 0) return; | 902 if (length == 0) return; |
| 901 Handle<DeoptimizationInputData> data = | 903 Handle<DeoptimizationInputData> data = |
| 902 factory()->NewDeoptimizationInputData(length, TENURED); | 904 factory()->NewDeoptimizationInputData(length, TENURED); |
| 903 | 905 |
| 904 Handle<ByteArray> translations = | 906 Handle<ByteArray> translations = |
| 905 translations_.CreateByteArray(isolate()->factory()); | 907 translations_.CreateByteArray(isolate()->factory()); |
| 906 data->SetTranslationByteArray(*translations); | 908 data->SetTranslationByteArray(*translations); |
| 907 data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); | 909 data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); |
| 910 data->SetOptimizationId(Smi::FromInt(info_->optimization_id())); |
| 911 if (info_->IsOptimizing()) { |
| 912 // Reference to shared function info does not change between phases. |
| 913 AllowDeferredHandleDereference allow_handle_dereference; |
| 914 data->SetSharedFunctionInfo(*info_->shared_info()); |
| 915 } else { |
| 916 data->SetSharedFunctionInfo(Smi::FromInt(0)); |
| 917 } |
| 908 | 918 |
| 909 Handle<FixedArray> literals = | 919 Handle<FixedArray> literals = |
| 910 factory()->NewFixedArray(deoptimization_literals_.length(), TENURED); | 920 factory()->NewFixedArray(deoptimization_literals_.length(), TENURED); |
| 911 { AllowDeferredHandleDereference copy_handles; | 921 { AllowDeferredHandleDereference copy_handles; |
| 912 for (int i = 0; i < deoptimization_literals_.length(); i++) { | 922 for (int i = 0; i < deoptimization_literals_.length(); i++) { |
| 913 literals->set(i, *deoptimization_literals_[i]); | 923 literals->set(i, *deoptimization_literals_[i]); |
| 914 } | 924 } |
| 915 data->SetLiteralArray(*literals); | 925 data->SetLiteralArray(*literals); |
| 916 } | 926 } |
| 917 | 927 |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1072 | 1082 |
| 1073 void LCodeGen::DoParameter(LParameter* instr) { | 1083 void LCodeGen::DoParameter(LParameter* instr) { |
| 1074 // Nothing to do. | 1084 // Nothing to do. |
| 1075 } | 1085 } |
| 1076 | 1086 |
| 1077 | 1087 |
| 1078 void LCodeGen::DoCallStub(LCallStub* instr) { | 1088 void LCodeGen::DoCallStub(LCallStub* instr) { |
| 1079 ASSERT(ToRegister(instr->context()).is(cp)); | 1089 ASSERT(ToRegister(instr->context()).is(cp)); |
| 1080 ASSERT(ToRegister(instr->result()).is(r0)); | 1090 ASSERT(ToRegister(instr->result()).is(r0)); |
| 1081 switch (instr->hydrogen()->major_key()) { | 1091 switch (instr->hydrogen()->major_key()) { |
| 1082 case CodeStub::RegExpConstructResult: { | |
| 1083 RegExpConstructResultStub stub; | |
| 1084 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | |
| 1085 break; | |
| 1086 } | |
| 1087 case CodeStub::RegExpExec: { | 1092 case CodeStub::RegExpExec: { |
| 1088 RegExpExecStub stub; | 1093 RegExpExecStub stub; |
| 1089 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 1094 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 1090 break; | 1095 break; |
| 1091 } | 1096 } |
| 1092 case CodeStub::SubString: { | 1097 case CodeStub::SubString: { |
| 1093 SubStringStub stub; | 1098 SubStringStub stub; |
| 1094 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 1099 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 1095 break; | 1100 break; |
| 1096 } | 1101 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1107 | 1112 |
| 1108 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 1113 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
| 1109 GenerateOsrPrologue(); | 1114 GenerateOsrPrologue(); |
| 1110 } | 1115 } |
| 1111 | 1116 |
| 1112 | 1117 |
| 1113 void LCodeGen::DoModI(LModI* instr) { | 1118 void LCodeGen::DoModI(LModI* instr) { |
| 1114 HMod* hmod = instr->hydrogen(); | 1119 HMod* hmod = instr->hydrogen(); |
| 1115 HValue* left = hmod->left(); | 1120 HValue* left = hmod->left(); |
| 1116 HValue* right = hmod->right(); | 1121 HValue* right = hmod->right(); |
| 1117 if (hmod->HasPowerOf2Divisor()) { | 1122 if (hmod->RightIsPowerOf2()) { |
| 1118 // TODO(svenpanne) We should really do the strength reduction on the | 1123 // TODO(svenpanne) We should really do the strength reduction on the |
| 1119 // Hydrogen level. | 1124 // Hydrogen level. |
| 1120 Register left_reg = ToRegister(instr->left()); | 1125 Register left_reg = ToRegister(instr->left()); |
| 1121 Register result_reg = ToRegister(instr->result()); | 1126 Register result_reg = ToRegister(instr->result()); |
| 1122 | 1127 |
| 1123 // Note: The code below even works when right contains kMinInt. | 1128 // Note: The code below even works when right contains kMinInt. |
| 1124 int32_t divisor = Abs(right->GetInteger32Constant()); | 1129 int32_t divisor = Abs(right->GetInteger32Constant()); |
| 1125 | 1130 |
| 1126 Label left_is_not_negative, done; | 1131 Label left_is_not_negative, done; |
| 1127 if (left->CanBeNegative()) { | 1132 if (left->CanBeNegative()) { |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1337 // This sequence could be replaced with 'mls' when | 1342 // This sequence could be replaced with 'mls' when |
| 1338 // it gets implemented. | 1343 // it gets implemented. |
| 1339 __ mul(scratch, result, ip); | 1344 __ mul(scratch, result, ip); |
| 1340 __ sub(remainder, dividend, scratch); | 1345 __ sub(remainder, dividend, scratch); |
| 1341 } | 1346 } |
| 1342 } | 1347 } |
| 1343 } | 1348 } |
| 1344 | 1349 |
| 1345 | 1350 |
| 1346 void LCodeGen::DoDivI(LDivI* instr) { | 1351 void LCodeGen::DoDivI(LDivI* instr) { |
| 1347 if (instr->hydrogen()->HasPowerOf2Divisor()) { | 1352 if (!instr->is_flooring() && instr->hydrogen()->RightIsPowerOf2()) { |
| 1348 const Register dividend = ToRegister(instr->left()); | 1353 Register dividend = ToRegister(instr->left()); |
| 1349 const Register result = ToRegister(instr->result()); | 1354 HDiv* hdiv = instr->hydrogen(); |
| 1350 int32_t divisor = instr->hydrogen()->right()->GetInteger32Constant(); | 1355 int32_t divisor = hdiv->right()->GetInteger32Constant(); |
| 1351 int32_t test_value = 0; | 1356 Register result = ToRegister(instr->result()); |
| 1352 int32_t power = 0; | 1357 ASSERT(!result.is(dividend)); |
| 1353 | 1358 |
| 1354 if (divisor > 0) { | 1359 // Check for (0 / -x) that will produce negative zero. |
| 1355 test_value = divisor - 1; | 1360 if (hdiv->left()->RangeCanInclude(0) && divisor < 0 && |
| 1356 power = WhichPowerOf2(divisor); | 1361 hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1362 __ cmp(dividend, Operand::Zero()); |
| 1363 DeoptimizeIf(eq, instr->environment()); |
| 1364 } |
| 1365 // Check for (kMinInt / -1). |
| 1366 if (hdiv->left()->RangeCanInclude(kMinInt) && divisor == -1 && |
| 1367 hdiv->CheckFlag(HValue::kCanOverflow)) { |
| 1368 __ cmp(dividend, Operand(kMinInt)); |
| 1369 DeoptimizeIf(eq, instr->environment()); |
| 1370 } |
| 1371 // Deoptimize if remainder will not be 0. |
| 1372 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && |
| 1373 Abs(divisor) != 1) { |
| 1374 __ tst(dividend, Operand(Abs(divisor) - 1)); |
| 1375 DeoptimizeIf(ne, instr->environment()); |
| 1376 } |
| 1377 if (divisor == -1) { // Nice shortcut, not needed for correctness. |
| 1378 __ rsb(result, dividend, Operand(0)); |
| 1379 return; |
| 1380 } |
| 1381 int32_t shift = WhichPowerOf2(Abs(divisor)); |
| 1382 if (shift == 0) { |
| 1383 __ mov(result, dividend); |
| 1384 } else if (shift == 1) { |
| 1385 __ add(result, dividend, Operand(dividend, LSR, 31)); |
| 1357 } else { | 1386 } else { |
| 1358 // Check for (0 / -x) that will produce negative zero. | 1387 __ mov(result, Operand(dividend, ASR, 31)); |
| 1359 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1388 __ add(result, dividend, Operand(result, LSR, 32 - shift)); |
| 1360 __ cmp(dividend, Operand::Zero()); | |
| 1361 DeoptimizeIf(eq, instr->environment()); | |
| 1362 } | |
| 1363 // Check for (kMinInt / -1). | |
| 1364 if (divisor == -1 && instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | |
| 1365 __ cmp(dividend, Operand(kMinInt)); | |
| 1366 DeoptimizeIf(eq, instr->environment()); | |
| 1367 } | |
| 1368 test_value = - divisor - 1; | |
| 1369 power = WhichPowerOf2(-divisor); | |
| 1370 } | 1389 } |
| 1371 | 1390 if (shift > 0) __ mov(result, Operand(result, ASR, shift)); |
| 1372 if (test_value != 0) { | 1391 if (divisor < 0) __ rsb(result, result, Operand(0)); |
| 1373 if (instr->hydrogen()->CheckFlag( | |
| 1374 HInstruction::kAllUsesTruncatingToInt32)) { | |
| 1375 __ sub(result, dividend, Operand::Zero(), SetCC); | |
| 1376 __ rsb(result, result, Operand::Zero(), LeaveCC, lt); | |
| 1377 __ mov(result, Operand(result, ASR, power)); | |
| 1378 if (divisor > 0) __ rsb(result, result, Operand::Zero(), LeaveCC, lt); | |
| 1379 if (divisor < 0) __ rsb(result, result, Operand::Zero(), LeaveCC, gt); | |
| 1380 return; // Don't fall through to "__ rsb" below. | |
| 1381 } else { | |
| 1382 // Deoptimize if remainder is not 0. | |
| 1383 __ tst(dividend, Operand(test_value)); | |
| 1384 DeoptimizeIf(ne, instr->environment()); | |
| 1385 __ mov(result, Operand(dividend, ASR, power)); | |
| 1386 if (divisor < 0) __ rsb(result, result, Operand(0)); | |
| 1387 } | |
| 1388 } else { | |
| 1389 if (divisor < 0) { | |
| 1390 __ rsb(result, dividend, Operand(0)); | |
| 1391 } else { | |
| 1392 __ Move(result, dividend); | |
| 1393 } | |
| 1394 } | |
| 1395 | |
| 1396 return; | 1392 return; |
| 1397 } | 1393 } |
| 1398 | 1394 |
| 1399 const Register left = ToRegister(instr->left()); | 1395 const Register left = ToRegister(instr->left()); |
| 1400 const Register right = ToRegister(instr->right()); | 1396 const Register right = ToRegister(instr->right()); |
| 1401 const Register result = ToRegister(instr->result()); | 1397 const Register result = ToRegister(instr->result()); |
| 1402 | 1398 |
| 1403 // Check for x / 0. | 1399 // Check for x / 0. |
| 1404 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 1400 if (instr->hydrogen_value()->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1405 __ cmp(right, Operand::Zero()); | 1401 __ cmp(right, Operand::Zero()); |
| 1406 DeoptimizeIf(eq, instr->environment()); | 1402 DeoptimizeIf(eq, instr->environment()); |
| 1407 } | 1403 } |
| 1408 | 1404 |
| 1409 // Check for (0 / -x) that will produce negative zero. | 1405 // Check for (0 / -x) that will produce negative zero. |
| 1410 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1406 if (instr->hydrogen_value()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1411 Label positive; | 1407 Label positive; |
| 1412 if (!instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 1408 if (!instr->hydrogen_value()->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1413 // Do the test only if it hadn't be done above. | 1409 // Do the test only if it hadn't be done above. |
| 1414 __ cmp(right, Operand::Zero()); | 1410 __ cmp(right, Operand::Zero()); |
| 1415 } | 1411 } |
| 1416 __ b(pl, &positive); | 1412 __ b(pl, &positive); |
| 1417 __ cmp(left, Operand::Zero()); | 1413 __ cmp(left, Operand::Zero()); |
| 1418 DeoptimizeIf(eq, instr->environment()); | 1414 DeoptimizeIf(eq, instr->environment()); |
| 1419 __ bind(&positive); | 1415 __ bind(&positive); |
| 1420 } | 1416 } |
| 1421 | 1417 |
| 1422 // Check for (kMinInt / -1). | 1418 // Check for (kMinInt / -1). |
| 1423 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow) && | 1419 if (instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow) && |
| 1424 (!CpuFeatures::IsSupported(SUDIV) || | 1420 (!CpuFeatures::IsSupported(SUDIV) || |
| 1425 !instr->hydrogen()->CheckFlag(HValue::kAllUsesTruncatingToInt32))) { | 1421 !instr->hydrogen_value()->CheckFlag( |
| 1422 HValue::kAllUsesTruncatingToInt32))) { |
| 1426 // We don't need to check for overflow when truncating with sdiv | 1423 // We don't need to check for overflow when truncating with sdiv |
| 1427 // support because, on ARM, sdiv kMinInt, -1 -> kMinInt. | 1424 // support because, on ARM, sdiv kMinInt, -1 -> kMinInt. |
| 1428 __ cmp(left, Operand(kMinInt)); | 1425 __ cmp(left, Operand(kMinInt)); |
| 1429 __ cmp(right, Operand(-1), eq); | 1426 __ cmp(right, Operand(-1), eq); |
| 1430 DeoptimizeIf(eq, instr->environment()); | 1427 DeoptimizeIf(eq, instr->environment()); |
| 1431 } | 1428 } |
| 1432 | 1429 |
| 1433 if (CpuFeatures::IsSupported(SUDIV)) { | 1430 if (CpuFeatures::IsSupported(SUDIV)) { |
| 1434 CpuFeatureScope scope(masm(), SUDIV); | 1431 CpuFeatureScope scope(masm(), SUDIV); |
| 1435 __ sdiv(result, left, right); | 1432 __ sdiv(result, left, right); |
| 1436 | 1433 |
| 1437 if (!instr->hydrogen()->CheckFlag( | 1434 if (!instr->hydrogen_value()->CheckFlag( |
| 1438 HInstruction::kAllUsesTruncatingToInt32)) { | 1435 HInstruction::kAllUsesTruncatingToInt32)) { |
| 1439 // Compute remainder and deopt if it's not zero. | 1436 // Compute remainder and deopt if it's not zero. |
| 1440 const Register remainder = scratch0(); | 1437 const Register remainder = scratch0(); |
| 1441 __ mls(remainder, result, right, left); | 1438 __ mls(remainder, result, right, left); |
| 1442 __ cmp(remainder, Operand::Zero()); | 1439 __ cmp(remainder, Operand::Zero()); |
| 1443 DeoptimizeIf(ne, instr->environment()); | 1440 DeoptimizeIf(ne, instr->environment()); |
| 1444 } | 1441 } |
| 1445 } else { | 1442 } else { |
| 1446 const DoubleRegister vleft = ToDoubleRegister(instr->temp()); | 1443 const DoubleRegister vleft = ToDoubleRegister(instr->temp()); |
| 1447 const DoubleRegister vright = double_scratch0(); | 1444 const DoubleRegister vright = double_scratch0(); |
| 1448 __ vmov(double_scratch0().low(), left); | 1445 __ vmov(double_scratch0().low(), left); |
| 1449 __ vcvt_f64_s32(vleft, double_scratch0().low()); | 1446 __ vcvt_f64_s32(vleft, double_scratch0().low()); |
| 1450 __ vmov(double_scratch0().low(), right); | 1447 __ vmov(double_scratch0().low(), right); |
| 1451 __ vcvt_f64_s32(vright, double_scratch0().low()); | 1448 __ vcvt_f64_s32(vright, double_scratch0().low()); |
| 1452 __ vdiv(vleft, vleft, vright); // vleft now contains the result. | 1449 __ vdiv(vleft, vleft, vright); // vleft now contains the result. |
| 1453 __ vcvt_s32_f64(double_scratch0().low(), vleft); | 1450 __ vcvt_s32_f64(double_scratch0().low(), vleft); |
| 1454 __ vmov(result, double_scratch0().low()); | 1451 __ vmov(result, double_scratch0().low()); |
| 1455 | 1452 |
| 1456 if (!instr->hydrogen()->CheckFlag( | 1453 if (!instr->hydrogen_value()->CheckFlag( |
| 1457 HInstruction::kAllUsesTruncatingToInt32)) { | 1454 HInstruction::kAllUsesTruncatingToInt32)) { |
| 1458 // Deopt if exact conversion to integer was not possible. | 1455 // Deopt if exact conversion to integer was not possible. |
| 1459 // Use vright as scratch register. | 1456 // Use vright as scratch register. |
| 1460 __ vcvt_f64_s32(double_scratch0(), double_scratch0().low()); | 1457 __ vcvt_f64_s32(double_scratch0(), double_scratch0().low()); |
| 1461 __ VFPCompareAndSetFlags(vleft, double_scratch0()); | 1458 __ VFPCompareAndSetFlags(vleft, double_scratch0()); |
| 1462 DeoptimizeIf(ne, instr->environment()); | 1459 DeoptimizeIf(ne, instr->environment()); |
| 1463 } | 1460 } |
| 1464 } | 1461 } |
| 1465 } | 1462 } |
| 1466 | 1463 |
| (...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1860 } | 1857 } |
| 1861 | 1858 |
| 1862 | 1859 |
| 1863 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { | 1860 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { |
| 1864 Register result = ToRegister(instr->result()); | 1861 Register result = ToRegister(instr->result()); |
| 1865 Register map = ToRegister(instr->value()); | 1862 Register map = ToRegister(instr->value()); |
| 1866 __ EnumLength(result, map); | 1863 __ EnumLength(result, map); |
| 1867 } | 1864 } |
| 1868 | 1865 |
| 1869 | 1866 |
| 1870 void LCodeGen::DoElementsKind(LElementsKind* instr) { | |
| 1871 Register result = ToRegister(instr->result()); | |
| 1872 Register input = ToRegister(instr->value()); | |
| 1873 | |
| 1874 // Load map into |result|. | |
| 1875 __ ldr(result, FieldMemOperand(input, HeapObject::kMapOffset)); | |
| 1876 // Load the map's "bit field 2" into |result|. We only need the first byte, | |
| 1877 // but the following bit field extraction takes care of that anyway. | |
| 1878 __ ldr(result, FieldMemOperand(result, Map::kBitField2Offset)); | |
| 1879 // Retrieve elements_kind from bit field 2. | |
| 1880 __ ubfx(result, result, Map::kElementsKindShift, Map::kElementsKindBitCount); | |
| 1881 } | |
| 1882 | |
| 1883 | |
| 1884 void LCodeGen::DoValueOf(LValueOf* instr) { | |
| 1885 Register input = ToRegister(instr->value()); | |
| 1886 Register result = ToRegister(instr->result()); | |
| 1887 Register map = ToRegister(instr->temp()); | |
| 1888 Label done; | |
| 1889 | |
| 1890 if (!instr->hydrogen()->value()->IsHeapObject()) { | |
| 1891 // If the object is a smi return the object. | |
| 1892 __ SmiTst(input); | |
| 1893 __ Move(result, input, eq); | |
| 1894 __ b(eq, &done); | |
| 1895 } | |
| 1896 | |
| 1897 // If the object is not a value type, return the object. | |
| 1898 __ CompareObjectType(input, map, map, JS_VALUE_TYPE); | |
| 1899 __ Move(result, input, ne); | |
| 1900 __ ldr(result, FieldMemOperand(input, JSValue::kValueOffset), eq); | |
| 1901 | |
| 1902 __ bind(&done); | |
| 1903 } | |
| 1904 | |
| 1905 | |
| 1906 void LCodeGen::DoDateField(LDateField* instr) { | 1867 void LCodeGen::DoDateField(LDateField* instr) { |
| 1907 Register object = ToRegister(instr->date()); | 1868 Register object = ToRegister(instr->date()); |
| 1908 Register result = ToRegister(instr->result()); | 1869 Register result = ToRegister(instr->result()); |
| 1909 Register scratch = ToRegister(instr->temp()); | 1870 Register scratch = ToRegister(instr->temp()); |
| 1910 Smi* index = instr->index(); | 1871 Smi* index = instr->index(); |
| 1911 Label runtime, done; | 1872 Label runtime, done; |
| 1912 ASSERT(object.is(result)); | 1873 ASSERT(object.is(result)); |
| 1913 ASSERT(object.is(r0)); | 1874 ASSERT(object.is(r0)); |
| 1914 ASSERT(!scratch.is(scratch0())); | 1875 ASSERT(!scratch.is(scratch0())); |
| 1915 ASSERT(!scratch.is(object)); | 1876 ASSERT(!scratch.is(object)); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2011 | 1972 |
| 2012 MemOperand operand = BuildSeqStringOperand(string, instr->index(), encoding); | 1973 MemOperand operand = BuildSeqStringOperand(string, instr->index(), encoding); |
| 2013 if (encoding == String::ONE_BYTE_ENCODING) { | 1974 if (encoding == String::ONE_BYTE_ENCODING) { |
| 2014 __ strb(value, operand); | 1975 __ strb(value, operand); |
| 2015 } else { | 1976 } else { |
| 2016 __ strh(value, operand); | 1977 __ strh(value, operand); |
| 2017 } | 1978 } |
| 2018 } | 1979 } |
| 2019 | 1980 |
| 2020 | 1981 |
| 2021 void LCodeGen::DoThrow(LThrow* instr) { | |
| 2022 __ push(ToRegister(instr->value())); | |
| 2023 ASSERT(ToRegister(instr->context()).is(cp)); | |
| 2024 CallRuntime(Runtime::kThrow, 1, instr); | |
| 2025 | |
| 2026 if (FLAG_debug_code) { | |
| 2027 __ stop("Unreachable code."); | |
| 2028 } | |
| 2029 } | |
| 2030 | |
| 2031 | |
| 2032 void LCodeGen::DoAddI(LAddI* instr) { | 1982 void LCodeGen::DoAddI(LAddI* instr) { |
| 2033 LOperand* left = instr->left(); | 1983 LOperand* left = instr->left(); |
| 2034 LOperand* right = instr->right(); | 1984 LOperand* right = instr->right(); |
| 2035 LOperand* result = instr->result(); | 1985 LOperand* result = instr->result(); |
| 2036 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1986 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
| 2037 SBit set_cond = can_overflow ? SetCC : LeaveCC; | 1987 SBit set_cond = can_overflow ? SetCC : LeaveCC; |
| 2038 | 1988 |
| 2039 if (right->IsStackSlot() || right->IsArgument()) { | 1989 if (right->IsStackSlot() || right->IsArgument()) { |
| 2040 Register right_reg = EmitLoadRegister(right, ip); | 1990 Register right_reg = EmitLoadRegister(right, ip); |
| 2041 __ add(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); | 1991 __ add(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); |
| (...skipping 1096 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3138 __ bind(&done); | 3088 __ bind(&done); |
| 3139 } | 3089 } |
| 3140 | 3090 |
| 3141 | 3091 |
| 3142 void LCodeGen::DoLoadRoot(LLoadRoot* instr) { | 3092 void LCodeGen::DoLoadRoot(LLoadRoot* instr) { |
| 3143 Register result = ToRegister(instr->result()); | 3093 Register result = ToRegister(instr->result()); |
| 3144 __ LoadRoot(result, instr->index()); | 3094 __ LoadRoot(result, instr->index()); |
| 3145 } | 3095 } |
| 3146 | 3096 |
| 3147 | 3097 |
| 3148 void LCodeGen::DoLoadExternalArrayPointer( | |
| 3149 LLoadExternalArrayPointer* instr) { | |
| 3150 Register to_reg = ToRegister(instr->result()); | |
| 3151 Register from_reg = ToRegister(instr->object()); | |
| 3152 __ ldr(to_reg, FieldMemOperand(from_reg, | |
| 3153 ExternalArray::kExternalPointerOffset)); | |
| 3154 } | |
| 3155 | |
| 3156 | |
| 3157 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { | 3098 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { |
| 3158 Register arguments = ToRegister(instr->arguments()); | 3099 Register arguments = ToRegister(instr->arguments()); |
| 3159 Register result = ToRegister(instr->result()); | 3100 Register result = ToRegister(instr->result()); |
| 3160 // There are two words between the frame pointer and the last argument. | 3101 // There are two words between the frame pointer and the last argument. |
| 3161 // Subtracting from length accounts for one of them add one more. | 3102 // Subtracting from length accounts for one of them add one more. |
| 3162 if (instr->length()->IsConstantOperand()) { | 3103 if (instr->length()->IsConstantOperand()) { |
| 3163 int const_length = ToInteger32(LConstantOperand::cast(instr->length())); | 3104 int const_length = ToInteger32(LConstantOperand::cast(instr->length())); |
| 3164 if (instr->index()->IsConstantOperand()) { | 3105 if (instr->index()->IsConstantOperand()) { |
| 3165 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); | 3106 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
| 3166 int index = (const_length - const_index) + 1; | 3107 int index = (const_length - const_index) + 1; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3205 key = ToRegister(instr->key()); | 3146 key = ToRegister(instr->key()); |
| 3206 } | 3147 } |
| 3207 int element_size_shift = ElementsKindToShiftSize(elements_kind); | 3148 int element_size_shift = ElementsKindToShiftSize(elements_kind); |
| 3208 int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) | 3149 int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) |
| 3209 ? (element_size_shift - kSmiTagSize) : element_size_shift; | 3150 ? (element_size_shift - kSmiTagSize) : element_size_shift; |
| 3210 int additional_offset = IsFixedTypedArrayElementsKind(elements_kind) | 3151 int additional_offset = IsFixedTypedArrayElementsKind(elements_kind) |
| 3211 ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag | 3152 ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag |
| 3212 : 0; | 3153 : 0; |
| 3213 | 3154 |
| 3214 | 3155 |
| 3215 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || | 3156 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || |
| 3216 elements_kind == FLOAT32_ELEMENTS || | 3157 elements_kind == FLOAT32_ELEMENTS || |
| 3217 elements_kind == EXTERNAL_DOUBLE_ELEMENTS || | 3158 elements_kind == EXTERNAL_FLOAT64_ELEMENTS || |
| 3218 elements_kind == FLOAT64_ELEMENTS) { | 3159 elements_kind == FLOAT64_ELEMENTS) { |
| 3219 int base_offset = | 3160 int base_offset = |
| 3220 (instr->additional_index() << element_size_shift) + additional_offset; | 3161 (instr->additional_index() << element_size_shift) + additional_offset; |
| 3221 DwVfpRegister result = ToDoubleRegister(instr->result()); | 3162 DwVfpRegister result = ToDoubleRegister(instr->result()); |
| 3222 Operand operand = key_is_constant | 3163 Operand operand = key_is_constant |
| 3223 ? Operand(constant_key << element_size_shift) | 3164 ? Operand(constant_key << element_size_shift) |
| 3224 : Operand(key, LSL, shift_size); | 3165 : Operand(key, LSL, shift_size); |
| 3225 __ add(scratch0(), external_pointer, operand); | 3166 __ add(scratch0(), external_pointer, operand); |
| 3226 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || | 3167 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || |
| 3227 elements_kind == FLOAT32_ELEMENTS) { | 3168 elements_kind == FLOAT32_ELEMENTS) { |
| 3228 __ vldr(double_scratch0().low(), scratch0(), base_offset); | 3169 __ vldr(double_scratch0().low(), scratch0(), base_offset); |
| 3229 __ vcvt_f64_f32(result, double_scratch0().low()); | 3170 __ vcvt_f64_f32(result, double_scratch0().low()); |
| 3230 } else { // loading doubles, not floats. | 3171 } else { // loading doubles, not floats. |
| 3231 __ vldr(result, scratch0(), base_offset); | 3172 __ vldr(result, scratch0(), base_offset); |
| 3232 } | 3173 } |
| 3233 } else { | 3174 } else { |
| 3234 Register result = ToRegister(instr->result()); | 3175 Register result = ToRegister(instr->result()); |
| 3235 MemOperand mem_operand = PrepareKeyedOperand( | 3176 MemOperand mem_operand = PrepareKeyedOperand( |
| 3236 key, external_pointer, key_is_constant, constant_key, | 3177 key, external_pointer, key_is_constant, constant_key, |
| 3237 element_size_shift, shift_size, | 3178 element_size_shift, shift_size, |
| 3238 instr->additional_index(), additional_offset); | 3179 instr->additional_index(), additional_offset); |
| 3239 switch (elements_kind) { | 3180 switch (elements_kind) { |
| 3240 case EXTERNAL_BYTE_ELEMENTS: | 3181 case EXTERNAL_INT8_ELEMENTS: |
| 3241 case INT8_ELEMENTS: | 3182 case INT8_ELEMENTS: |
| 3242 __ ldrsb(result, mem_operand); | 3183 __ ldrsb(result, mem_operand); |
| 3243 break; | 3184 break; |
| 3244 case EXTERNAL_PIXEL_ELEMENTS: | 3185 case EXTERNAL_UINT8_CLAMPED_ELEMENTS: |
| 3245 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 3186 case EXTERNAL_UINT8_ELEMENTS: |
| 3246 case UINT8_ELEMENTS: | 3187 case UINT8_ELEMENTS: |
| 3247 case UINT8_CLAMPED_ELEMENTS: | 3188 case UINT8_CLAMPED_ELEMENTS: |
| 3248 __ ldrb(result, mem_operand); | 3189 __ ldrb(result, mem_operand); |
| 3249 break; | 3190 break; |
| 3250 case EXTERNAL_SHORT_ELEMENTS: | 3191 case EXTERNAL_INT16_ELEMENTS: |
| 3251 case INT16_ELEMENTS: | 3192 case INT16_ELEMENTS: |
| 3252 __ ldrsh(result, mem_operand); | 3193 __ ldrsh(result, mem_operand); |
| 3253 break; | 3194 break; |
| 3254 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3195 case EXTERNAL_UINT16_ELEMENTS: |
| 3255 case UINT16_ELEMENTS: | 3196 case UINT16_ELEMENTS: |
| 3256 __ ldrh(result, mem_operand); | 3197 __ ldrh(result, mem_operand); |
| 3257 break; | 3198 break; |
| 3258 case EXTERNAL_INT_ELEMENTS: | 3199 case EXTERNAL_INT32_ELEMENTS: |
| 3259 case INT32_ELEMENTS: | 3200 case INT32_ELEMENTS: |
| 3260 __ ldr(result, mem_operand); | 3201 __ ldr(result, mem_operand); |
| 3261 break; | 3202 break; |
| 3262 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3203 case EXTERNAL_UINT32_ELEMENTS: |
| 3263 case UINT32_ELEMENTS: | 3204 case UINT32_ELEMENTS: |
| 3264 __ ldr(result, mem_operand); | 3205 __ ldr(result, mem_operand); |
| 3265 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { | 3206 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { |
| 3266 __ cmp(result, Operand(0x80000000)); | 3207 __ cmp(result, Operand(0x80000000)); |
| 3267 DeoptimizeIf(cs, instr->environment()); | 3208 DeoptimizeIf(cs, instr->environment()); |
| 3268 } | 3209 } |
| 3269 break; | 3210 break; |
| 3270 case FLOAT32_ELEMENTS: | 3211 case FLOAT32_ELEMENTS: |
| 3271 case FLOAT64_ELEMENTS: | 3212 case FLOAT64_ELEMENTS: |
| 3272 case EXTERNAL_FLOAT_ELEMENTS: | 3213 case EXTERNAL_FLOAT32_ELEMENTS: |
| 3273 case EXTERNAL_DOUBLE_ELEMENTS: | 3214 case EXTERNAL_FLOAT64_ELEMENTS: |
| 3274 case FAST_HOLEY_DOUBLE_ELEMENTS: | 3215 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 3275 case FAST_HOLEY_ELEMENTS: | 3216 case FAST_HOLEY_ELEMENTS: |
| 3276 case FAST_HOLEY_SMI_ELEMENTS: | 3217 case FAST_HOLEY_SMI_ELEMENTS: |
| 3277 case FAST_DOUBLE_ELEMENTS: | 3218 case FAST_DOUBLE_ELEMENTS: |
| 3278 case FAST_ELEMENTS: | 3219 case FAST_ELEMENTS: |
| 3279 case FAST_SMI_ELEMENTS: | 3220 case FAST_SMI_ELEMENTS: |
| 3280 case DICTIONARY_ELEMENTS: | 3221 case DICTIONARY_ELEMENTS: |
| 3281 case NON_STRICT_ARGUMENTS_ELEMENTS: | 3222 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 3282 UNREACHABLE(); | 3223 UNREACHABLE(); |
| 3283 break; | 3224 break; |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3481 Register receiver = ToRegister(instr->receiver()); | 3422 Register receiver = ToRegister(instr->receiver()); |
| 3482 Register function = ToRegister(instr->function()); | 3423 Register function = ToRegister(instr->function()); |
| 3483 Register result = ToRegister(instr->result()); | 3424 Register result = ToRegister(instr->result()); |
| 3484 Register scratch = scratch0(); | 3425 Register scratch = scratch0(); |
| 3485 | 3426 |
| 3486 // If the receiver is null or undefined, we have to pass the global | 3427 // If the receiver is null or undefined, we have to pass the global |
| 3487 // object as a receiver to normal functions. Values have to be | 3428 // object as a receiver to normal functions. Values have to be |
| 3488 // passed unchanged to builtins and strict-mode functions. | 3429 // passed unchanged to builtins and strict-mode functions. |
| 3489 Label global_object, result_in_receiver; | 3430 Label global_object, result_in_receiver; |
| 3490 | 3431 |
| 3491 // Do not transform the receiver to object for strict mode | 3432 if (!instr->hydrogen()->known_function()) { |
| 3492 // functions. | 3433 // Do not transform the receiver to object for strict mode |
| 3493 __ ldr(scratch, | 3434 // functions. |
| 3494 FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset)); | 3435 __ ldr(scratch, |
| 3495 __ ldr(scratch, | 3436 FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset)); |
| 3496 FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset)); | 3437 __ ldr(scratch, |
| 3497 __ tst(scratch, | 3438 FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset)); |
| 3498 Operand(1 << (SharedFunctionInfo::kStrictModeFunction + kSmiTagSize))); | 3439 int mask = 1 << (SharedFunctionInfo::kStrictModeFunction + kSmiTagSize); |
| 3499 __ b(ne, &result_in_receiver); | 3440 __ tst(scratch, Operand(mask)); |
| 3441 __ b(ne, &result_in_receiver); |
| 3500 | 3442 |
| 3501 // Do not transform the receiver to object for builtins. | 3443 // Do not transform the receiver to object for builtins. |
| 3502 __ tst(scratch, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize))); | 3444 __ tst(scratch, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize))); |
| 3503 __ b(ne, &result_in_receiver); | 3445 __ b(ne, &result_in_receiver); |
| 3446 } |
| 3504 | 3447 |
| 3505 // Normal function. Replace undefined or null with global receiver. | 3448 // Normal function. Replace undefined or null with global receiver. |
| 3506 __ LoadRoot(scratch, Heap::kNullValueRootIndex); | 3449 __ LoadRoot(scratch, Heap::kNullValueRootIndex); |
| 3507 __ cmp(receiver, scratch); | 3450 __ cmp(receiver, scratch); |
| 3508 __ b(eq, &global_object); | 3451 __ b(eq, &global_object); |
| 3509 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); | 3452 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); |
| 3510 __ cmp(receiver, scratch); | 3453 __ cmp(receiver, scratch); |
| 3511 __ b(eq, &global_object); | 3454 __ b(eq, &global_object); |
| 3512 | 3455 |
| 3513 // Deoptimize if the receiver is not a JS object. | 3456 // Deoptimize if the receiver is not a JS object. |
| 3514 __ SmiTst(receiver); | 3457 __ SmiTst(receiver); |
| 3515 DeoptimizeIf(eq, instr->environment()); | 3458 DeoptimizeIf(eq, instr->environment()); |
| 3516 __ CompareObjectType(receiver, scratch, scratch, FIRST_SPEC_OBJECT_TYPE); | 3459 __ CompareObjectType(receiver, scratch, scratch, FIRST_SPEC_OBJECT_TYPE); |
| 3517 DeoptimizeIf(lt, instr->environment()); | 3460 DeoptimizeIf(lt, instr->environment()); |
| 3461 |
| 3518 __ b(&result_in_receiver); | 3462 __ b(&result_in_receiver); |
| 3519 | |
| 3520 __ bind(&global_object); | 3463 __ bind(&global_object); |
| 3521 __ ldr(receiver, FieldMemOperand(function, JSFunction::kContextOffset)); | 3464 __ ldr(result, FieldMemOperand(function, JSFunction::kContextOffset)); |
| 3522 __ ldr(receiver, | 3465 __ ldr(result, |
| 3523 ContextOperand(receiver, Context::GLOBAL_OBJECT_INDEX)); | 3466 ContextOperand(result, Context::GLOBAL_OBJECT_INDEX)); |
| 3524 __ ldr(receiver, | 3467 __ ldr(result, |
| 3525 FieldMemOperand(receiver, GlobalObject::kGlobalReceiverOffset)); | 3468 FieldMemOperand(result, GlobalObject::kGlobalReceiverOffset)); |
| 3526 | 3469 |
| 3527 if (result.is(receiver)) { | 3470 if (result.is(receiver)) { |
| 3528 __ bind(&result_in_receiver); | 3471 __ bind(&result_in_receiver); |
| 3529 } else { | 3472 } else { |
| 3530 Label result_ok; | 3473 Label result_ok; |
| 3531 __ b(&result_ok); | 3474 __ b(&result_ok); |
| 3532 __ bind(&result_in_receiver); | 3475 __ bind(&result_in_receiver); |
| 3533 __ mov(result, receiver); | 3476 __ mov(result, receiver); |
| 3534 __ bind(&result_ok); | 3477 __ bind(&result_ok); |
| 3535 } | 3478 } |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3610 Register result = ToRegister(instr->result()); | 3553 Register result = ToRegister(instr->result()); |
| 3611 if (info()->IsOptimizing()) { | 3554 if (info()->IsOptimizing()) { |
| 3612 __ ldr(result, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 3555 __ ldr(result, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 3613 } else { | 3556 } else { |
| 3614 // If there is no frame, the context must be in cp. | 3557 // If there is no frame, the context must be in cp. |
| 3615 ASSERT(result.is(cp)); | 3558 ASSERT(result.is(cp)); |
| 3616 } | 3559 } |
| 3617 } | 3560 } |
| 3618 | 3561 |
| 3619 | 3562 |
| 3620 void LCodeGen::DoOuterContext(LOuterContext* instr) { | |
| 3621 Register context = ToRegister(instr->context()); | |
| 3622 Register result = ToRegister(instr->result()); | |
| 3623 __ ldr(result, | |
| 3624 MemOperand(context, Context::SlotOffset(Context::PREVIOUS_INDEX))); | |
| 3625 } | |
| 3626 | |
| 3627 | |
| 3628 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { | 3563 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { |
| 3629 ASSERT(ToRegister(instr->context()).is(cp)); | 3564 ASSERT(ToRegister(instr->context()).is(cp)); |
| 3630 __ push(cp); // The context is the first argument. | 3565 __ push(cp); // The context is the first argument. |
| 3631 __ Move(scratch0(), instr->hydrogen()->pairs()); | 3566 __ Move(scratch0(), instr->hydrogen()->pairs()); |
| 3632 __ push(scratch0()); | 3567 __ push(scratch0()); |
| 3633 __ mov(scratch0(), Operand(Smi::FromInt(instr->hydrogen()->flags()))); | 3568 __ mov(scratch0(), Operand(Smi::FromInt(instr->hydrogen()->flags()))); |
| 3634 __ push(scratch0()); | 3569 __ push(scratch0()); |
| 3635 CallRuntime(Runtime::kDeclareGlobals, 3, instr); | 3570 CallRuntime(Runtime::kDeclareGlobals, 3, instr); |
| 3636 } | 3571 } |
| 3637 | 3572 |
| 3638 | 3573 |
| 3639 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { | |
| 3640 Register context = ToRegister(instr->context()); | |
| 3641 Register result = ToRegister(instr->result()); | |
| 3642 __ ldr(result, ContextOperand(context, Context::GLOBAL_OBJECT_INDEX)); | |
| 3643 } | |
| 3644 | |
| 3645 | |
| 3646 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { | |
| 3647 Register global = ToRegister(instr->global_object()); | |
| 3648 Register result = ToRegister(instr->result()); | |
| 3649 __ ldr(result, FieldMemOperand(global, GlobalObject::kGlobalReceiverOffset)); | |
| 3650 } | |
| 3651 | |
| 3652 | |
| 3653 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, | 3574 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, |
| 3654 int formal_parameter_count, | 3575 int formal_parameter_count, |
| 3655 int arity, | 3576 int arity, |
| 3656 LInstruction* instr, | 3577 LInstruction* instr, |
| 3657 R1State r1_state) { | 3578 R1State r1_state) { |
| 3658 bool dont_adapt_arguments = | 3579 bool dont_adapt_arguments = |
| 3659 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; | 3580 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; |
| 3660 bool can_invoke_directly = | 3581 bool can_invoke_directly = |
| 3661 dont_adapt_arguments || formal_parameter_count == arity; | 3582 dont_adapt_arguments || formal_parameter_count == arity; |
| 3662 | 3583 |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3947 | 3868 |
| 3948 void LCodeGen::DoMathLog(LMathLog* instr) { | 3869 void LCodeGen::DoMathLog(LMathLog* instr) { |
| 3949 __ PrepareCallCFunction(0, 1, scratch0()); | 3870 __ PrepareCallCFunction(0, 1, scratch0()); |
| 3950 __ MovToFloatParameter(ToDoubleRegister(instr->value())); | 3871 __ MovToFloatParameter(ToDoubleRegister(instr->value())); |
| 3951 __ CallCFunction(ExternalReference::math_log_double_function(isolate()), | 3872 __ CallCFunction(ExternalReference::math_log_double_function(isolate()), |
| 3952 0, 1); | 3873 0, 1); |
| 3953 __ MovFromFloatResult(ToDoubleRegister(instr->result())); | 3874 __ MovFromFloatResult(ToDoubleRegister(instr->result())); |
| 3954 } | 3875 } |
| 3955 | 3876 |
| 3956 | 3877 |
| 3878 void LCodeGen::DoMathClz32(LMathClz32* instr) { |
| 3879 Register input = ToRegister(instr->value()); |
| 3880 Register result = ToRegister(instr->result()); |
| 3881 __ clz(result, input); |
| 3882 } |
| 3883 |
| 3884 |
| 3957 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { | 3885 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { |
| 3958 ASSERT(ToRegister(instr->context()).is(cp)); | 3886 ASSERT(ToRegister(instr->context()).is(cp)); |
| 3959 ASSERT(ToRegister(instr->function()).is(r1)); | 3887 ASSERT(ToRegister(instr->function()).is(r1)); |
| 3960 ASSERT(instr->HasPointerMap()); | 3888 ASSERT(instr->HasPointerMap()); |
| 3961 | 3889 |
| 3962 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 3890 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); |
| 3963 if (known_function.is_null()) { | 3891 if (known_function.is_null()) { |
| 3964 LPointerMap* pointers = instr->pointer_map(); | 3892 LPointerMap* pointers = instr->pointer_map(); |
| 3965 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3893 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
| 3966 ParameterCount count(instr->arity()); | 3894 ParameterCount count(instr->arity()); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4018 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 3946 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
| 4019 } | 3947 } |
| 4020 | 3948 |
| 4021 | 3949 |
| 4022 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 3950 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
| 4023 ASSERT(ToRegister(instr->context()).is(cp)); | 3951 ASSERT(ToRegister(instr->context()).is(cp)); |
| 4024 ASSERT(ToRegister(instr->function()).is(r1)); | 3952 ASSERT(ToRegister(instr->function()).is(r1)); |
| 4025 ASSERT(ToRegister(instr->result()).is(r0)); | 3953 ASSERT(ToRegister(instr->result()).is(r0)); |
| 4026 | 3954 |
| 4027 int arity = instr->arity(); | 3955 int arity = instr->arity(); |
| 4028 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); | 3956 CallFunctionStub stub(arity, instr->hydrogen()->function_flags()); |
| 4029 if (instr->hydrogen()->IsTailCall()) { | 3957 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 4030 if (NeedsEagerFrame()) __ mov(sp, fp); | |
| 4031 __ Jump(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); | |
| 4032 } else { | |
| 4033 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | |
| 4034 } | |
| 4035 } | 3958 } |
| 4036 | 3959 |
| 4037 | 3960 |
| 4038 void LCodeGen::DoCallNew(LCallNew* instr) { | 3961 void LCodeGen::DoCallNew(LCallNew* instr) { |
| 4039 ASSERT(ToRegister(instr->context()).is(cp)); | 3962 ASSERT(ToRegister(instr->context()).is(cp)); |
| 4040 ASSERT(ToRegister(instr->constructor()).is(r1)); | 3963 ASSERT(ToRegister(instr->constructor()).is(r1)); |
| 4041 ASSERT(ToRegister(instr->result()).is(r0)); | 3964 ASSERT(ToRegister(instr->result()).is(r0)); |
| 4042 | 3965 |
| 4043 __ mov(r0, Operand(instr->arity())); | 3966 __ mov(r0, Operand(instr->arity())); |
| 4044 // No cell in r2 for construct type feedback in optimized code | 3967 // No cell in r2 for construct type feedback in optimized code |
| 4045 Handle<Object> undefined_value(isolate()->factory()->undefined_value()); | 3968 Handle<Object> undefined_value(isolate()->factory()->undefined_value()); |
| 4046 __ mov(r2, Operand(undefined_value)); | 3969 __ mov(r2, Operand(undefined_value)); |
| 4047 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); | 3970 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); |
| 4048 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 3971 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 4049 } | 3972 } |
| 4050 | 3973 |
| 4051 | 3974 |
| 4052 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { | 3975 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { |
| 4053 ASSERT(ToRegister(instr->context()).is(cp)); | 3976 ASSERT(ToRegister(instr->context()).is(cp)); |
| 4054 ASSERT(ToRegister(instr->constructor()).is(r1)); | 3977 ASSERT(ToRegister(instr->constructor()).is(r1)); |
| 4055 ASSERT(ToRegister(instr->result()).is(r0)); | 3978 ASSERT(ToRegister(instr->result()).is(r0)); |
| 4056 | 3979 |
| 4057 __ mov(r0, Operand(instr->arity())); | 3980 __ mov(r0, Operand(instr->arity())); |
| 4058 __ mov(r2, Operand(instr->hydrogen()->property_cell())); | 3981 __ mov(r2, Operand(factory()->undefined_value())); |
| 4059 ElementsKind kind = instr->hydrogen()->elements_kind(); | 3982 ElementsKind kind = instr->hydrogen()->elements_kind(); |
| 4060 AllocationSiteOverrideMode override_mode = | 3983 AllocationSiteOverrideMode override_mode = |
| 4061 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) | 3984 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) |
| 4062 ? DISABLE_ALLOCATION_SITES | 3985 ? DISABLE_ALLOCATION_SITES |
| 4063 : DONT_OVERRIDE; | 3986 : DONT_OVERRIDE; |
| 4064 | 3987 |
| 4065 if (instr->arity() == 0) { | 3988 if (instr->arity() == 0) { |
| 4066 ArrayNoArgumentConstructorStub stub(kind, override_mode); | 3989 ArrayNoArgumentConstructorStub stub(kind, override_mode); |
| 4067 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 3990 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 4068 } else if (instr->arity() == 1) { | 3991 } else if (instr->arity() == 1) { |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4128 int offset = access.offset(); | 4051 int offset = access.offset(); |
| 4129 | 4052 |
| 4130 if (access.IsExternalMemory()) { | 4053 if (access.IsExternalMemory()) { |
| 4131 Register value = ToRegister(instr->value()); | 4054 Register value = ToRegister(instr->value()); |
| 4132 MemOperand operand = MemOperand(object, offset); | 4055 MemOperand operand = MemOperand(object, offset); |
| 4133 __ Store(value, operand, representation); | 4056 __ Store(value, operand, representation); |
| 4134 return; | 4057 return; |
| 4135 } | 4058 } |
| 4136 | 4059 |
| 4137 Handle<Map> transition = instr->transition(); | 4060 Handle<Map> transition = instr->transition(); |
| 4061 SmiCheck check_needed = |
| 4062 instr->hydrogen()->value()->IsHeapObject() |
| 4063 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
| 4138 | 4064 |
| 4139 if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { | 4065 if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { |
| 4140 Register value = ToRegister(instr->value()); | 4066 Register value = ToRegister(instr->value()); |
| 4141 if (!instr->hydrogen()->value()->type().IsHeapObject()) { | 4067 if (!instr->hydrogen()->value()->type().IsHeapObject()) { |
| 4142 __ SmiTst(value); | 4068 __ SmiTst(value); |
| 4143 DeoptimizeIf(eq, instr->environment()); | 4069 DeoptimizeIf(eq, instr->environment()); |
| 4070 |
| 4071 // We know that value is a smi now, so we can omit the check below. |
| 4072 check_needed = OMIT_SMI_CHECK; |
| 4144 } | 4073 } |
| 4145 } else if (FLAG_track_double_fields && representation.IsDouble()) { | 4074 } else if (representation.IsDouble()) { |
| 4146 ASSERT(transition.is_null()); | 4075 ASSERT(transition.is_null()); |
| 4147 ASSERT(access.IsInobject()); | 4076 ASSERT(access.IsInobject()); |
| 4148 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); | 4077 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); |
| 4149 DwVfpRegister value = ToDoubleRegister(instr->value()); | 4078 DwVfpRegister value = ToDoubleRegister(instr->value()); |
| 4150 __ vstr(value, FieldMemOperand(object, offset)); | 4079 __ vstr(value, FieldMemOperand(object, offset)); |
| 4151 return; | 4080 return; |
| 4152 } | 4081 } |
| 4153 | 4082 |
| 4154 if (!transition.is_null()) { | 4083 if (!transition.is_null()) { |
| 4155 __ mov(scratch, Operand(transition)); | 4084 __ mov(scratch, Operand(transition)); |
| 4156 __ str(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); | 4085 __ str(scratch, FieldMemOperand(object, HeapObject::kMapOffset)); |
| 4157 if (instr->hydrogen()->NeedsWriteBarrierForMap()) { | 4086 if (instr->hydrogen()->NeedsWriteBarrierForMap()) { |
| 4158 Register temp = ToRegister(instr->temp()); | 4087 Register temp = ToRegister(instr->temp()); |
| 4159 // Update the write barrier for the map field. | 4088 // Update the write barrier for the map field. |
| 4160 __ RecordWriteField(object, | 4089 __ RecordWriteField(object, |
| 4161 HeapObject::kMapOffset, | 4090 HeapObject::kMapOffset, |
| 4162 scratch, | 4091 scratch, |
| 4163 temp, | 4092 temp, |
| 4164 GetLinkRegisterState(), | 4093 GetLinkRegisterState(), |
| 4165 kSaveFPRegs, | 4094 kSaveFPRegs, |
| 4166 OMIT_REMEMBERED_SET, | 4095 OMIT_REMEMBERED_SET, |
| 4167 OMIT_SMI_CHECK); | 4096 OMIT_SMI_CHECK); |
| 4168 } | 4097 } |
| 4169 } | 4098 } |
| 4170 | 4099 |
| 4171 // Do the store. | 4100 // Do the store. |
| 4172 Register value = ToRegister(instr->value()); | 4101 Register value = ToRegister(instr->value()); |
| 4173 ASSERT(!object.is(value)); | |
| 4174 SmiCheck check_needed = | |
| 4175 instr->hydrogen()->value()->IsHeapObject() | |
| 4176 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | |
| 4177 if (access.IsInobject()) { | 4102 if (access.IsInobject()) { |
| 4178 MemOperand operand = FieldMemOperand(object, offset); | 4103 MemOperand operand = FieldMemOperand(object, offset); |
| 4179 __ Store(value, operand, representation); | 4104 __ Store(value, operand, representation); |
| 4180 if (instr->hydrogen()->NeedsWriteBarrier()) { | 4105 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 4181 // Update the write barrier for the object for in-object properties. | 4106 // Update the write barrier for the object for in-object properties. |
| 4182 __ RecordWriteField(object, | 4107 __ RecordWriteField(object, |
| 4183 offset, | 4108 offset, |
| 4184 value, | 4109 value, |
| 4185 scratch, | 4110 scratch, |
| 4186 GetLinkRegisterState(), | 4111 GetLinkRegisterState(), |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4267 } else { | 4192 } else { |
| 4268 key = ToRegister(instr->key()); | 4193 key = ToRegister(instr->key()); |
| 4269 } | 4194 } |
| 4270 int element_size_shift = ElementsKindToShiftSize(elements_kind); | 4195 int element_size_shift = ElementsKindToShiftSize(elements_kind); |
| 4271 int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) | 4196 int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) |
| 4272 ? (element_size_shift - kSmiTagSize) : element_size_shift; | 4197 ? (element_size_shift - kSmiTagSize) : element_size_shift; |
| 4273 int additional_offset = IsFixedTypedArrayElementsKind(elements_kind) | 4198 int additional_offset = IsFixedTypedArrayElementsKind(elements_kind) |
| 4274 ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag | 4199 ? FixedTypedArrayBase::kDataOffset - kHeapObjectTag |
| 4275 : 0; | 4200 : 0; |
| 4276 | 4201 |
| 4277 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || | 4202 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || |
| 4278 elements_kind == FLOAT32_ELEMENTS || | 4203 elements_kind == FLOAT32_ELEMENTS || |
| 4279 elements_kind == EXTERNAL_DOUBLE_ELEMENTS || | 4204 elements_kind == EXTERNAL_FLOAT64_ELEMENTS || |
| 4280 elements_kind == FLOAT64_ELEMENTS) { | 4205 elements_kind == FLOAT64_ELEMENTS) { |
| 4281 int base_offset = | 4206 int base_offset = |
| 4282 (instr->additional_index() << element_size_shift) + additional_offset; | 4207 (instr->additional_index() << element_size_shift) + additional_offset; |
| 4283 Register address = scratch0(); | 4208 Register address = scratch0(); |
| 4284 DwVfpRegister value(ToDoubleRegister(instr->value())); | 4209 DwVfpRegister value(ToDoubleRegister(instr->value())); |
| 4285 if (key_is_constant) { | 4210 if (key_is_constant) { |
| 4286 if (constant_key != 0) { | 4211 if (constant_key != 0) { |
| 4287 __ add(address, external_pointer, | 4212 __ add(address, external_pointer, |
| 4288 Operand(constant_key << element_size_shift)); | 4213 Operand(constant_key << element_size_shift)); |
| 4289 } else { | 4214 } else { |
| 4290 address = external_pointer; | 4215 address = external_pointer; |
| 4291 } | 4216 } |
| 4292 } else { | 4217 } else { |
| 4293 __ add(address, external_pointer, Operand(key, LSL, shift_size)); | 4218 __ add(address, external_pointer, Operand(key, LSL, shift_size)); |
| 4294 } | 4219 } |
| 4295 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || | 4220 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || |
| 4296 elements_kind == FLOAT32_ELEMENTS) { | 4221 elements_kind == FLOAT32_ELEMENTS) { |
| 4297 __ vcvt_f32_f64(double_scratch0().low(), value); | 4222 __ vcvt_f32_f64(double_scratch0().low(), value); |
| 4298 __ vstr(double_scratch0().low(), address, base_offset); | 4223 __ vstr(double_scratch0().low(), address, base_offset); |
| 4299 } else { // Storing doubles, not floats. | 4224 } else { // Storing doubles, not floats. |
| 4300 __ vstr(value, address, base_offset); | 4225 __ vstr(value, address, base_offset); |
| 4301 } | 4226 } |
| 4302 } else { | 4227 } else { |
| 4303 Register value(ToRegister(instr->value())); | 4228 Register value(ToRegister(instr->value())); |
| 4304 MemOperand mem_operand = PrepareKeyedOperand( | 4229 MemOperand mem_operand = PrepareKeyedOperand( |
| 4305 key, external_pointer, key_is_constant, constant_key, | 4230 key, external_pointer, key_is_constant, constant_key, |
| 4306 element_size_shift, shift_size, | 4231 element_size_shift, shift_size, |
| 4307 instr->additional_index(), additional_offset); | 4232 instr->additional_index(), additional_offset); |
| 4308 switch (elements_kind) { | 4233 switch (elements_kind) { |
| 4309 case EXTERNAL_PIXEL_ELEMENTS: | 4234 case EXTERNAL_UINT8_CLAMPED_ELEMENTS: |
| 4310 case EXTERNAL_BYTE_ELEMENTS: | 4235 case EXTERNAL_INT8_ELEMENTS: |
| 4311 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 4236 case EXTERNAL_UINT8_ELEMENTS: |
| 4312 case UINT8_ELEMENTS: | 4237 case UINT8_ELEMENTS: |
| 4313 case UINT8_CLAMPED_ELEMENTS: | 4238 case UINT8_CLAMPED_ELEMENTS: |
| 4314 case INT8_ELEMENTS: | 4239 case INT8_ELEMENTS: |
| 4315 __ strb(value, mem_operand); | 4240 __ strb(value, mem_operand); |
| 4316 break; | 4241 break; |
| 4317 case EXTERNAL_SHORT_ELEMENTS: | 4242 case EXTERNAL_INT16_ELEMENTS: |
| 4318 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 4243 case EXTERNAL_UINT16_ELEMENTS: |
| 4319 case INT16_ELEMENTS: | 4244 case INT16_ELEMENTS: |
| 4320 case UINT16_ELEMENTS: | 4245 case UINT16_ELEMENTS: |
| 4321 __ strh(value, mem_operand); | 4246 __ strh(value, mem_operand); |
| 4322 break; | 4247 break; |
| 4323 case EXTERNAL_INT_ELEMENTS: | 4248 case EXTERNAL_INT32_ELEMENTS: |
| 4324 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 4249 case EXTERNAL_UINT32_ELEMENTS: |
| 4325 case INT32_ELEMENTS: | 4250 case INT32_ELEMENTS: |
| 4326 case UINT32_ELEMENTS: | 4251 case UINT32_ELEMENTS: |
| 4327 __ str(value, mem_operand); | 4252 __ str(value, mem_operand); |
| 4328 break; | 4253 break; |
| 4329 case FLOAT32_ELEMENTS: | 4254 case FLOAT32_ELEMENTS: |
| 4330 case FLOAT64_ELEMENTS: | 4255 case FLOAT64_ELEMENTS: |
| 4331 case EXTERNAL_FLOAT_ELEMENTS: | 4256 case EXTERNAL_FLOAT32_ELEMENTS: |
| 4332 case EXTERNAL_DOUBLE_ELEMENTS: | 4257 case EXTERNAL_FLOAT64_ELEMENTS: |
| 4333 case FAST_DOUBLE_ELEMENTS: | 4258 case FAST_DOUBLE_ELEMENTS: |
| 4334 case FAST_ELEMENTS: | 4259 case FAST_ELEMENTS: |
| 4335 case FAST_SMI_ELEMENTS: | 4260 case FAST_SMI_ELEMENTS: |
| 4336 case FAST_HOLEY_DOUBLE_ELEMENTS: | 4261 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 4337 case FAST_HOLEY_ELEMENTS: | 4262 case FAST_HOLEY_ELEMENTS: |
| 4338 case FAST_HOLEY_SMI_ELEMENTS: | 4263 case FAST_HOLEY_SMI_ELEMENTS: |
| 4339 case DICTIONARY_ELEMENTS: | 4264 case DICTIONARY_ELEMENTS: |
| 4340 case NON_STRICT_ARGUMENTS_ELEMENTS: | 4265 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 4341 UNREACHABLE(); | 4266 UNREACHABLE(); |
| 4342 break; | 4267 break; |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4501 Register temp = ToRegister(instr->temp()); | 4426 Register temp = ToRegister(instr->temp()); |
| 4502 Label no_memento_found; | 4427 Label no_memento_found; |
| 4503 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); | 4428 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); |
| 4504 DeoptimizeIf(eq, instr->environment()); | 4429 DeoptimizeIf(eq, instr->environment()); |
| 4505 __ bind(&no_memento_found); | 4430 __ bind(&no_memento_found); |
| 4506 } | 4431 } |
| 4507 | 4432 |
| 4508 | 4433 |
| 4509 void LCodeGen::DoStringAdd(LStringAdd* instr) { | 4434 void LCodeGen::DoStringAdd(LStringAdd* instr) { |
| 4510 ASSERT(ToRegister(instr->context()).is(cp)); | 4435 ASSERT(ToRegister(instr->context()).is(cp)); |
| 4511 if (FLAG_new_string_add) { | 4436 ASSERT(ToRegister(instr->left()).is(r1)); |
| 4512 ASSERT(ToRegister(instr->left()).is(r1)); | 4437 ASSERT(ToRegister(instr->right()).is(r0)); |
| 4513 ASSERT(ToRegister(instr->right()).is(r0)); | 4438 StringAddStub stub(instr->hydrogen()->flags(), |
| 4514 NewStringAddStub stub(instr->hydrogen()->flags(), | 4439 instr->hydrogen()->pretenure_flag()); |
| 4515 isolate()->heap()->GetPretenureMode()); | 4440 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 4516 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | |
| 4517 } else { | |
| 4518 __ push(ToRegister(instr->left())); | |
| 4519 __ push(ToRegister(instr->right())); | |
| 4520 StringAddStub stub(instr->hydrogen()->flags()); | |
| 4521 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | |
| 4522 } | |
| 4523 } | 4441 } |
| 4524 | 4442 |
| 4525 | 4443 |
| 4526 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { | 4444 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { |
| 4527 class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode { | 4445 class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode { |
| 4528 public: | 4446 public: |
| 4529 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) | 4447 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) |
| 4530 : LDeferredCode(codegen), instr_(instr) { } | 4448 : LDeferredCode(codegen), instr_(instr) { } |
| 4531 virtual void Generate() V8_OVERRIDE { | 4449 virtual void Generate() V8_OVERRIDE { |
| 4532 codegen()->DoDeferredStringCharCodeAt(instr_); | 4450 codegen()->DoDeferredStringCharCodeAt(instr_); |
| (...skipping 801 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5334 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); | 5252 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); |
| 5335 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 5253 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
| 5336 flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE); | 5254 flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE); |
| 5337 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { | 5255 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { |
| 5338 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 5256 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
| 5339 flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_DATA_SPACE); | 5257 flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_DATA_SPACE); |
| 5340 } | 5258 } |
| 5341 | 5259 |
| 5342 if (instr->size()->IsConstantOperand()) { | 5260 if (instr->size()->IsConstantOperand()) { |
| 5343 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); | 5261 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); |
| 5344 __ Allocate(size, result, scratch, scratch2, deferred->entry(), flags); | 5262 if (size <= Page::kMaxRegularHeapObjectSize) { |
| 5263 __ Allocate(size, result, scratch, scratch2, deferred->entry(), flags); |
| 5264 } else { |
| 5265 __ jmp(deferred->entry()); |
| 5266 } |
| 5345 } else { | 5267 } else { |
| 5346 Register size = ToRegister(instr->size()); | 5268 Register size = ToRegister(instr->size()); |
| 5347 __ Allocate(size, | 5269 __ Allocate(size, |
| 5348 result, | 5270 result, |
| 5349 scratch, | 5271 scratch, |
| 5350 scratch2, | 5272 scratch2, |
| 5351 deferred->entry(), | 5273 deferred->entry(), |
| 5352 flags); | 5274 flags); |
| 5353 } | 5275 } |
| 5354 | 5276 |
| (...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5831 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); | 5753 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); |
| 5832 __ ldr(result, FieldMemOperand(scratch, | 5754 __ ldr(result, FieldMemOperand(scratch, |
| 5833 FixedArray::kHeaderSize - kPointerSize)); | 5755 FixedArray::kHeaderSize - kPointerSize)); |
| 5834 __ bind(&done); | 5756 __ bind(&done); |
| 5835 } | 5757 } |
| 5836 | 5758 |
| 5837 | 5759 |
| 5838 #undef __ | 5760 #undef __ |
| 5839 | 5761 |
| 5840 } } // namespace v8::internal | 5762 } } // namespace v8::internal |
| OLD | NEW |