OLD | NEW |
---|---|
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 1342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1353 | 1353 |
1354 | 1354 |
1355 MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, | 1355 MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, |
1356 JSObject* holder, | 1356 JSObject* holder, |
1357 JSGlobalPropertyCell* cell, | 1357 JSGlobalPropertyCell* cell, |
1358 JSFunction* function, | 1358 JSFunction* function, |
1359 String* name) { | 1359 String* name) { |
1360 // ----------- S t a t e ------------- | 1360 // ----------- S t a t e ------------- |
1361 // -- r2 : name | 1361 // -- r2 : name |
1362 // -- lr : return address | 1362 // -- lr : return address |
1363 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
1364 // -- ... | |
1365 // -- sp[argc * 4] : receiver | |
1363 // ----------------------------------- | 1366 // ----------------------------------- |
1364 | 1367 |
1365 // TODO(639): faster implementation. | |
1366 | |
1367 // If object is not an array, bail out to regular call. | 1368 // If object is not an array, bail out to regular call. |
1368 if (!object->IsJSArray() || cell != NULL) return Heap::undefined_value(); | 1369 if (!object->IsJSArray() || cell != NULL) return Heap::undefined_value(); |
1369 | 1370 |
1370 Label miss; | 1371 Label miss; |
1371 | 1372 |
1372 GenerateNameCheck(name, &miss); | 1373 GenerateNameCheck(name, &miss); |
1373 | 1374 |
1375 Register receiver = r1; | |
1376 | |
1374 // Get the receiver from the stack | 1377 // Get the receiver from the stack |
1375 const int argc = arguments().immediate(); | 1378 const int argc = arguments().immediate(); |
1376 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 1379 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); |
1377 | 1380 |
1378 // Check that the receiver isn't a smi. | 1381 // Check that the receiver isn't a smi. |
1379 __ tst(r1, Operand(kSmiTagMask)); | 1382 __ BranchOnSmi(receiver, &miss); |
1380 __ b(eq, &miss); | |
1381 | 1383 |
1382 // Check that the maps haven't changed. | 1384 // Check that the maps haven't changed. |
1383 CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, r4, name, &miss); | 1385 CheckPrototypes(JSObject::cast(object), receiver, |
1386 holder, r3, r0, r4, name, &miss); | |
1384 | 1387 |
1385 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush), | 1388 if (argc == 0) { |
1386 argc + 1, | 1389 // Nothing to do, just return the length. |
1387 1); | 1390 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
1391 __ Drop(argc + 1); | |
1392 __ Ret(); | |
1393 } else { | |
1394 Label call_builtin; | |
1395 | |
1396 Register elements = r3; | |
1397 Register end_elements = r5; | |
1398 | |
1399 // Get the elements array of the object. | |
1400 __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); | |
1401 | |
1402 // Check that the elements are in fast mode and writable. | |
1403 __ CheckMap(elements, r0, | |
1404 Heap::kFixedArrayMapRootIndex, &call_builtin, true); | |
1405 | |
1406 if (argc == 1) { // Otherwise fall through to call the builtin. | |
1407 Label exit, with_write_barrier, attempt_to_grow_elements; | |
1408 | |
1409 // Get the array's length into r0 and calculate new length. | |
1410 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | |
1411 STATIC_ASSERT(kSmiTagSize == 1); | |
1412 STATIC_ASSERT(kSmiTag == 0); | |
1413 __ add(r0, r0, Operand(Smi::FromInt(argc))); | |
1414 | |
1415 // Get the element's length. | |
1416 __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset)); | |
1417 | |
1418 // Check if we could survive without allocation. | |
1419 __ cmp(r0, r4); | |
1420 __ b(gt, &attempt_to_grow_elements); | |
1421 | |
1422 // Save new length. | |
1423 __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | |
1424 | |
1425 // Push the element. | |
1426 __ ldr(r4, MemOperand(sp, (argc - 1) * kPointerSize)); | |
1427 // We may need a register containing the address end_elements below, | |
1428 // so write back the value in end_elements. | |
1429 __ add(end_elements, elements, | |
1430 Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); | |
1431 const int kEndElementsOffset = FixedArray::kHeaderSize | |
1432 - kHeapObjectTag - argc * kPointerSize; | |
Mads Ager (chromium)
2010/11/19 08:35:23
Strange indentation. Could we move the whole expre
| |
1433 __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex)); | |
1434 | |
1435 // Check for a smi. | |
1436 __ BranchOnNotSmi(r4, &with_write_barrier); | |
1437 __ bind(&exit); | |
1438 __ Drop(argc + 1); | |
1439 __ Ret(); | |
1440 | |
1441 __ bind(&with_write_barrier); | |
1442 __ InNewSpace(elements, r4, eq, &exit); | |
1443 __ RecordWriteHelper(elements, end_elements, r4); | |
1444 __ Drop(argc + 1); | |
1445 __ Ret(); | |
1446 | |
1447 __ bind(&attempt_to_grow_elements); | |
1448 // r0: array's length + 1. | |
1449 // r4: elements' length. | |
1450 | |
1451 if (!FLAG_inline_new) { | |
1452 __ b(&call_builtin); | |
1453 } | |
1454 | |
1455 ExternalReference new_space_allocation_top = | |
1456 ExternalReference::new_space_allocation_top_address(); | |
1457 ExternalReference new_space_allocation_limit = | |
1458 ExternalReference::new_space_allocation_limit_address(); | |
1459 | |
1460 const int kAllocationDelta = 4; | |
1461 // Load top and check if it is the end of elements. | |
1462 __ add(end_elements, elements, | |
1463 Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); | |
1464 __ add(end_elements, end_elements, Operand(kEndElementsOffset)); | |
1465 __ mov(r7, Operand(new_space_allocation_top)); | |
1466 __ ldr(r6, MemOperand(r7)); | |
1467 __ cmp(end_elements, r6); | |
1468 __ b(ne, &call_builtin); | |
1469 | |
1470 __ mov(r9, Operand(new_space_allocation_limit)); | |
1471 __ ldr(r9, MemOperand(r9)); | |
1472 __ add(r6, r6, Operand(kAllocationDelta * kPointerSize)); | |
1473 __ cmp(r6, r9); | |
1474 __ b(hi, &call_builtin); | |
1475 | |
1476 // We fit and could grow elements. | |
1477 // Update new_space_allocation_top. | |
1478 __ str(r6, MemOperand(r7)); | |
1479 // Push the argument. | |
1480 __ ldr(r6, MemOperand(sp, (argc - 1) * kPointerSize)); | |
1481 __ str(r6, MemOperand(end_elements)); | |
1482 // Fill the rest with holes. | |
1483 __ LoadRoot(r6, Heap::kTheHoleValueRootIndex); | |
1484 for (int i = 1; i < kAllocationDelta; i++) { | |
1485 __ str(r6, MemOperand(end_elements, i * kPointerSize)); | |
1486 } | |
1487 | |
1488 // Update elements' and array's sizes. | |
1489 __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | |
1490 __ add(r4, r4, Operand(Smi::FromInt(kAllocationDelta))); | |
1491 __ str(r4, FieldMemOperand(elements, FixedArray::kLengthOffset)); | |
1492 | |
1493 // Elements are in new space, so write barrier is not required. | |
1494 __ Drop(argc + 1); | |
1495 __ Ret(); | |
1496 } | |
1497 __ bind(&call_builtin); | |
1498 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush), | |
1499 argc + 1, | |
1500 1); | |
1501 } | |
1388 | 1502 |
1389 // Handle call cache miss. | 1503 // Handle call cache miss. |
1390 __ bind(&miss); | 1504 __ bind(&miss); |
1391 Object* obj; | 1505 Object* obj; |
1392 { MaybeObject* maybe_obj = GenerateMissBranch(); | 1506 { MaybeObject* maybe_obj = GenerateMissBranch(); |
1393 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1507 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
1394 } | 1508 } |
1395 | 1509 |
1396 // Return the generated code. | 1510 // Return the generated code. |
1397 return GetCode(function); | 1511 return GetCode(function); |
1398 } | 1512 } |
1399 | 1513 |
1400 | 1514 |
1401 MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, | 1515 MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, |
1402 JSObject* holder, | 1516 JSObject* holder, |
1403 JSGlobalPropertyCell* cell, | 1517 JSGlobalPropertyCell* cell, |
1404 JSFunction* function, | 1518 JSFunction* function, |
1405 String* name) { | 1519 String* name) { |
1406 // ----------- S t a t e ------------- | 1520 // ----------- S t a t e ------------- |
1407 // -- r2 : name | 1521 // -- r2 : name |
1408 // -- lr : return address | 1522 // -- lr : return address |
1523 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
1524 // -- ... | |
1525 // -- sp[argc * 4] : receiver | |
1409 // ----------------------------------- | 1526 // ----------------------------------- |
1410 | 1527 |
1411 // TODO(642): faster implementation. | |
1412 | |
1413 // If object is not an array, bail out to regular call. | 1528 // If object is not an array, bail out to regular call. |
1414 if (!object->IsJSArray() || cell != NULL) return Heap::undefined_value(); | 1529 if (!object->IsJSArray() || cell != NULL) return Heap::undefined_value(); |
1415 | 1530 |
1416 Label miss; | 1531 Label miss, return_undefined, call_builtin; |
1532 | |
1533 Register receiver = r1; | |
1534 Register elements = r3; | |
1417 | 1535 |
1418 GenerateNameCheck(name, &miss); | 1536 GenerateNameCheck(name, &miss); |
1419 | 1537 |
1420 // Get the receiver from the stack | 1538 // Get the receiver from the stack |
1421 const int argc = arguments().immediate(); | 1539 const int argc = arguments().immediate(); |
1422 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 1540 __ ldr(receiver, MemOperand(sp, argc * kPointerSize)); |
1423 | 1541 |
1424 // Check that the receiver isn't a smi. | 1542 // Check that the receiver isn't a smi. |
1425 __ tst(r1, Operand(kSmiTagMask)); | 1543 __ BranchOnSmi(receiver, &miss); |
1426 __ b(eq, &miss); | |
1427 | 1544 |
1428 // Check that the maps haven't changed. | 1545 // Check that the maps haven't changed. |
1429 CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, r4, name, &miss); | 1546 CheckPrototypes(JSObject::cast(object), |
1547 receiver, holder, elements, r4, r0, name, &miss); | |
1430 | 1548 |
1549 // Get the elements array of the object. | |
1550 __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); | |
1551 | |
1552 // Check that the elements are in fast mode and writable. | |
1553 __ CheckMap(elements, r0, Heap::kFixedArrayMapRootIndex, &call_builtin, true); | |
1554 | |
1555 // Get the array's length into r4 and calculate new length. | |
1556 __ ldr(r4, FieldMemOperand(receiver, JSArray::kLengthOffset)); | |
1557 __ sub(r4, r4, Operand(Smi::FromInt(1)), SetCC); | |
1558 __ b(lt, &return_undefined); | |
1559 | |
1560 // Get the last element. | |
1561 __ LoadRoot(r6, Heap::kTheHoleValueRootIndex); | |
1562 STATIC_ASSERT(kSmiTagSize == 1); | |
1563 STATIC_ASSERT(kSmiTag == 0); | |
1564 // We can't address the last element in one operation. Compute the more | |
1565 // expensive shift first, and use an offset later on. | |
1566 __ add(elements, elements, Operand(r4, LSL, kPointerSizeLog2 - kSmiTagSize)); | |
1567 __ ldr(r0, MemOperand(elements, FixedArray::kHeaderSize - kHeapObjectTag)); | |
1568 __ cmp(r0, r6); | |
1569 __ b(eq, &call_builtin); | |
1570 | |
1571 // Set the array's length. | |
1572 __ str(r4, FieldMemOperand(receiver, JSArray::kLengthOffset)); | |
1573 | |
1574 // Fill with the hole. | |
1575 __ str(r6, MemOperand(elements, FixedArray::kHeaderSize - kHeapObjectTag)); | |
1576 __ Drop(argc + 1); | |
1577 __ Ret(); | |
1578 | |
1579 __ bind(&return_undefined); | |
1580 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | |
1581 __ Drop(argc + 1); | |
1582 __ Ret(); | |
1583 | |
1584 __ bind(&call_builtin); | |
1431 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop), | 1585 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop), |
1432 argc + 1, | 1586 argc + 1, |
1433 1); | 1587 1); |
1434 | 1588 |
1435 // Handle call cache miss. | 1589 // Handle call cache miss. |
1436 __ bind(&miss); | 1590 __ bind(&miss); |
1437 Object* obj; | 1591 Object* obj; |
1438 { MaybeObject* maybe_obj = GenerateMissBranch(); | 1592 { MaybeObject* maybe_obj = GenerateMissBranch(); |
1439 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1593 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
1440 } | 1594 } |
(...skipping 1224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2665 } | 2819 } |
2666 | 2820 |
2667 | 2821 |
2668 MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { | 2822 MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { |
2669 // ----------- S t a t e ------------- | 2823 // ----------- S t a t e ------------- |
2670 // -- lr : return address | 2824 // -- lr : return address |
2671 // -- r0 : key | 2825 // -- r0 : key |
2672 // -- r1 : receiver | 2826 // -- r1 : receiver |
2673 // ----------------------------------- | 2827 // ----------------------------------- |
2674 Label miss; | 2828 Label miss; |
2675 __ IncrementCounter(&Counters::keyed_load_string_length, 1, r1, r3); | 2829 __ IncrementCounter(&Counters::keyed_load_string_length, 1, r2, r3); |
2676 | 2830 |
2677 // Check the key is the cached one. | 2831 // Check the key is the cached one. |
2678 __ cmp(r0, Operand(Handle<String>(name))); | 2832 __ cmp(r0, Operand(Handle<String>(name))); |
2679 __ b(ne, &miss); | 2833 __ b(ne, &miss); |
2680 | 2834 |
2681 GenerateLoadStringLength(masm(), r1, r2, r3, &miss); | 2835 GenerateLoadStringLength(masm(), r1, r2, r3, &miss); |
2682 __ bind(&miss); | 2836 __ bind(&miss); |
2683 __ DecrementCounter(&Counters::keyed_load_string_length, 1, r1, r3); | 2837 __ DecrementCounter(&Counters::keyed_load_string_length, 1, r2, r3); |
2684 | 2838 |
2685 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2839 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
2686 | 2840 |
2687 return GetCode(CALLBACKS, name); | 2841 return GetCode(CALLBACKS, name); |
2688 } | 2842 } |
2689 | 2843 |
2690 | 2844 |
2691 // TODO(1224671): implement the fast case. | |
2692 MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { | 2845 MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { |
2693 // ----------- S t a t e ------------- | 2846 // ----------- S t a t e ------------- |
2694 // -- lr : return address | 2847 // -- lr : return address |
2695 // -- r0 : key | 2848 // -- r0 : key |
2696 // -- r1 : receiver | 2849 // -- r1 : receiver |
2697 // ----------------------------------- | 2850 // ----------------------------------- |
2851 Label miss; | |
2852 | |
2853 __ IncrementCounter(&Counters::keyed_load_function_prototype, 1, r2, r3); | |
2854 | |
2855 // Check the name hasn't changed. | |
2856 __ cmp(r0, Operand(Handle<String>(name))); | |
2857 __ b(ne, &miss); | |
2858 | |
2859 GenerateLoadFunctionPrototype(masm(), r1, r2, r3, &miss); | |
2860 __ bind(&miss); | |
2861 __ DecrementCounter(&Counters::keyed_load_function_prototype, 1, r2, r3); | |
2698 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 2862 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
2699 | 2863 |
2700 return GetCode(CALLBACKS, name); | 2864 return GetCode(CALLBACKS, name); |
2701 } | 2865 } |
2702 | 2866 |
2703 | 2867 |
2704 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, | 2868 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, |
2705 int index, | 2869 int index, |
2706 Map* transition, | 2870 Map* transition, |
2707 String* name) { | 2871 String* name) { |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2880 // Return the generated code. | 3044 // Return the generated code. |
2881 return GetCode(); | 3045 return GetCode(); |
2882 } | 3046 } |
2883 | 3047 |
2884 | 3048 |
2885 #undef __ | 3049 #undef __ |
2886 | 3050 |
2887 } } // namespace v8::internal | 3051 } } // namespace v8::internal |
2888 | 3052 |
2889 #endif // V8_TARGET_ARCH_ARM | 3053 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |