OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <limits.h> // For LONG_MIN, LONG_MAX. | 5 #include <limits.h> // For LONG_MIN, LONG_MAX. |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM | 7 #if V8_TARGET_ARCH_ARM |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/base/division-by-constant.h" | 10 #include "src/base/division-by-constant.h" |
(...skipping 1286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1297 b(done); | 1297 b(done); |
1298 } | 1298 } |
1299 } else { | 1299 } else { |
1300 Jump(adaptor, RelocInfo::CODE_TARGET); | 1300 Jump(adaptor, RelocInfo::CODE_TARGET); |
1301 } | 1301 } |
1302 bind(®ular_invoke); | 1302 bind(®ular_invoke); |
1303 } | 1303 } |
1304 } | 1304 } |
1305 | 1305 |
1306 | 1306 |
1307 void MacroAssembler::InvokeCode(Register code, | 1307 void MacroAssembler::FloodFunctionIfStepping(Register fun, Register new_target, |
1308 Register new_target, | 1308 const ParameterCount& expected, |
1309 const ParameterCount& expected, | 1309 const ParameterCount& actual) { |
1310 const ParameterCount& actual, | 1310 Label skip_flooding; |
1311 InvokeFlag flag, | 1311 ExternalReference debug_step_action = |
1312 const CallWrapper& call_wrapper) { | 1312 ExternalReference::debug_last_step_action_address(isolate()); |
| 1313 mov(r4, Operand(debug_step_action)); |
| 1314 ldrb(r4, MemOperand(r4)); |
| 1315 cmp(r4, Operand(StepIn)); |
| 1316 b(ne, &skip_flooding); |
| 1317 { |
| 1318 FrameScope frame(this, |
| 1319 has_frame() ? StackFrame::NONE : StackFrame::INTERNAL); |
| 1320 if (expected.is_reg()) { |
| 1321 SmiTag(expected.reg()); |
| 1322 Push(expected.reg()); |
| 1323 } |
| 1324 if (actual.is_reg()) { |
| 1325 SmiTag(actual.reg()); |
| 1326 Push(actual.reg()); |
| 1327 } |
| 1328 if (new_target.is_valid()) { |
| 1329 Push(new_target); |
| 1330 } |
| 1331 Push(fun); |
| 1332 Push(fun); |
| 1333 CallRuntime(Runtime::kDebugPrepareStepInIfStepping, 1); |
| 1334 Pop(fun); |
| 1335 if (new_target.is_valid()) { |
| 1336 Pop(new_target); |
| 1337 } |
| 1338 if (actual.is_reg()) { |
| 1339 Pop(actual.reg()); |
| 1340 SmiUntag(actual.reg()); |
| 1341 } |
| 1342 if (expected.is_reg()) { |
| 1343 Pop(expected.reg()); |
| 1344 SmiUntag(expected.reg()); |
| 1345 } |
| 1346 } |
| 1347 bind(&skip_flooding); |
| 1348 } |
| 1349 |
| 1350 |
| 1351 void MacroAssembler::InvokeFunctionCode(Register function, Register new_target, |
| 1352 const ParameterCount& expected, |
| 1353 const ParameterCount& actual, |
| 1354 InvokeFlag flag, |
| 1355 const CallWrapper& call_wrapper) { |
1313 // You can't call a function without a valid frame. | 1356 // You can't call a function without a valid frame. |
1314 DCHECK(flag == JUMP_FUNCTION || has_frame()); | 1357 DCHECK(flag == JUMP_FUNCTION || has_frame()); |
| 1358 DCHECK(function.is(r1)); |
| 1359 DCHECK_IMPLIES(new_target.is_valid(), new_target.is(r3)); |
1315 | 1360 |
1316 // Ensure new target is passed in the correct register. Otherwise clear the | 1361 if (call_wrapper.NeedsDebugStepCheck()) { |
1317 // appropriate register in case new target is not given. | 1362 FloodFunctionIfStepping(function, new_target, expected, actual); |
1318 DCHECK_IMPLIES(new_target.is_valid(), new_target.is(r3)); | 1363 } |
| 1364 |
| 1365 // Clear the new.target register if not given. |
1319 if (!new_target.is_valid()) { | 1366 if (!new_target.is_valid()) { |
1320 LoadRoot(r3, Heap::kUndefinedValueRootIndex); | 1367 LoadRoot(r3, Heap::kUndefinedValueRootIndex); |
1321 } | 1368 } |
1322 | 1369 |
1323 Label done; | 1370 Label done; |
1324 bool definitely_mismatches = false; | 1371 bool definitely_mismatches = false; |
1325 InvokePrologue(expected, actual, &done, &definitely_mismatches, flag, | 1372 InvokePrologue(expected, actual, &done, &definitely_mismatches, flag, |
1326 call_wrapper); | 1373 call_wrapper); |
1327 if (!definitely_mismatches) { | 1374 if (!definitely_mismatches) { |
| 1375 // We call indirectly through the code field in the function to |
| 1376 // allow recompilation to take effect without changing any of the |
| 1377 // call sites. |
| 1378 Register code = r4; |
| 1379 ldr(code, FieldMemOperand(function, JSFunction::kCodeEntryOffset)); |
1328 if (flag == CALL_FUNCTION) { | 1380 if (flag == CALL_FUNCTION) { |
1329 call_wrapper.BeforeCall(CallSize(code)); | 1381 call_wrapper.BeforeCall(CallSize(code)); |
1330 Call(code); | 1382 Call(code); |
1331 call_wrapper.AfterCall(); | 1383 call_wrapper.AfterCall(); |
1332 } else { | 1384 } else { |
1333 DCHECK(flag == JUMP_FUNCTION); | 1385 DCHECK(flag == JUMP_FUNCTION); |
1334 Jump(code); | 1386 Jump(code); |
1335 } | 1387 } |
1336 | 1388 |
1337 // Continue here if InvokePrologue does handle the invocation due to | 1389 // Continue here if InvokePrologue does handle the invocation due to |
1338 // mismatched parameter counts. | 1390 // mismatched parameter counts. |
1339 bind(&done); | 1391 bind(&done); |
1340 } | 1392 } |
1341 } | 1393 } |
1342 | 1394 |
1343 | 1395 |
1344 void MacroAssembler::InvokeFunction(Register fun, | 1396 void MacroAssembler::InvokeFunction(Register fun, |
1345 Register new_target, | 1397 Register new_target, |
1346 const ParameterCount& actual, | 1398 const ParameterCount& actual, |
1347 InvokeFlag flag, | 1399 InvokeFlag flag, |
1348 const CallWrapper& call_wrapper) { | 1400 const CallWrapper& call_wrapper) { |
1349 // You can't call a function without a valid frame. | 1401 // You can't call a function without a valid frame. |
1350 DCHECK(flag == JUMP_FUNCTION || has_frame()); | 1402 DCHECK(flag == JUMP_FUNCTION || has_frame()); |
1351 | 1403 |
1352 // Contract with called JS functions requires that function is passed in r1. | 1404 // Contract with called JS functions requires that function is passed in r1. |
1353 DCHECK(fun.is(r1)); | 1405 DCHECK(fun.is(r1)); |
1354 | 1406 |
1355 Register expected_reg = r2; | 1407 Register expected_reg = r2; |
1356 Register code_reg = r4; | 1408 Register temp_reg = r4; |
1357 | 1409 |
1358 ldr(code_reg, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | 1410 ldr(temp_reg, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
1359 ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 1411 ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
1360 ldr(expected_reg, | 1412 ldr(expected_reg, |
1361 FieldMemOperand(code_reg, | 1413 FieldMemOperand(temp_reg, |
1362 SharedFunctionInfo::kFormalParameterCountOffset)); | 1414 SharedFunctionInfo::kFormalParameterCountOffset)); |
1363 SmiUntag(expected_reg); | 1415 SmiUntag(expected_reg); |
1364 ldr(code_reg, | |
1365 FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); | |
1366 | 1416 |
1367 ParameterCount expected(expected_reg); | 1417 ParameterCount expected(expected_reg); |
1368 InvokeCode(code_reg, new_target, expected, actual, flag, call_wrapper); | 1418 InvokeFunctionCode(fun, new_target, expected, actual, flag, call_wrapper); |
1369 } | 1419 } |
1370 | 1420 |
1371 | 1421 |
1372 void MacroAssembler::InvokeFunction(Register function, | 1422 void MacroAssembler::InvokeFunction(Register function, |
1373 const ParameterCount& expected, | 1423 const ParameterCount& expected, |
1374 const ParameterCount& actual, | 1424 const ParameterCount& actual, |
1375 InvokeFlag flag, | 1425 InvokeFlag flag, |
1376 const CallWrapper& call_wrapper) { | 1426 const CallWrapper& call_wrapper) { |
1377 // You can't call a function without a valid frame. | 1427 // You can't call a function without a valid frame. |
1378 DCHECK(flag == JUMP_FUNCTION || has_frame()); | 1428 DCHECK(flag == JUMP_FUNCTION || has_frame()); |
1379 | 1429 |
1380 // Contract with called JS functions requires that function is passed in r1. | 1430 // Contract with called JS functions requires that function is passed in r1. |
1381 DCHECK(function.is(r1)); | 1431 DCHECK(function.is(r1)); |
1382 | 1432 |
1383 // Get the function and setup the context. | 1433 // Get the function and setup the context. |
1384 ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 1434 ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
1385 | 1435 |
1386 // We call indirectly through the code field in the function to | 1436 InvokeFunctionCode(r1, no_reg, expected, actual, flag, call_wrapper); |
1387 // allow recompilation to take effect without changing any of the | |
1388 // call sites. | |
1389 ldr(r4, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); | |
1390 InvokeCode(r4, no_reg, expected, actual, flag, call_wrapper); | |
1391 } | 1437 } |
1392 | 1438 |
1393 | 1439 |
1394 void MacroAssembler::InvokeFunction(Handle<JSFunction> function, | 1440 void MacroAssembler::InvokeFunction(Handle<JSFunction> function, |
1395 const ParameterCount& expected, | 1441 const ParameterCount& expected, |
1396 const ParameterCount& actual, | 1442 const ParameterCount& actual, |
1397 InvokeFlag flag, | 1443 InvokeFlag flag, |
1398 const CallWrapper& call_wrapper) { | 1444 const CallWrapper& call_wrapper) { |
1399 Move(r1, function); | 1445 Move(r1, function); |
1400 InvokeFunction(r1, expected, actual, flag, call_wrapper); | 1446 InvokeFunction(r1, expected, actual, flag, call_wrapper); |
(...skipping 2282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3683 } | 3729 } |
3684 } | 3730 } |
3685 if (mag.shift > 0) mov(result, Operand(result, ASR, mag.shift)); | 3731 if (mag.shift > 0) mov(result, Operand(result, ASR, mag.shift)); |
3686 add(result, result, Operand(dividend, LSR, 31)); | 3732 add(result, result, Operand(dividend, LSR, 31)); |
3687 } | 3733 } |
3688 | 3734 |
3689 } // namespace internal | 3735 } // namespace internal |
3690 } // namespace v8 | 3736 } // namespace v8 |
3691 | 3737 |
3692 #endif // V8_TARGET_ARCH_ARM | 3738 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |