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 1285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1296 b(done); | 1296 b(done); |
1297 } | 1297 } |
1298 } else { | 1298 } else { |
1299 Jump(adaptor, RelocInfo::CODE_TARGET); | 1299 Jump(adaptor, RelocInfo::CODE_TARGET); |
1300 } | 1300 } |
1301 bind(®ular_invoke); | 1301 bind(®ular_invoke); |
1302 } | 1302 } |
1303 } | 1303 } |
1304 | 1304 |
1305 | 1305 |
1306 void MacroAssembler::FloodFunctionIfStepping(Register fun, Register new_target, | 1306 void MacroAssembler::InvokeCode(Register code, |
1307 const ParameterCount& expected, | 1307 Register new_target, |
1308 const ParameterCount& actual) { | 1308 const ParameterCount& expected, |
1309 Label skip_flooding; | 1309 const ParameterCount& actual, |
1310 ExternalReference debug_step_action = | 1310 InvokeFlag flag, |
1311 ExternalReference::debug_last_step_action_address(isolate()); | 1311 const CallWrapper& call_wrapper) { |
1312 mov(r4, Operand(debug_step_action)); | |
1313 ldrb(r4, MemOperand(r4)); | |
1314 cmp(r4, Operand(StepIn)); | |
1315 b(ne, &skip_flooding); | |
1316 { | |
1317 FrameScope frame(this, | |
1318 has_frame() ? StackFrame::NONE : StackFrame::INTERNAL); | |
1319 if (expected.is_reg()) { | |
1320 SmiTag(expected.reg()); | |
1321 Push(expected.reg()); | |
1322 } | |
1323 if (actual.is_reg()) { | |
1324 SmiTag(actual.reg()); | |
1325 Push(actual.reg()); | |
1326 } | |
1327 if (new_target.is_valid()) { | |
1328 Push(new_target); | |
1329 } | |
1330 Push(fun); | |
1331 Push(fun); | |
1332 CallRuntime(Runtime::kDebugPrepareStepInIfStepping, 1); | |
1333 Pop(fun); | |
1334 if (new_target.is_valid()) { | |
1335 Pop(new_target); | |
1336 } | |
1337 if (actual.is_reg()) { | |
1338 Pop(actual.reg()); | |
1339 SmiUntag(actual.reg()); | |
1340 } | |
1341 if (expected.is_reg()) { | |
1342 Pop(expected.reg()); | |
1343 SmiUntag(expected.reg()); | |
1344 } | |
1345 } | |
1346 bind(&skip_flooding); | |
1347 } | |
1348 | |
1349 | |
1350 void MacroAssembler::InvokeFunctionCode(Register function, Register new_target, | |
1351 const ParameterCount& expected, | |
1352 const ParameterCount& actual, | |
1353 InvokeFlag flag, | |
1354 const CallWrapper& call_wrapper) { | |
1355 // You can't call a function without a valid frame. | 1312 // You can't call a function without a valid frame. |
1356 DCHECK(flag == JUMP_FUNCTION || has_frame()); | 1313 DCHECK(flag == JUMP_FUNCTION || has_frame()); |
1357 DCHECK(function.is(r1)); | 1314 |
| 1315 // Ensure new target is passed in the correct register. Otherwise clear the |
| 1316 // appropriate register in case new target is not given. |
1358 DCHECK_IMPLIES(new_target.is_valid(), new_target.is(r3)); | 1317 DCHECK_IMPLIES(new_target.is_valid(), new_target.is(r3)); |
1359 | |
1360 if (call_wrapper.NeedsDebugStepCheck()) { | |
1361 FloodFunctionIfStepping(function, new_target, expected, actual); | |
1362 } | |
1363 | |
1364 // Clear the new.target register if not given. | |
1365 if (!new_target.is_valid()) { | 1318 if (!new_target.is_valid()) { |
1366 LoadRoot(r3, Heap::kUndefinedValueRootIndex); | 1319 LoadRoot(r3, Heap::kUndefinedValueRootIndex); |
1367 } | 1320 } |
1368 | 1321 |
1369 Label done; | 1322 Label done; |
1370 bool definitely_mismatches = false; | 1323 bool definitely_mismatches = false; |
1371 InvokePrologue(expected, actual, &done, &definitely_mismatches, flag, | 1324 InvokePrologue(expected, actual, &done, &definitely_mismatches, flag, |
1372 call_wrapper); | 1325 call_wrapper); |
1373 if (!definitely_mismatches) { | 1326 if (!definitely_mismatches) { |
1374 // We call indirectly through the code field in the function to | |
1375 // allow recompilation to take effect without changing any of the | |
1376 // call sites. | |
1377 Register code = r4; | |
1378 ldr(code, FieldMemOperand(function, JSFunction::kCodeEntryOffset)); | |
1379 if (flag == CALL_FUNCTION) { | 1327 if (flag == CALL_FUNCTION) { |
1380 call_wrapper.BeforeCall(CallSize(code)); | 1328 call_wrapper.BeforeCall(CallSize(code)); |
1381 Call(code); | 1329 Call(code); |
1382 call_wrapper.AfterCall(); | 1330 call_wrapper.AfterCall(); |
1383 } else { | 1331 } else { |
1384 DCHECK(flag == JUMP_FUNCTION); | 1332 DCHECK(flag == JUMP_FUNCTION); |
1385 Jump(code); | 1333 Jump(code); |
1386 } | 1334 } |
1387 | 1335 |
1388 // Continue here if InvokePrologue does handle the invocation due to | 1336 // Continue here if InvokePrologue does handle the invocation due to |
1389 // mismatched parameter counts. | 1337 // mismatched parameter counts. |
1390 bind(&done); | 1338 bind(&done); |
1391 } | 1339 } |
1392 } | 1340 } |
1393 | 1341 |
1394 | 1342 |
1395 void MacroAssembler::InvokeFunction(Register fun, | 1343 void MacroAssembler::InvokeFunction(Register fun, |
1396 Register new_target, | 1344 Register new_target, |
1397 const ParameterCount& actual, | 1345 const ParameterCount& actual, |
1398 InvokeFlag flag, | 1346 InvokeFlag flag, |
1399 const CallWrapper& call_wrapper) { | 1347 const CallWrapper& call_wrapper) { |
1400 // You can't call a function without a valid frame. | 1348 // You can't call a function without a valid frame. |
1401 DCHECK(flag == JUMP_FUNCTION || has_frame()); | 1349 DCHECK(flag == JUMP_FUNCTION || has_frame()); |
1402 | 1350 |
1403 // Contract with called JS functions requires that function is passed in r1. | 1351 // Contract with called JS functions requires that function is passed in r1. |
1404 DCHECK(fun.is(r1)); | 1352 DCHECK(fun.is(r1)); |
1405 | 1353 |
1406 Register expected_reg = r2; | 1354 Register expected_reg = r2; |
1407 Register temp_reg = r4; | 1355 Register code_reg = r4; |
1408 | 1356 |
1409 ldr(temp_reg, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | 1357 ldr(code_reg, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
1410 ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 1358 ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
1411 ldr(expected_reg, | 1359 ldr(expected_reg, |
1412 FieldMemOperand(temp_reg, | 1360 FieldMemOperand(code_reg, |
1413 SharedFunctionInfo::kFormalParameterCountOffset)); | 1361 SharedFunctionInfo::kFormalParameterCountOffset)); |
1414 SmiUntag(expected_reg); | 1362 SmiUntag(expected_reg); |
| 1363 ldr(code_reg, |
| 1364 FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); |
1415 | 1365 |
1416 ParameterCount expected(expected_reg); | 1366 ParameterCount expected(expected_reg); |
1417 InvokeFunctionCode(fun, new_target, expected, actual, flag, call_wrapper); | 1367 InvokeCode(code_reg, new_target, expected, actual, flag, call_wrapper); |
1418 } | 1368 } |
1419 | 1369 |
1420 | 1370 |
1421 void MacroAssembler::InvokeFunction(Register function, | 1371 void MacroAssembler::InvokeFunction(Register function, |
1422 const ParameterCount& expected, | 1372 const ParameterCount& expected, |
1423 const ParameterCount& actual, | 1373 const ParameterCount& actual, |
1424 InvokeFlag flag, | 1374 InvokeFlag flag, |
1425 const CallWrapper& call_wrapper) { | 1375 const CallWrapper& call_wrapper) { |
1426 // You can't call a function without a valid frame. | 1376 // You can't call a function without a valid frame. |
1427 DCHECK(flag == JUMP_FUNCTION || has_frame()); | 1377 DCHECK(flag == JUMP_FUNCTION || has_frame()); |
1428 | 1378 |
1429 // Contract with called JS functions requires that function is passed in r1. | 1379 // Contract with called JS functions requires that function is passed in r1. |
1430 DCHECK(function.is(r1)); | 1380 DCHECK(function.is(r1)); |
1431 | 1381 |
1432 // Get the function and setup the context. | 1382 // Get the function and setup the context. |
1433 ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 1383 ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
1434 | 1384 |
1435 InvokeFunctionCode(r1, no_reg, expected, actual, flag, call_wrapper); | 1385 // We call indirectly through the code field in the function to |
| 1386 // allow recompilation to take effect without changing any of the |
| 1387 // call sites. |
| 1388 ldr(r4, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); |
| 1389 InvokeCode(r4, no_reg, expected, actual, flag, call_wrapper); |
1436 } | 1390 } |
1437 | 1391 |
1438 | 1392 |
1439 void MacroAssembler::InvokeFunction(Handle<JSFunction> function, | 1393 void MacroAssembler::InvokeFunction(Handle<JSFunction> function, |
1440 const ParameterCount& expected, | 1394 const ParameterCount& expected, |
1441 const ParameterCount& actual, | 1395 const ParameterCount& actual, |
1442 InvokeFlag flag, | 1396 InvokeFlag flag, |
1443 const CallWrapper& call_wrapper) { | 1397 const CallWrapper& call_wrapper) { |
1444 Move(r1, function); | 1398 Move(r1, function); |
1445 InvokeFunction(r1, expected, actual, flag, call_wrapper); | 1399 InvokeFunction(r1, expected, actual, flag, call_wrapper); |
(...skipping 2307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3753 } | 3707 } |
3754 } | 3708 } |
3755 if (mag.shift > 0) mov(result, Operand(result, ASR, mag.shift)); | 3709 if (mag.shift > 0) mov(result, Operand(result, ASR, mag.shift)); |
3756 add(result, result, Operand(dividend, LSR, 31)); | 3710 add(result, result, Operand(dividend, LSR, 31)); |
3757 } | 3711 } |
3758 | 3712 |
3759 } // namespace internal | 3713 } // namespace internal |
3760 } // namespace v8 | 3714 } // namespace v8 |
3761 | 3715 |
3762 #endif // V8_TARGET_ARCH_ARM | 3716 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |