Chromium Code Reviews| 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 |