| 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 |
| 11 // with the distribution. | 11 // with the distribution. |
| 12 // * Neither the name of Google Inc. nor the names of its | 12 // * Neither the name of Google Inc. nor the names of its |
| 13 // contributors may be used to endorse or promote products derived | 13 // contributors may be used to endorse or promote products derived |
| 14 // from this software without specific prior written permission. | 14 // from this software without specific prior written permission. |
| 15 // | 15 // |
| 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #if defined(V8_TARGET_ARCH_ARM) | 30 #if V8_TARGET_ARCH_ARM |
| 31 | 31 |
| 32 #include "bootstrapper.h" | 32 #include "bootstrapper.h" |
| 33 #include "code-stubs.h" | 33 #include "code-stubs.h" |
| 34 #include "regexp-macro-assembler.h" | 34 #include "regexp-macro-assembler.h" |
| 35 #include "stub-cache.h" | 35 #include "stub-cache.h" |
| 36 | 36 |
| 37 namespace v8 { | 37 namespace v8 { |
| 38 namespace internal { | 38 namespace internal { |
| 39 | 39 |
| 40 | 40 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 53 Isolate* isolate, | 53 Isolate* isolate, |
| 54 CodeStubInterfaceDescriptor* descriptor) { | 54 CodeStubInterfaceDescriptor* descriptor) { |
| 55 static Register registers[] = { r3, r2, r1, r0 }; | 55 static Register registers[] = { r3, r2, r1, r0 }; |
| 56 descriptor->register_param_count_ = 4; | 56 descriptor->register_param_count_ = 4; |
| 57 descriptor->register_params_ = registers; | 57 descriptor->register_params_ = registers; |
| 58 descriptor->deoptimization_handler_ = | 58 descriptor->deoptimization_handler_ = |
| 59 Runtime::FunctionForId(Runtime::kCreateObjectLiteralShallow)->entry; | 59 Runtime::FunctionForId(Runtime::kCreateObjectLiteralShallow)->entry; |
| 60 } | 60 } |
| 61 | 61 |
| 62 | 62 |
| 63 void CreateAllocationSiteStub::InitializeInterfaceDescriptor( |
| 64 Isolate* isolate, |
| 65 CodeStubInterfaceDescriptor* descriptor) { |
| 66 static Register registers[] = { r2 }; |
| 67 descriptor->register_param_count_ = 1; |
| 68 descriptor->register_params_ = registers; |
| 69 descriptor->deoptimization_handler_ = NULL; |
| 70 } |
| 71 |
| 72 |
| 63 void KeyedLoadFastElementStub::InitializeInterfaceDescriptor( | 73 void KeyedLoadFastElementStub::InitializeInterfaceDescriptor( |
| 64 Isolate* isolate, | 74 Isolate* isolate, |
| 65 CodeStubInterfaceDescriptor* descriptor) { | 75 CodeStubInterfaceDescriptor* descriptor) { |
| 66 static Register registers[] = { r1, r0 }; | 76 static Register registers[] = { r1, r0 }; |
| 67 descriptor->register_param_count_ = 2; | 77 descriptor->register_param_count_ = 2; |
| 68 descriptor->register_params_ = registers; | 78 descriptor->register_params_ = registers; |
| 69 descriptor->deoptimization_handler_ = | 79 descriptor->deoptimization_handler_ = |
| 70 FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure); | 80 FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure); |
| 71 } | 81 } |
| 72 | 82 |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 } | 229 } |
| 220 | 230 |
| 221 | 231 |
| 222 void InternalArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( | 232 void InternalArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( |
| 223 Isolate* isolate, | 233 Isolate* isolate, |
| 224 CodeStubInterfaceDescriptor* descriptor) { | 234 CodeStubInterfaceDescriptor* descriptor) { |
| 225 InitializeInternalArrayConstructorDescriptor(isolate, descriptor, -1); | 235 InitializeInternalArrayConstructorDescriptor(isolate, descriptor, -1); |
| 226 } | 236 } |
| 227 | 237 |
| 228 | 238 |
| 239 void UnaryOpStub::InitializeInterfaceDescriptor( |
| 240 Isolate* isolate, |
| 241 CodeStubInterfaceDescriptor* descriptor) { |
| 242 static Register registers[] = { r0 }; |
| 243 descriptor->register_param_count_ = 1; |
| 244 descriptor->register_params_ = registers; |
| 245 descriptor->deoptimization_handler_ = |
| 246 FUNCTION_ADDR(UnaryOpIC_Miss); |
| 247 } |
| 248 |
| 249 |
| 250 void StoreGlobalStub::InitializeInterfaceDescriptor( |
| 251 Isolate* isolate, |
| 252 CodeStubInterfaceDescriptor* descriptor) { |
| 253 static Register registers[] = { r1, r2, r0 }; |
| 254 descriptor->register_param_count_ = 3; |
| 255 descriptor->register_params_ = registers; |
| 256 descriptor->deoptimization_handler_ = |
| 257 FUNCTION_ADDR(StoreIC_MissFromStubFailure); |
| 258 } |
| 259 |
| 260 |
| 229 #define __ ACCESS_MASM(masm) | 261 #define __ ACCESS_MASM(masm) |
| 230 | 262 |
| 263 |
| 231 static void EmitIdenticalObjectComparison(MacroAssembler* masm, | 264 static void EmitIdenticalObjectComparison(MacroAssembler* masm, |
| 232 Label* slow, | 265 Label* slow, |
| 233 Condition cond); | 266 Condition cond); |
| 234 static void EmitSmiNonsmiComparison(MacroAssembler* masm, | 267 static void EmitSmiNonsmiComparison(MacroAssembler* masm, |
| 235 Register lhs, | 268 Register lhs, |
| 236 Register rhs, | 269 Register rhs, |
| 237 Label* lhs_not_nan, | 270 Label* lhs_not_nan, |
| 238 Label* slow, | 271 Label* slow, |
| 239 bool strict); | 272 bool strict); |
| 240 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, | 273 static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm, |
| (...skipping 1041 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1282 __ CallCFunction( | 1315 __ CallCFunction( |
| 1283 ExternalReference::store_buffer_overflow_function(masm->isolate()), | 1316 ExternalReference::store_buffer_overflow_function(masm->isolate()), |
| 1284 argument_count); | 1317 argument_count); |
| 1285 if (save_doubles_ == kSaveFPRegs) { | 1318 if (save_doubles_ == kSaveFPRegs) { |
| 1286 __ RestoreFPRegs(sp, scratch); | 1319 __ RestoreFPRegs(sp, scratch); |
| 1287 } | 1320 } |
| 1288 __ ldm(ia_w, sp, kCallerSaved | pc.bit()); // Also pop pc to get Ret(0). | 1321 __ ldm(ia_w, sp, kCallerSaved | pc.bit()); // Also pop pc to get Ret(0). |
| 1289 } | 1322 } |
| 1290 | 1323 |
| 1291 | 1324 |
| 1292 void UnaryOpStub::PrintName(StringStream* stream) { | |
| 1293 const char* op_name = Token::Name(op_); | |
| 1294 const char* overwrite_name = NULL; // Make g++ happy. | |
| 1295 switch (mode_) { | |
| 1296 case UNARY_NO_OVERWRITE: overwrite_name = "Alloc"; break; | |
| 1297 case UNARY_OVERWRITE: overwrite_name = "Overwrite"; break; | |
| 1298 } | |
| 1299 stream->Add("UnaryOpStub_%s_%s_%s", | |
| 1300 op_name, | |
| 1301 overwrite_name, | |
| 1302 UnaryOpIC::GetName(operand_type_)); | |
| 1303 } | |
| 1304 | |
| 1305 | |
| 1306 // TODO(svenpanne): Use virtual functions instead of switch. | |
| 1307 void UnaryOpStub::Generate(MacroAssembler* masm) { | |
| 1308 switch (operand_type_) { | |
| 1309 case UnaryOpIC::UNINITIALIZED: | |
| 1310 GenerateTypeTransition(masm); | |
| 1311 break; | |
| 1312 case UnaryOpIC::SMI: | |
| 1313 GenerateSmiStub(masm); | |
| 1314 break; | |
| 1315 case UnaryOpIC::NUMBER: | |
| 1316 GenerateNumberStub(masm); | |
| 1317 break; | |
| 1318 case UnaryOpIC::GENERIC: | |
| 1319 GenerateGenericStub(masm); | |
| 1320 break; | |
| 1321 } | |
| 1322 } | |
| 1323 | |
| 1324 | |
| 1325 void UnaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { | |
| 1326 __ mov(r3, Operand(r0)); // the operand | |
| 1327 __ mov(r2, Operand(Smi::FromInt(op_))); | |
| 1328 __ mov(r1, Operand(Smi::FromInt(mode_))); | |
| 1329 __ mov(r0, Operand(Smi::FromInt(operand_type_))); | |
| 1330 __ Push(r3, r2, r1, r0); | |
| 1331 | |
| 1332 __ TailCallExternalReference( | |
| 1333 ExternalReference(IC_Utility(IC::kUnaryOp_Patch), masm->isolate()), 4, 1); | |
| 1334 } | |
| 1335 | |
| 1336 | |
| 1337 // TODO(svenpanne): Use virtual functions instead of switch. | |
| 1338 void UnaryOpStub::GenerateSmiStub(MacroAssembler* masm) { | |
| 1339 switch (op_) { | |
| 1340 case Token::SUB: | |
| 1341 GenerateSmiStubSub(masm); | |
| 1342 break; | |
| 1343 case Token::BIT_NOT: | |
| 1344 GenerateSmiStubBitNot(masm); | |
| 1345 break; | |
| 1346 default: | |
| 1347 UNREACHABLE(); | |
| 1348 } | |
| 1349 } | |
| 1350 | |
| 1351 | |
| 1352 void UnaryOpStub::GenerateSmiStubSub(MacroAssembler* masm) { | |
| 1353 Label non_smi, slow; | |
| 1354 GenerateSmiCodeSub(masm, &non_smi, &slow); | |
| 1355 __ bind(&non_smi); | |
| 1356 __ bind(&slow); | |
| 1357 GenerateTypeTransition(masm); | |
| 1358 } | |
| 1359 | |
| 1360 | |
| 1361 void UnaryOpStub::GenerateSmiStubBitNot(MacroAssembler* masm) { | |
| 1362 Label non_smi; | |
| 1363 GenerateSmiCodeBitNot(masm, &non_smi); | |
| 1364 __ bind(&non_smi); | |
| 1365 GenerateTypeTransition(masm); | |
| 1366 } | |
| 1367 | |
| 1368 | |
| 1369 void UnaryOpStub::GenerateSmiCodeSub(MacroAssembler* masm, | |
| 1370 Label* non_smi, | |
| 1371 Label* slow) { | |
| 1372 __ JumpIfNotSmi(r0, non_smi); | |
| 1373 | |
| 1374 // The result of negating zero or the smallest negative smi is not a smi. | |
| 1375 __ bic(ip, r0, Operand(0x80000000), SetCC); | |
| 1376 __ b(eq, slow); | |
| 1377 | |
| 1378 // Return '0 - value'. | |
| 1379 __ rsb(r0, r0, Operand::Zero()); | |
| 1380 __ Ret(); | |
| 1381 } | |
| 1382 | |
| 1383 | |
| 1384 void UnaryOpStub::GenerateSmiCodeBitNot(MacroAssembler* masm, | |
| 1385 Label* non_smi) { | |
| 1386 __ JumpIfNotSmi(r0, non_smi); | |
| 1387 | |
| 1388 // Flip bits and revert inverted smi-tag. | |
| 1389 __ mvn(r0, Operand(r0)); | |
| 1390 __ bic(r0, r0, Operand(kSmiTagMask)); | |
| 1391 __ Ret(); | |
| 1392 } | |
| 1393 | |
| 1394 | |
| 1395 // TODO(svenpanne): Use virtual functions instead of switch. | |
| 1396 void UnaryOpStub::GenerateNumberStub(MacroAssembler* masm) { | |
| 1397 switch (op_) { | |
| 1398 case Token::SUB: | |
| 1399 GenerateNumberStubSub(masm); | |
| 1400 break; | |
| 1401 case Token::BIT_NOT: | |
| 1402 GenerateNumberStubBitNot(masm); | |
| 1403 break; | |
| 1404 default: | |
| 1405 UNREACHABLE(); | |
| 1406 } | |
| 1407 } | |
| 1408 | |
| 1409 | |
| 1410 void UnaryOpStub::GenerateNumberStubSub(MacroAssembler* masm) { | |
| 1411 Label non_smi, slow, call_builtin; | |
| 1412 GenerateSmiCodeSub(masm, &non_smi, &call_builtin); | |
| 1413 __ bind(&non_smi); | |
| 1414 GenerateHeapNumberCodeSub(masm, &slow); | |
| 1415 __ bind(&slow); | |
| 1416 GenerateTypeTransition(masm); | |
| 1417 __ bind(&call_builtin); | |
| 1418 GenerateGenericCodeFallback(masm); | |
| 1419 } | |
| 1420 | |
| 1421 | |
| 1422 void UnaryOpStub::GenerateNumberStubBitNot(MacroAssembler* masm) { | |
| 1423 Label non_smi, slow; | |
| 1424 GenerateSmiCodeBitNot(masm, &non_smi); | |
| 1425 __ bind(&non_smi); | |
| 1426 GenerateHeapNumberCodeBitNot(masm, &slow); | |
| 1427 __ bind(&slow); | |
| 1428 GenerateTypeTransition(masm); | |
| 1429 } | |
| 1430 | |
| 1431 void UnaryOpStub::GenerateHeapNumberCodeSub(MacroAssembler* masm, | |
| 1432 Label* slow) { | |
| 1433 EmitCheckForHeapNumber(masm, r0, r1, r6, slow); | |
| 1434 // r0 is a heap number. Get a new heap number in r1. | |
| 1435 if (mode_ == UNARY_OVERWRITE) { | |
| 1436 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); | |
| 1437 __ eor(r2, r2, Operand(HeapNumber::kSignMask)); // Flip sign. | |
| 1438 __ str(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); | |
| 1439 } else { | |
| 1440 Label slow_allocate_heapnumber, heapnumber_allocated; | |
| 1441 __ AllocateHeapNumber(r1, r2, r3, r6, &slow_allocate_heapnumber); | |
| 1442 __ jmp(&heapnumber_allocated); | |
| 1443 | |
| 1444 __ bind(&slow_allocate_heapnumber); | |
| 1445 { | |
| 1446 FrameScope scope(masm, StackFrame::INTERNAL); | |
| 1447 __ push(r0); | |
| 1448 __ CallRuntime(Runtime::kNumberAlloc, 0); | |
| 1449 __ mov(r1, Operand(r0)); | |
| 1450 __ pop(r0); | |
| 1451 } | |
| 1452 | |
| 1453 __ bind(&heapnumber_allocated); | |
| 1454 __ ldr(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); | |
| 1455 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); | |
| 1456 __ str(r3, FieldMemOperand(r1, HeapNumber::kMantissaOffset)); | |
| 1457 __ eor(r2, r2, Operand(HeapNumber::kSignMask)); // Flip sign. | |
| 1458 __ str(r2, FieldMemOperand(r1, HeapNumber::kExponentOffset)); | |
| 1459 __ mov(r0, Operand(r1)); | |
| 1460 } | |
| 1461 __ Ret(); | |
| 1462 } | |
| 1463 | |
| 1464 | |
| 1465 void UnaryOpStub::GenerateHeapNumberCodeBitNot(MacroAssembler* masm, | |
| 1466 Label* slow) { | |
| 1467 EmitCheckForHeapNumber(masm, r0, r1, r6, slow); | |
| 1468 | |
| 1469 // Convert the heap number in r0 to an untagged integer in r1. | |
| 1470 __ vldr(d0, FieldMemOperand(r0, HeapNumber::kValueOffset)); | |
| 1471 __ ECMAToInt32(r1, d0, r2, r3, r4, d1); | |
| 1472 | |
| 1473 // Do the bitwise operation and check if the result fits in a smi. | |
| 1474 Label try_float; | |
| 1475 __ mvn(r1, Operand(r1)); | |
| 1476 __ cmn(r1, Operand(0x40000000)); | |
| 1477 __ b(mi, &try_float); | |
| 1478 | |
| 1479 // Tag the result as a smi and we're done. | |
| 1480 __ SmiTag(r0, r1); | |
| 1481 __ Ret(); | |
| 1482 | |
| 1483 // Try to store the result in a heap number. | |
| 1484 __ bind(&try_float); | |
| 1485 if (mode_ == UNARY_NO_OVERWRITE) { | |
| 1486 Label slow_allocate_heapnumber, heapnumber_allocated; | |
| 1487 __ AllocateHeapNumber(r0, r3, r4, r6, &slow_allocate_heapnumber); | |
| 1488 __ jmp(&heapnumber_allocated); | |
| 1489 | |
| 1490 __ bind(&slow_allocate_heapnumber); | |
| 1491 { | |
| 1492 FrameScope scope(masm, StackFrame::INTERNAL); | |
| 1493 // Push the lower bit of the result (left shifted to look like a smi). | |
| 1494 __ mov(r2, Operand(r1, LSL, 31)); | |
| 1495 // Push the 31 high bits (bit 0 cleared to look like a smi). | |
| 1496 __ bic(r1, r1, Operand(1)); | |
| 1497 __ Push(r2, r1); | |
| 1498 __ CallRuntime(Runtime::kNumberAlloc, 0); | |
| 1499 __ Pop(r2, r1); // Restore the result. | |
| 1500 __ orr(r1, r1, Operand(r2, LSR, 31)); | |
| 1501 } | |
| 1502 __ bind(&heapnumber_allocated); | |
| 1503 } | |
| 1504 | |
| 1505 __ vmov(s0, r1); | |
| 1506 __ vcvt_f64_s32(d0, s0); | |
| 1507 __ vstr(d0, FieldMemOperand(r0, HeapNumber::kValueOffset)); | |
| 1508 __ Ret(); | |
| 1509 } | |
| 1510 | |
| 1511 | |
| 1512 // TODO(svenpanne): Use virtual functions instead of switch. | |
| 1513 void UnaryOpStub::GenerateGenericStub(MacroAssembler* masm) { | |
| 1514 switch (op_) { | |
| 1515 case Token::SUB: | |
| 1516 GenerateGenericStubSub(masm); | |
| 1517 break; | |
| 1518 case Token::BIT_NOT: | |
| 1519 GenerateGenericStubBitNot(masm); | |
| 1520 break; | |
| 1521 default: | |
| 1522 UNREACHABLE(); | |
| 1523 } | |
| 1524 } | |
| 1525 | |
| 1526 | |
| 1527 void UnaryOpStub::GenerateGenericStubSub(MacroAssembler* masm) { | |
| 1528 Label non_smi, slow; | |
| 1529 GenerateSmiCodeSub(masm, &non_smi, &slow); | |
| 1530 __ bind(&non_smi); | |
| 1531 GenerateHeapNumberCodeSub(masm, &slow); | |
| 1532 __ bind(&slow); | |
| 1533 GenerateGenericCodeFallback(masm); | |
| 1534 } | |
| 1535 | |
| 1536 | |
| 1537 void UnaryOpStub::GenerateGenericStubBitNot(MacroAssembler* masm) { | |
| 1538 Label non_smi, slow; | |
| 1539 GenerateSmiCodeBitNot(masm, &non_smi); | |
| 1540 __ bind(&non_smi); | |
| 1541 GenerateHeapNumberCodeBitNot(masm, &slow); | |
| 1542 __ bind(&slow); | |
| 1543 GenerateGenericCodeFallback(masm); | |
| 1544 } | |
| 1545 | |
| 1546 | |
| 1547 void UnaryOpStub::GenerateGenericCodeFallback(MacroAssembler* masm) { | |
| 1548 // Handle the slow case by jumping to the JavaScript builtin. | |
| 1549 __ push(r0); | |
| 1550 switch (op_) { | |
| 1551 case Token::SUB: | |
| 1552 __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION); | |
| 1553 break; | |
| 1554 case Token::BIT_NOT: | |
| 1555 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION); | |
| 1556 break; | |
| 1557 default: | |
| 1558 UNREACHABLE(); | |
| 1559 } | |
| 1560 } | |
| 1561 | |
| 1562 | |
| 1563 // Generates code to call a C function to do a double operation. | 1325 // Generates code to call a C function to do a double operation. |
| 1564 // This code never falls through, but returns with a heap number containing | 1326 // This code never falls through, but returns with a heap number containing |
| 1565 // the result in r0. | 1327 // the result in r0. |
| 1566 // Register heapnumber_result must be a heap number in which the | 1328 // Register heapnumber_result must be a heap number in which the |
| 1567 // result of the operation will be stored. | 1329 // result of the operation will be stored. |
| 1568 // Requires the following layout on entry: | 1330 // Requires the following layout on entry: |
| 1569 // d0: Left value. | 1331 // d0: Left value. |
| 1570 // d1: Right value. | 1332 // d1: Right value. |
| 1571 // If soft float ABI, use also r0, r1, r2, r3. | 1333 // If soft float ABI, use also r0, r1, r2, r3. |
| 1572 static void CallCCodeForDoubleOperation(MacroAssembler* masm, | 1334 static void CallCCodeForDoubleOperation(MacroAssembler* masm, |
| (...skipping 1421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2994 } | 2756 } |
| 2995 | 2757 |
| 2996 | 2758 |
| 2997 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { | 2759 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { |
| 2998 CEntryStub::GenerateAheadOfTime(isolate); | 2760 CEntryStub::GenerateAheadOfTime(isolate); |
| 2999 WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(isolate); | 2761 WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(isolate); |
| 3000 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); | 2762 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); |
| 3001 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); | 2763 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); |
| 3002 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate); | 2764 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate); |
| 3003 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); | 2765 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); |
| 2766 CreateAllocationSiteStub::GenerateAheadOfTime(isolate); |
| 3004 } | 2767 } |
| 3005 | 2768 |
| 3006 | 2769 |
| 3007 void CodeStub::GenerateFPStubs(Isolate* isolate) { | 2770 void CodeStub::GenerateFPStubs(Isolate* isolate) { |
| 3008 SaveFPRegsMode mode = kSaveFPRegs; | 2771 SaveFPRegsMode mode = kSaveFPRegs; |
| 3009 CEntryStub save_doubles(1, mode); | 2772 CEntryStub save_doubles(1, mode); |
| 3010 StoreBufferOverflowStub stub(mode); | 2773 StoreBufferOverflowStub stub(mode); |
| 3011 // These stubs might already be in the snapshot, detect that and don't | 2774 // These stubs might already be in the snapshot, detect that and don't |
| 3012 // regenerate, which would lead to code stub initialization state being messed | 2775 // regenerate, which would lead to code stub initialization state being messed |
| 3013 // up. | 2776 // up. |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3070 __ ldr(r1, MemOperand(r0)); | 2833 __ ldr(r1, MemOperand(r0)); |
| 3071 __ add(r1, r1, Operand(1)); | 2834 __ add(r1, r1, Operand(1)); |
| 3072 __ str(r1, MemOperand(r0)); | 2835 __ str(r1, MemOperand(r0)); |
| 3073 } | 2836 } |
| 3074 | 2837 |
| 3075 // Call C built-in. | 2838 // Call C built-in. |
| 3076 // r0 = argc, r1 = argv | 2839 // r0 = argc, r1 = argv |
| 3077 __ mov(r0, Operand(r4)); | 2840 __ mov(r0, Operand(r4)); |
| 3078 __ mov(r1, Operand(r6)); | 2841 __ mov(r1, Operand(r6)); |
| 3079 | 2842 |
| 3080 #if defined(V8_HOST_ARCH_ARM) | 2843 #if V8_HOST_ARCH_ARM |
| 3081 int frame_alignment = MacroAssembler::ActivationFrameAlignment(); | 2844 int frame_alignment = MacroAssembler::ActivationFrameAlignment(); |
| 3082 int frame_alignment_mask = frame_alignment - 1; | 2845 int frame_alignment_mask = frame_alignment - 1; |
| 3083 if (FLAG_debug_code) { | 2846 if (FLAG_debug_code) { |
| 3084 if (frame_alignment > kPointerSize) { | 2847 if (frame_alignment > kPointerSize) { |
| 3085 Label alignment_as_expected; | 2848 Label alignment_as_expected; |
| 3086 ASSERT(IsPowerOf2(frame_alignment)); | 2849 ASSERT(IsPowerOf2(frame_alignment)); |
| 3087 __ tst(sp, Operand(frame_alignment_mask)); | 2850 __ tst(sp, Operand(frame_alignment_mask)); |
| 3088 __ b(eq, &alignment_as_expected); | 2851 __ b(eq, &alignment_as_expected); |
| 3089 // Don't use Check here, as it will call Runtime_Abort re-entering here. | 2852 // Don't use Check here, as it will call Runtime_Abort re-entering here. |
| 3090 __ stop("Unexpected alignment"); | 2853 __ stop("Unexpected alignment"); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3174 | 2937 |
| 3175 | 2938 |
| 3176 void CEntryStub::Generate(MacroAssembler* masm) { | 2939 void CEntryStub::Generate(MacroAssembler* masm) { |
| 3177 // Called from JavaScript; parameters are on stack as if calling JS function | 2940 // Called from JavaScript; parameters are on stack as if calling JS function |
| 3178 // r0: number of arguments including receiver | 2941 // r0: number of arguments including receiver |
| 3179 // r1: pointer to builtin function | 2942 // r1: pointer to builtin function |
| 3180 // fp: frame pointer (restored after C call) | 2943 // fp: frame pointer (restored after C call) |
| 3181 // sp: stack pointer (restored as callee's sp after C call) | 2944 // sp: stack pointer (restored as callee's sp after C call) |
| 3182 // cp: current context (C callee-saved) | 2945 // cp: current context (C callee-saved) |
| 3183 | 2946 |
| 2947 ProfileEntryHookStub::MaybeCallEntryHook(masm); |
| 2948 |
| 3184 // Result returned in r0 or r0+r1 by default. | 2949 // Result returned in r0 or r0+r1 by default. |
| 3185 | 2950 |
| 3186 // NOTE: Invocations of builtins may return failure objects | 2951 // NOTE: Invocations of builtins may return failure objects |
| 3187 // instead of a proper result. The builtin entry handles | 2952 // instead of a proper result. The builtin entry handles |
| 3188 // this by performing a garbage collection and retrying the | 2953 // this by performing a garbage collection and retrying the |
| 3189 // builtin once. | 2954 // builtin once. |
| 3190 | 2955 |
| 3191 // Compute the argv pointer in a callee-saved register. | 2956 // Compute the argv pointer in a callee-saved register. |
| 3192 __ add(r6, sp, Operand(r0, LSL, kPointerSizeLog2)); | 2957 __ add(r6, sp, Operand(r0, LSL, kPointerSizeLog2)); |
| 3193 __ sub(r6, r6, Operand(kPointerSize)); | 2958 __ sub(r6, r6, Operand(kPointerSize)); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3264 | 3029 |
| 3265 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { | 3030 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { |
| 3266 // r0: code entry | 3031 // r0: code entry |
| 3267 // r1: function | 3032 // r1: function |
| 3268 // r2: receiver | 3033 // r2: receiver |
| 3269 // r3: argc | 3034 // r3: argc |
| 3270 // [sp+0]: argv | 3035 // [sp+0]: argv |
| 3271 | 3036 |
| 3272 Label invoke, handler_entry, exit; | 3037 Label invoke, handler_entry, exit; |
| 3273 | 3038 |
| 3039 ProfileEntryHookStub::MaybeCallEntryHook(masm); |
| 3040 |
| 3274 // Called from C, so do not pop argc and args on exit (preserve sp) | 3041 // Called from C, so do not pop argc and args on exit (preserve sp) |
| 3275 // No need to save register-passed args | 3042 // No need to save register-passed args |
| 3276 // Save callee-saved registers (incl. cp and fp), sp, and lr | 3043 // Save callee-saved registers (incl. cp and fp), sp, and lr |
| 3277 __ stm(db_w, sp, kCalleeSaved | lr.bit()); | 3044 __ stm(db_w, sp, kCalleeSaved | lr.bit()); |
| 3278 | 3045 |
| 3279 // Save callee-saved vfp registers. | 3046 // Save callee-saved vfp registers. |
| 3280 __ vstm(db_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg); | 3047 __ vstm(db_w, sp, kFirstCalleeSavedDoubleReg, kLastCalleeSavedDoubleReg); |
| 3281 // Set up the reserved register for 0.0. | 3048 // Set up the reserved register for 0.0. |
| 3282 __ vmov(kDoubleRegZero, 0.0); | 3049 __ vmov(kDoubleRegZero, 0.0); |
| 3283 __ VFPEnsureFPSCRState(r4); | 3050 __ VFPEnsureFPSCRState(r4); |
| (...skipping 1354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4638 ASSERT_EQ(*TypeFeedbackCells::UninitializedSentinel(masm->isolate()), | 4405 ASSERT_EQ(*TypeFeedbackCells::UninitializedSentinel(masm->isolate()), |
| 4639 masm->isolate()->heap()->the_hole_value()); | 4406 masm->isolate()->heap()->the_hole_value()); |
| 4640 | 4407 |
| 4641 // Load the cache state into r3. | 4408 // Load the cache state into r3. |
| 4642 __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset)); | 4409 __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset)); |
| 4643 | 4410 |
| 4644 // A monomorphic cache hit or an already megamorphic state: invoke the | 4411 // A monomorphic cache hit or an already megamorphic state: invoke the |
| 4645 // function without changing the state. | 4412 // function without changing the state. |
| 4646 __ cmp(r3, r1); | 4413 __ cmp(r3, r1); |
| 4647 __ b(eq, &done); | 4414 __ b(eq, &done); |
| 4648 __ CompareRoot(r3, Heap::kUndefinedValueRootIndex); | |
| 4649 __ b(eq, &done); | |
| 4650 | 4415 |
| 4651 // Special handling of the Array() function, which caches not only the | 4416 // If we came here, we need to see if we are the array function. |
| 4652 // monomorphic Array function but the initial ElementsKind with special | 4417 // If we didn't have a matching function, and we didn't find the megamorph |
| 4653 // sentinels | 4418 // sentinel, then we have in the cell either some other function or an |
| 4654 Handle<Object> terminal_kind_sentinel = | 4419 // AllocationSite. Do a map check on the object in ecx. |
| 4655 TypeFeedbackCells::MonomorphicArraySentinel(masm->isolate(), | 4420 Handle<Map> allocation_site_map( |
| 4656 LAST_FAST_ELEMENTS_KIND); | 4421 masm->isolate()->heap()->allocation_site_map(), |
| 4657 __ JumpIfNotSmi(r3, &miss); | 4422 masm->isolate()); |
| 4658 __ cmp(r3, Operand(terminal_kind_sentinel)); | 4423 __ ldr(r5, FieldMemOperand(r3, 0)); |
| 4659 __ b(gt, &miss); | 4424 __ CompareRoot(r5, Heap::kAllocationSiteMapRootIndex); |
| 4425 __ b(ne, &miss); |
| 4426 |
| 4660 // Make sure the function is the Array() function | 4427 // Make sure the function is the Array() function |
| 4661 __ LoadArrayFunction(r3); | 4428 __ LoadArrayFunction(r3); |
| 4662 __ cmp(r1, r3); | 4429 __ cmp(r1, r3); |
| 4663 __ b(ne, &megamorphic); | 4430 __ b(ne, &megamorphic); |
| 4664 __ jmp(&done); | 4431 __ jmp(&done); |
| 4665 | 4432 |
| 4666 __ bind(&miss); | 4433 __ bind(&miss); |
| 4667 | 4434 |
| 4668 // A monomorphic miss (i.e, here the cache is not uninitialized) goes | 4435 // A monomorphic miss (i.e, here the cache is not uninitialized) goes |
| 4669 // megamorphic. | 4436 // megamorphic. |
| 4670 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); | 4437 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); |
| 4671 __ b(eq, &initialize); | 4438 __ b(eq, &initialize); |
| 4672 // MegamorphicSentinel is an immortal immovable object (undefined) so no | 4439 // MegamorphicSentinel is an immortal immovable object (undefined) so no |
| 4673 // write-barrier is needed. | 4440 // write-barrier is needed. |
| 4674 __ bind(&megamorphic); | 4441 __ bind(&megamorphic); |
| 4675 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 4442 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 4676 __ str(ip, FieldMemOperand(r2, Cell::kValueOffset)); | 4443 __ str(ip, FieldMemOperand(r2, Cell::kValueOffset)); |
| 4677 __ jmp(&done); | 4444 __ jmp(&done); |
| 4678 | 4445 |
| 4679 // An uninitialized cache is patched with the function or sentinel to | 4446 // An uninitialized cache is patched with the function or sentinel to |
| 4680 // indicate the ElementsKind if function is the Array constructor. | 4447 // indicate the ElementsKind if function is the Array constructor. |
| 4681 __ bind(&initialize); | 4448 __ bind(&initialize); |
| 4682 // Make sure the function is the Array() function | 4449 // Make sure the function is the Array() function |
| 4683 __ LoadArrayFunction(r3); | 4450 __ LoadArrayFunction(r3); |
| 4684 __ cmp(r1, r3); | 4451 __ cmp(r1, r3); |
| 4685 __ b(ne, ¬_array_function); | 4452 __ b(ne, ¬_array_function); |
| 4686 | 4453 |
| 4687 // The target function is the Array constructor, install a sentinel value in | 4454 // The target function is the Array constructor, |
| 4688 // the constructor's type info cell that will track the initial ElementsKind | 4455 // Create an AllocationSite if we don't already have it, store it in the cell |
| 4689 // that should be used for the array when its constructed. | 4456 { |
| 4690 Handle<Object> initial_kind_sentinel = | 4457 FrameScope scope(masm, StackFrame::INTERNAL); |
| 4691 TypeFeedbackCells::MonomorphicArraySentinel(masm->isolate(), | 4458 |
| 4692 GetInitialFastElementsKind()); | 4459 __ push(r0); |
| 4693 __ mov(r3, Operand(initial_kind_sentinel)); | 4460 __ push(r1); |
| 4694 __ str(r3, FieldMemOperand(r2, Cell::kValueOffset)); | 4461 __ push(r2); |
| 4462 |
| 4463 CreateAllocationSiteStub create_stub; |
| 4464 __ CallStub(&create_stub); |
| 4465 |
| 4466 __ pop(r2); |
| 4467 __ pop(r1); |
| 4468 __ pop(r0); |
| 4469 } |
| 4695 __ b(&done); | 4470 __ b(&done); |
| 4696 | 4471 |
| 4697 __ bind(¬_array_function); | 4472 __ bind(¬_array_function); |
| 4698 __ str(r1, FieldMemOperand(r2, Cell::kValueOffset)); | 4473 __ str(r1, FieldMemOperand(r2, Cell::kValueOffset)); |
| 4699 // No need for a write barrier here - cells are rescanned. | 4474 // No need for a write barrier here - cells are rescanned. |
| 4700 | 4475 |
| 4701 __ bind(&done); | 4476 __ bind(&done); |
| 4702 } | 4477 } |
| 4703 | 4478 |
| 4704 | 4479 |
| (...skipping 1992 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6697 __ mov(result, Operand::Zero()); | 6472 __ mov(result, Operand::Zero()); |
| 6698 __ Ret(); | 6473 __ Ret(); |
| 6699 } | 6474 } |
| 6700 | 6475 |
| 6701 | 6476 |
| 6702 struct AheadOfTimeWriteBarrierStubList { | 6477 struct AheadOfTimeWriteBarrierStubList { |
| 6703 Register object, value, address; | 6478 Register object, value, address; |
| 6704 RememberedSetAction action; | 6479 RememberedSetAction action; |
| 6705 }; | 6480 }; |
| 6706 | 6481 |
| 6482 |
| 6707 #define REG(Name) { kRegister_ ## Name ## _Code } | 6483 #define REG(Name) { kRegister_ ## Name ## _Code } |
| 6708 | 6484 |
| 6709 static const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = { | 6485 static const AheadOfTimeWriteBarrierStubList kAheadOfTime[] = { |
| 6710 // Used in RegExpExecStub. | 6486 // Used in RegExpExecStub. |
| 6711 { REG(r6), REG(r4), REG(r7), EMIT_REMEMBERED_SET }, | 6487 { REG(r6), REG(r4), REG(r7), EMIT_REMEMBERED_SET }, |
| 6712 // Used in CompileArrayPushCall. | 6488 // Used in CompileArrayPushCall. |
| 6713 // Also used in StoreIC::GenerateNormal via GenerateDictionaryStore. | 6489 // Also used in StoreIC::GenerateNormal via GenerateDictionaryStore. |
| 6714 // Also used in KeyedStoreIC::GenerateGeneric. | 6490 // Also used in KeyedStoreIC::GenerateGeneric. |
| 6715 { REG(r3), REG(r4), REG(r5), EMIT_REMEMBERED_SET }, | 6491 { REG(r3), REG(r4), REG(r5), EMIT_REMEMBERED_SET }, |
| 6716 // Used in CompileStoreGlobal. | 6492 // Used in CompileStoreGlobal. |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7064 __ add(r1, r1, Operand(1)); | 6840 __ add(r1, r1, Operand(1)); |
| 7065 } | 6841 } |
| 7066 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); | 6842 masm->LeaveFrame(StackFrame::STUB_FAILURE_TRAMPOLINE); |
| 7067 __ mov(r1, Operand(r1, LSL, kPointerSizeLog2)); | 6843 __ mov(r1, Operand(r1, LSL, kPointerSizeLog2)); |
| 7068 __ add(sp, sp, r1); | 6844 __ add(sp, sp, r1); |
| 7069 __ Ret(); | 6845 __ Ret(); |
| 7070 } | 6846 } |
| 7071 | 6847 |
| 7072 | 6848 |
| 7073 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { | 6849 void ProfileEntryHookStub::MaybeCallEntryHook(MacroAssembler* masm) { |
| 7074 if (entry_hook_ != NULL) { | 6850 if (masm->isolate()->function_entry_hook() != NULL) { |
| 7075 PredictableCodeSizeScope predictable(masm, 4 * Assembler::kInstrSize); | 6851 PredictableCodeSizeScope predictable(masm, 4 * Assembler::kInstrSize); |
| 6852 AllowStubCallsScope allow_stub_calls(masm, true); |
| 7076 ProfileEntryHookStub stub; | 6853 ProfileEntryHookStub stub; |
| 7077 __ push(lr); | 6854 __ push(lr); |
| 7078 __ CallStub(&stub); | 6855 __ CallStub(&stub); |
| 7079 __ pop(lr); | 6856 __ pop(lr); |
| 7080 } | 6857 } |
| 7081 } | 6858 } |
| 7082 | 6859 |
| 7083 | 6860 |
| 7084 void ProfileEntryHookStub::Generate(MacroAssembler* masm) { | 6861 void ProfileEntryHookStub::Generate(MacroAssembler* masm) { |
| 7085 // The entry hook is a "push lr" instruction, followed by a call. | 6862 // The entry hook is a "push lr" instruction, followed by a call. |
| 7086 const int32_t kReturnAddressDistanceFromFunctionStart = | 6863 const int32_t kReturnAddressDistanceFromFunctionStart = |
| 7087 3 * Assembler::kInstrSize; | 6864 3 * Assembler::kInstrSize; |
| 7088 | 6865 |
| 7089 // Save live volatile registers. | 6866 // This should contain all kCallerSaved registers. |
| 7090 __ Push(lr, r5, r1); | 6867 const RegList kSavedRegs = |
| 7091 const int32_t kNumSavedRegs = 3; | 6868 1 << 0 | // r0 |
| 6869 1 << 1 | // r1 |
| 6870 1 << 2 | // r2 |
| 6871 1 << 3 | // r3 |
| 6872 1 << 5 | // r5 |
| 6873 1 << 9; // r9 |
| 6874 // We also save lr, so the count here is one higher than the mask indicates. |
| 6875 const int32_t kNumSavedRegs = 7; |
| 6876 |
| 6877 ASSERT((kCallerSaved & kSavedRegs) == kCallerSaved); |
| 6878 |
| 6879 // Save all caller-save registers as this may be called from anywhere. |
| 6880 __ stm(db_w, sp, kSavedRegs | lr.bit()); |
| 7092 | 6881 |
| 7093 // Compute the function's address for the first argument. | 6882 // Compute the function's address for the first argument. |
| 7094 __ sub(r0, lr, Operand(kReturnAddressDistanceFromFunctionStart)); | 6883 __ sub(r0, lr, Operand(kReturnAddressDistanceFromFunctionStart)); |
| 7095 | 6884 |
| 7096 // The caller's return address is above the saved temporaries. | 6885 // The caller's return address is above the saved temporaries. |
| 7097 // Grab that for the second argument to the hook. | 6886 // Grab that for the second argument to the hook. |
| 7098 __ add(r1, sp, Operand(kNumSavedRegs * kPointerSize)); | 6887 __ add(r1, sp, Operand(kNumSavedRegs * kPointerSize)); |
| 7099 | 6888 |
| 7100 // Align the stack if necessary. | 6889 // Align the stack if necessary. |
| 7101 int frame_alignment = masm->ActivationFrameAlignment(); | 6890 int frame_alignment = masm->ActivationFrameAlignment(); |
| 7102 if (frame_alignment > kPointerSize) { | 6891 if (frame_alignment > kPointerSize) { |
| 7103 __ mov(r5, sp); | 6892 __ mov(r5, sp); |
| 7104 ASSERT(IsPowerOf2(frame_alignment)); | 6893 ASSERT(IsPowerOf2(frame_alignment)); |
| 7105 __ and_(sp, sp, Operand(-frame_alignment)); | 6894 __ and_(sp, sp, Operand(-frame_alignment)); |
| 7106 } | 6895 } |
| 7107 | 6896 |
| 7108 #if defined(V8_HOST_ARCH_ARM) | 6897 #if V8_HOST_ARCH_ARM |
| 7109 __ mov(ip, Operand(reinterpret_cast<int32_t>(&entry_hook_))); | 6898 int32_t entry_hook = |
| 7110 __ ldr(ip, MemOperand(ip)); | 6899 reinterpret_cast<int32_t>(masm->isolate()->function_entry_hook()); |
| 6900 __ mov(ip, Operand(entry_hook)); |
| 7111 #else | 6901 #else |
| 7112 // Under the simulator we need to indirect the entry hook through a | 6902 // Under the simulator we need to indirect the entry hook through a |
| 7113 // trampoline function at a known address. | 6903 // trampoline function at a known address. |
| 7114 Address trampoline_address = reinterpret_cast<Address>( | 6904 ApiFunction dispatcher(FUNCTION_ADDR(EntryHookTrampoline)); |
| 7115 reinterpret_cast<intptr_t>(EntryHookTrampoline)); | |
| 7116 ApiFunction dispatcher(trampoline_address); | |
| 7117 __ mov(ip, Operand(ExternalReference(&dispatcher, | 6905 __ mov(ip, Operand(ExternalReference(&dispatcher, |
| 7118 ExternalReference::BUILTIN_CALL, | 6906 ExternalReference::BUILTIN_CALL, |
| 7119 masm->isolate()))); | 6907 masm->isolate()))); |
| 7120 #endif | 6908 #endif |
| 7121 __ Call(ip); | 6909 __ Call(ip); |
| 7122 | 6910 |
| 7123 // Restore the stack pointer if needed. | 6911 // Restore the stack pointer if needed. |
| 7124 if (frame_alignment > kPointerSize) { | 6912 if (frame_alignment > kPointerSize) { |
| 7125 __ mov(sp, r5); | 6913 __ mov(sp, r5); |
| 7126 } | 6914 } |
| 7127 | 6915 |
| 7128 __ Pop(lr, r5, r1); | 6916 // Also pop pc to get Ret(0). |
| 7129 __ Ret(); | 6917 __ ldm(ia_w, sp, kSavedRegs | pc.bit()); |
| 7130 } | 6918 } |
| 7131 | 6919 |
| 7132 | 6920 |
| 7133 template<class T> | 6921 template<class T> |
| 7134 static void CreateArrayDispatch(MacroAssembler* masm) { | 6922 static void CreateArrayDispatch(MacroAssembler* masm) { |
| 7135 int last_index = GetSequenceIndexFromFastElementsKind( | 6923 int last_index = GetSequenceIndexFromFastElementsKind( |
| 7136 TERMINAL_FAST_ELEMENTS_KIND); | 6924 TERMINAL_FAST_ELEMENTS_KIND); |
| 7137 for (int i = 0; i <= last_index; ++i) { | 6925 for (int i = 0; i <= last_index; ++i) { |
| 7138 Label next; | 6926 Label next; |
| 7139 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 6927 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 7155 // r0 - number of arguments | 6943 // r0 - number of arguments |
| 7156 // r1 - constructor? | 6944 // r1 - constructor? |
| 7157 // sp[0] - last argument | 6945 // sp[0] - last argument |
| 7158 ASSERT(FAST_SMI_ELEMENTS == 0); | 6946 ASSERT(FAST_SMI_ELEMENTS == 0); |
| 7159 ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); | 6947 ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); |
| 7160 ASSERT(FAST_ELEMENTS == 2); | 6948 ASSERT(FAST_ELEMENTS == 2); |
| 7161 ASSERT(FAST_HOLEY_ELEMENTS == 3); | 6949 ASSERT(FAST_HOLEY_ELEMENTS == 3); |
| 7162 ASSERT(FAST_DOUBLE_ELEMENTS == 4); | 6950 ASSERT(FAST_DOUBLE_ELEMENTS == 4); |
| 7163 ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5); | 6951 ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5); |
| 7164 | 6952 |
| 7165 Handle<Object> undefined_sentinel( | |
| 7166 masm->isolate()->heap()->undefined_value(), | |
| 7167 masm->isolate()); | |
| 7168 | |
| 7169 // is the low bit set? If so, we are holey and that is good. | 6953 // is the low bit set? If so, we are holey and that is good. |
| 7170 __ tst(r3, Operand(1)); | 6954 __ tst(r3, Operand(1)); |
| 7171 Label normal_sequence; | 6955 Label normal_sequence; |
| 7172 __ b(ne, &normal_sequence); | 6956 __ b(ne, &normal_sequence); |
| 7173 | 6957 |
| 7174 // look at the first argument | 6958 // look at the first argument |
| 7175 __ ldr(r5, MemOperand(sp, 0)); | 6959 __ ldr(r5, MemOperand(sp, 0)); |
| 7176 __ cmp(r5, Operand::Zero()); | 6960 __ cmp(r5, Operand::Zero()); |
| 7177 __ b(eq, &normal_sequence); | 6961 __ b(eq, &normal_sequence); |
| 7178 | 6962 |
| 7179 // We are going to create a holey array, but our kind is non-holey. | 6963 // We are going to create a holey array, but our kind is non-holey. |
| 7180 // Fix kind and retry | 6964 // Fix kind and retry (only if we have an allocation site in the cell). |
| 7181 __ add(r3, r3, Operand(1)); | 6965 __ add(r3, r3, Operand(1)); |
| 7182 __ cmp(r2, Operand(undefined_sentinel)); | 6966 __ CompareRoot(r2, Heap::kUndefinedValueRootIndex); |
| 7183 __ b(eq, &normal_sequence); | 6967 __ b(eq, &normal_sequence); |
| 6968 __ ldr(r5, FieldMemOperand(r2, Cell::kValueOffset)); |
| 6969 __ ldr(r5, FieldMemOperand(r5, 0)); |
| 6970 __ CompareRoot(r5, Heap::kAllocationSiteMapRootIndex); |
| 6971 __ b(ne, &normal_sequence); |
| 7184 | 6972 |
| 7185 // Save the resulting elements kind in type info | 6973 // Save the resulting elements kind in type info |
| 7186 __ SmiTag(r3); | 6974 __ SmiTag(r3); |
| 7187 __ str(r3, FieldMemOperand(r2, kPointerSize)); | 6975 __ ldr(r5, FieldMemOperand(r2, Cell::kValueOffset)); |
| 6976 __ str(r3, FieldMemOperand(r5, AllocationSite::kPayloadOffset)); |
| 7188 __ SmiUntag(r3); | 6977 __ SmiUntag(r3); |
| 7189 | 6978 |
| 7190 __ bind(&normal_sequence); | 6979 __ bind(&normal_sequence); |
| 7191 int last_index = GetSequenceIndexFromFastElementsKind( | 6980 int last_index = GetSequenceIndexFromFastElementsKind( |
| 7192 TERMINAL_FAST_ELEMENTS_KIND); | 6981 TERMINAL_FAST_ELEMENTS_KIND); |
| 7193 for (int i = 0; i <= last_index; ++i) { | 6982 for (int i = 0; i <= last_index; ++i) { |
| 7194 Label next; | 6983 Label next; |
| 7195 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 6984 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
| 7196 __ cmp(r3, Operand(kind)); | 6985 __ cmp(r3, Operand(kind)); |
| 7197 __ b(ne, &next); | 6986 __ b(ne, &next); |
| 7198 ArraySingleArgumentConstructorStub stub(kind); | 6987 ArraySingleArgumentConstructorStub stub(kind); |
| 7199 __ TailCallStub(&stub); | 6988 __ TailCallStub(&stub); |
| 7200 __ bind(&next); | 6989 __ bind(&next); |
| 7201 } | 6990 } |
| 7202 | 6991 |
| 7203 // If we reached this point there is a problem. | 6992 // If we reached this point there is a problem. |
| 7204 __ Abort("Unexpected ElementsKind in array constructor"); | 6993 __ Abort("Unexpected ElementsKind in array constructor"); |
| 7205 } | 6994 } |
| 7206 | 6995 |
| 7207 | 6996 |
| 7208 template<class T> | 6997 template<class T> |
| 7209 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { | 6998 static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { |
| 7210 int to_index = GetSequenceIndexFromFastElementsKind( | 6999 int to_index = GetSequenceIndexFromFastElementsKind( |
| 7211 TERMINAL_FAST_ELEMENTS_KIND); | 7000 TERMINAL_FAST_ELEMENTS_KIND); |
| 7212 for (int i = 0; i <= to_index; ++i) { | 7001 for (int i = 0; i <= to_index; ++i) { |
| 7213 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 7002 ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); |
| 7214 T stub(kind); | 7003 T stub(kind); |
| 7215 stub.GetCode(isolate)->set_is_pregenerated(true); | 7004 stub.GetCode(isolate)->set_is_pregenerated(true); |
| 7216 if (AllocationSiteInfo::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) { | 7005 if (AllocationSite::GetMode(kind) != DONT_TRACK_ALLOCATION_SITE) { |
| 7217 T stub1(kind, true); | 7006 T stub1(kind, CONTEXT_CHECK_REQUIRED, DISABLE_ALLOCATION_SITES); |
| 7218 stub1.GetCode(isolate)->set_is_pregenerated(true); | 7007 stub1.GetCode(isolate)->set_is_pregenerated(true); |
| 7219 } | 7008 } |
| 7220 } | 7009 } |
| 7221 } | 7010 } |
| 7222 | 7011 |
| 7223 | 7012 |
| 7224 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { | 7013 void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { |
| 7225 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( | 7014 ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( |
| 7226 isolate); | 7015 isolate); |
| 7227 ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>( | 7016 ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>( |
| (...skipping 19 matching lines...) Expand all Loading... |
| 7247 | 7036 |
| 7248 | 7037 |
| 7249 void ArrayConstructorStub::Generate(MacroAssembler* masm) { | 7038 void ArrayConstructorStub::Generate(MacroAssembler* masm) { |
| 7250 // ----------- S t a t e ------------- | 7039 // ----------- S t a t e ------------- |
| 7251 // -- r0 : argc (only if argument_count_ == ANY) | 7040 // -- r0 : argc (only if argument_count_ == ANY) |
| 7252 // -- r1 : constructor | 7041 // -- r1 : constructor |
| 7253 // -- r2 : type info cell | 7042 // -- r2 : type info cell |
| 7254 // -- sp[0] : return address | 7043 // -- sp[0] : return address |
| 7255 // -- sp[4] : last argument | 7044 // -- sp[4] : last argument |
| 7256 // ----------------------------------- | 7045 // ----------------------------------- |
| 7257 Handle<Object> undefined_sentinel( | |
| 7258 masm->isolate()->heap()->undefined_value(), | |
| 7259 masm->isolate()); | |
| 7260 | |
| 7261 if (FLAG_debug_code) { | 7046 if (FLAG_debug_code) { |
| 7262 // The array construct code is only set for the global and natives | 7047 // The array construct code is only set for the global and natives |
| 7263 // builtin Array functions which always have maps. | 7048 // builtin Array functions which always have maps. |
| 7264 | 7049 |
| 7265 // Initial map for the builtin Array function should be a map. | 7050 // Initial map for the builtin Array function should be a map. |
| 7266 __ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); | 7051 __ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); |
| 7267 // Will both indicate a NULL and a Smi. | 7052 // Will both indicate a NULL and a Smi. |
| 7268 __ tst(r3, Operand(kSmiTagMask)); | 7053 __ tst(r3, Operand(kSmiTagMask)); |
| 7269 __ Assert(ne, "Unexpected initial map for Array function"); | 7054 __ Assert(ne, "Unexpected initial map for Array function"); |
| 7270 __ CompareObjectType(r3, r3, r4, MAP_TYPE); | 7055 __ CompareObjectType(r3, r3, r4, MAP_TYPE); |
| 7271 __ Assert(eq, "Unexpected initial map for Array function"); | 7056 __ Assert(eq, "Unexpected initial map for Array function"); |
| 7272 | 7057 |
| 7273 // We should either have undefined in ebx or a valid cell | 7058 // We should either have undefined in ebx or a valid cell |
| 7274 Label okay_here; | 7059 Label okay_here; |
| 7275 Handle<Map> cell_map = masm->isolate()->factory()->cell_map(); | 7060 Handle<Map> cell_map = masm->isolate()->factory()->cell_map(); |
| 7276 __ cmp(r2, Operand(undefined_sentinel)); | 7061 __ CompareRoot(r2, Heap::kUndefinedValueRootIndex); |
| 7277 __ b(eq, &okay_here); | 7062 __ b(eq, &okay_here); |
| 7278 __ ldr(r3, FieldMemOperand(r2, 0)); | 7063 __ ldr(r3, FieldMemOperand(r2, 0)); |
| 7279 __ cmp(r3, Operand(cell_map)); | 7064 __ cmp(r3, Operand(cell_map)); |
| 7280 __ Assert(eq, "Expected property cell in register ebx"); | 7065 __ Assert(eq, "Expected property cell in register ebx"); |
| 7281 __ bind(&okay_here); | 7066 __ bind(&okay_here); |
| 7282 } | 7067 } |
| 7283 | 7068 |
| 7284 Label no_info, switch_ready; | 7069 Label no_info, switch_ready; |
| 7285 // Get the elements kind and case on that. | 7070 // Get the elements kind and case on that. |
| 7286 __ cmp(r2, Operand(undefined_sentinel)); | 7071 __ CompareRoot(r2, Heap::kUndefinedValueRootIndex); |
| 7287 __ b(eq, &no_info); | 7072 __ b(eq, &no_info); |
| 7288 __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset)); | 7073 __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset)); |
| 7289 __ JumpIfNotSmi(r3, &no_info); | 7074 |
| 7075 // The type cell may have undefined in its value. |
| 7076 __ CompareRoot(r3, Heap::kUndefinedValueRootIndex); |
| 7077 __ b(eq, &no_info); |
| 7078 |
| 7079 // We should have an allocation site object |
| 7080 if (FLAG_debug_code) { |
| 7081 __ push(r3); |
| 7082 __ ldr(r3, FieldMemOperand(r3, 0)); |
| 7083 __ CompareRoot(r3, Heap::kAllocationSiteMapRootIndex); |
| 7084 __ Assert(eq, "Expected AllocationSite object in register edx"); |
| 7085 } |
| 7086 |
| 7087 __ ldr(r3, FieldMemOperand(r3, AllocationSite::kPayloadOffset)); |
| 7290 __ SmiUntag(r3); | 7088 __ SmiUntag(r3); |
| 7291 __ jmp(&switch_ready); | 7089 __ jmp(&switch_ready); |
| 7292 __ bind(&no_info); | 7090 __ bind(&no_info); |
| 7293 __ mov(r3, Operand(GetInitialFastElementsKind())); | 7091 __ mov(r3, Operand(GetInitialFastElementsKind())); |
| 7294 __ bind(&switch_ready); | 7092 __ bind(&switch_ready); |
| 7295 | 7093 |
| 7296 if (argument_count_ == ANY) { | 7094 if (argument_count_ == ANY) { |
| 7297 Label not_zero_case, not_one_case; | 7095 Label not_zero_case, not_one_case; |
| 7298 __ tst(r0, r0); | 7096 __ tst(r0, r0); |
| 7299 __ b(ne, ¬_zero_case); | 7097 __ b(ne, ¬_zero_case); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7401 __ bind(&fast_elements_case); | 7199 __ bind(&fast_elements_case); |
| 7402 GenerateCase(masm, FAST_ELEMENTS); | 7200 GenerateCase(masm, FAST_ELEMENTS); |
| 7403 } | 7201 } |
| 7404 | 7202 |
| 7405 | 7203 |
| 7406 #undef __ | 7204 #undef __ |
| 7407 | 7205 |
| 7408 } } // namespace v8::internal | 7206 } } // namespace v8::internal |
| 7409 | 7207 |
| 7410 #endif // V8_TARGET_ARCH_ARM | 7208 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |