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 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 // Check that receiver is a JSObject. | 132 // Check that receiver is a JSObject. |
133 __ CmpInstanceType(r0, FIRST_JS_OBJECT_TYPE); | 133 __ CmpInstanceType(r0, FIRST_JS_OBJECT_TYPE); |
134 __ j(below, miss_label, not_taken); | 134 __ j(below, miss_label, not_taken); |
135 | 135 |
136 // Load properties array. | 136 // Load properties array. |
137 Register properties = r0; | 137 Register properties = r0; |
138 __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); | 138 __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
139 | 139 |
140 // Check that the properties array is a dictionary. | 140 // Check that the properties array is a dictionary. |
141 __ cmp(FieldOperand(properties, HeapObject::kMapOffset), | 141 __ cmp(FieldOperand(properties, HeapObject::kMapOffset), |
142 Immediate(FACTORY->hash_table_map())); | 142 Immediate(masm->isolate()->factory()->hash_table_map())); |
143 __ j(not_equal, miss_label); | 143 __ j(not_equal, miss_label); |
144 | 144 |
145 // Compute the capacity mask. | 145 // Compute the capacity mask. |
146 const int kCapacityOffset = | 146 const int kCapacityOffset = |
147 StringDictionary::kHeaderSize + | 147 StringDictionary::kHeaderSize + |
148 StringDictionary::kCapacityIndex * kPointerSize; | 148 StringDictionary::kCapacityIndex * kPointerSize; |
149 | 149 |
150 // Generate an unrolled loop that performs a few probes before | 150 // Generate an unrolled loop that performs a few probes before |
151 // giving up. | 151 // giving up. |
152 static const int kProbes = 4; | 152 static const int kProbes = 4; |
(...skipping 19 matching lines...) Expand all Loading... |
172 | 172 |
173 // Scale the index by multiplying by the entry size. | 173 // Scale the index by multiplying by the entry size. |
174 ASSERT(StringDictionary::kEntrySize == 3); | 174 ASSERT(StringDictionary::kEntrySize == 3); |
175 __ lea(index, Operand(index, index, times_2, 0)); // index *= 3. | 175 __ lea(index, Operand(index, index, times_2, 0)); // index *= 3. |
176 | 176 |
177 Register entity_name = r1; | 177 Register entity_name = r1; |
178 // Having undefined at this place means the name is not contained. | 178 // Having undefined at this place means the name is not contained. |
179 ASSERT_EQ(kSmiTagSize, 1); | 179 ASSERT_EQ(kSmiTagSize, 1); |
180 __ mov(entity_name, Operand(properties, index, times_half_pointer_size, | 180 __ mov(entity_name, Operand(properties, index, times_half_pointer_size, |
181 kElementsStartOffset - kHeapObjectTag)); | 181 kElementsStartOffset - kHeapObjectTag)); |
182 __ cmp(entity_name, FACTORY->undefined_value()); | 182 __ cmp(entity_name, masm->isolate()->factory()->undefined_value()); |
183 if (i != kProbes - 1) { | 183 if (i != kProbes - 1) { |
184 __ j(equal, &done, taken); | 184 __ j(equal, &done, taken); |
185 | 185 |
186 // Stop if found the property. | 186 // Stop if found the property. |
187 __ cmp(entity_name, Handle<String>(name)); | 187 __ cmp(entity_name, Handle<String>(name)); |
188 __ j(equal, miss_label, not_taken); | 188 __ j(equal, miss_label, not_taken); |
189 | 189 |
190 // Check if the entry name is not a symbol. | 190 // Check if the entry name is not a symbol. |
191 __ mov(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset)); | 191 __ mov(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset)); |
192 __ test_b(FieldOperand(entity_name, Map::kInstanceTypeOffset), | 192 __ test_b(FieldOperand(entity_name, Map::kInstanceTypeOffset), |
(...skipping 660 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
853 Label* miss) { | 853 Label* miss) { |
854 Object* probe; | 854 Object* probe; |
855 { MaybeObject* maybe_probe = global->EnsurePropertyCell(name); | 855 { MaybeObject* maybe_probe = global->EnsurePropertyCell(name); |
856 if (!maybe_probe->ToObject(&probe)) return maybe_probe; | 856 if (!maybe_probe->ToObject(&probe)) return maybe_probe; |
857 } | 857 } |
858 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); | 858 JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); |
859 ASSERT(cell->value()->IsTheHole()); | 859 ASSERT(cell->value()->IsTheHole()); |
860 if (Serializer::enabled()) { | 860 if (Serializer::enabled()) { |
861 __ mov(scratch, Immediate(Handle<Object>(cell))); | 861 __ mov(scratch, Immediate(Handle<Object>(cell))); |
862 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), | 862 __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), |
863 Immediate(FACTORY->the_hole_value())); | 863 Immediate(masm->isolate()->factory()->the_hole_value())); |
864 } else { | 864 } else { |
865 __ cmp(Operand::Cell(Handle<JSGlobalPropertyCell>(cell)), | 865 __ cmp(Operand::Cell(Handle<JSGlobalPropertyCell>(cell)), |
866 Immediate(FACTORY->the_hole_value())); | 866 Immediate(masm->isolate()->factory()->the_hole_value())); |
867 } | 867 } |
868 __ j(not_equal, miss, not_taken); | 868 __ j(not_equal, miss, not_taken); |
869 return cell; | 869 return cell; |
870 } | 870 } |
871 | 871 |
872 | 872 |
873 // Calls GenerateCheckPropertyCell for each global object in the prototype chain | 873 // Calls GenerateCheckPropertyCell for each global object in the prototype chain |
874 // from object to (but not including) holder. | 874 // from object to (but not including) holder. |
875 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCells( | 875 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCells( |
876 MacroAssembler* masm, | 876 MacroAssembler* masm, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
909 Register scratch1, | 909 Register scratch1, |
910 Register scratch2, | 910 Register scratch2, |
911 String* name, | 911 String* name, |
912 int save_at_depth, | 912 int save_at_depth, |
913 Label* miss) { | 913 Label* miss) { |
914 // Make sure there's no overlap between holder and object registers. | 914 // Make sure there's no overlap between holder and object registers. |
915 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 915 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
916 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 916 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
917 && !scratch2.is(scratch1)); | 917 && !scratch2.is(scratch1)); |
918 | 918 |
919 Heap* heap = isolate()->heap(); | |
920 | |
921 // Keep track of the current object in register reg. | 919 // Keep track of the current object in register reg. |
922 Register reg = object_reg; | 920 Register reg = object_reg; |
923 JSObject* current = object; | 921 JSObject* current = object; |
924 int depth = 0; | 922 int depth = 0; |
925 | 923 |
926 if (save_at_depth == depth) { | 924 if (save_at_depth == depth) { |
927 __ mov(Operand(esp, kPointerSize), reg); | 925 __ mov(Operand(esp, kPointerSize), reg); |
928 } | 926 } |
929 | 927 |
930 // Traverse the prototype chain and check the maps in the prototype chain for | 928 // Traverse the prototype chain and check the maps in the prototype chain for |
931 // fast and global objects or do negative lookup for normal objects. | 929 // fast and global objects or do negative lookup for normal objects. |
932 while (current != holder) { | 930 while (current != holder) { |
933 depth++; | 931 depth++; |
934 | 932 |
935 // Only global objects and objects that do not require access | 933 // Only global objects and objects that do not require access |
936 // checks are allowed in stubs. | 934 // checks are allowed in stubs. |
937 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); | 935 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); |
938 | 936 |
939 ASSERT(current->GetPrototype()->IsJSObject()); | 937 ASSERT(current->GetPrototype()->IsJSObject()); |
940 JSObject* prototype = JSObject::cast(current->GetPrototype()); | 938 JSObject* prototype = JSObject::cast(current->GetPrototype()); |
941 if (!current->HasFastProperties() && | 939 if (!current->HasFastProperties() && |
942 !current->IsJSGlobalObject() && | 940 !current->IsJSGlobalObject() && |
943 !current->IsJSGlobalProxy()) { | 941 !current->IsJSGlobalProxy()) { |
944 if (!name->IsSymbol()) { | 942 if (!name->IsSymbol()) { |
945 MaybeObject* maybe_lookup_result = heap->LookupSymbol(name); | 943 MaybeObject* maybe_lookup_result = heap()->LookupSymbol(name); |
946 Object* lookup_result = NULL; // Initialization to please compiler. | 944 Object* lookup_result = NULL; // Initialization to please compiler. |
947 if (!maybe_lookup_result->ToObject(&lookup_result)) { | 945 if (!maybe_lookup_result->ToObject(&lookup_result)) { |
948 set_failure(Failure::cast(maybe_lookup_result)); | 946 set_failure(Failure::cast(maybe_lookup_result)); |
949 return reg; | 947 return reg; |
950 } | 948 } |
951 name = String::cast(lookup_result); | 949 name = String::cast(lookup_result); |
952 } | 950 } |
953 ASSERT(current->property_dictionary()->FindEntry(name) == | 951 ASSERT(current->property_dictionary()->FindEntry(name) == |
954 StringDictionary::kNotFound); | 952 StringDictionary::kNotFound); |
955 | 953 |
956 GenerateDictionaryNegativeLookup(masm(), | 954 GenerateDictionaryNegativeLookup(masm(), |
957 miss, | 955 miss, |
958 reg, | 956 reg, |
959 name, | 957 name, |
960 scratch1, | 958 scratch1, |
961 scratch2); | 959 scratch2); |
962 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 960 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
963 reg = holder_reg; // from now the object is in holder_reg | 961 reg = holder_reg; // from now the object is in holder_reg |
964 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 962 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
965 } else if (heap->InNewSpace(prototype)) { | 963 } else if (heap()->InNewSpace(prototype)) { |
966 // Get the map of the current object. | 964 // Get the map of the current object. |
967 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 965 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
968 __ cmp(Operand(scratch1), Immediate(Handle<Map>(current->map()))); | 966 __ cmp(Operand(scratch1), Immediate(Handle<Map>(current->map()))); |
969 // Branch on the result of the map check. | 967 // Branch on the result of the map check. |
970 __ j(not_equal, miss, not_taken); | 968 __ j(not_equal, miss, not_taken); |
971 // Check access rights to the global object. This has to happen | 969 // Check access rights to the global object. This has to happen |
972 // after the map check so that we know that the object is | 970 // after the map check so that we know that the object is |
973 // actually a global object. | 971 // actually a global object. |
974 if (current->IsJSGlobalProxy()) { | 972 if (current->IsJSGlobalProxy()) { |
975 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 973 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1209 // of this method.) | 1207 // of this method.) |
1210 CompileCallLoadPropertyWithInterceptor(masm(), | 1208 CompileCallLoadPropertyWithInterceptor(masm(), |
1211 receiver, | 1209 receiver, |
1212 holder_reg, | 1210 holder_reg, |
1213 name_reg, | 1211 name_reg, |
1214 interceptor_holder); | 1212 interceptor_holder); |
1215 | 1213 |
1216 // Check if interceptor provided a value for property. If it's | 1214 // Check if interceptor provided a value for property. If it's |
1217 // the case, return immediately. | 1215 // the case, return immediately. |
1218 Label interceptor_failed; | 1216 Label interceptor_failed; |
1219 __ cmp(eax, FACTORY->no_interceptor_result_sentinel()); | 1217 __ cmp(eax, factory()->no_interceptor_result_sentinel()); |
1220 __ j(equal, &interceptor_failed); | 1218 __ j(equal, &interceptor_failed); |
1221 __ LeaveInternalFrame(); | 1219 __ LeaveInternalFrame(); |
1222 __ ret(0); | 1220 __ ret(0); |
1223 | 1221 |
1224 __ bind(&interceptor_failed); | 1222 __ bind(&interceptor_failed); |
1225 __ pop(name_reg); | 1223 __ pop(name_reg); |
1226 __ pop(holder_reg); | 1224 __ pop(holder_reg); |
1227 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { | 1225 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { |
1228 __ pop(receiver); | 1226 __ pop(receiver); |
1229 } | 1227 } |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1467 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); | 1465 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); |
1468 __ ret((argc + 1) * kPointerSize); | 1466 __ ret((argc + 1) * kPointerSize); |
1469 } else { | 1467 } else { |
1470 Label call_builtin; | 1468 Label call_builtin; |
1471 | 1469 |
1472 // Get the elements array of the object. | 1470 // Get the elements array of the object. |
1473 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); | 1471 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); |
1474 | 1472 |
1475 // Check that the elements are in fast mode and writable. | 1473 // Check that the elements are in fast mode and writable. |
1476 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), | 1474 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), |
1477 Immediate(FACTORY->fixed_array_map())); | 1475 Immediate(factory()->fixed_array_map())); |
1478 __ j(not_equal, &call_builtin); | 1476 __ j(not_equal, &call_builtin); |
1479 | 1477 |
1480 if (argc == 1) { // Otherwise fall through to call builtin. | 1478 if (argc == 1) { // Otherwise fall through to call builtin. |
1481 Label exit, with_write_barrier, attempt_to_grow_elements; | 1479 Label exit, with_write_barrier, attempt_to_grow_elements; |
1482 | 1480 |
1483 // Get the array's length into eax and calculate new length. | 1481 // Get the array's length into eax and calculate new length. |
1484 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); | 1482 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); |
1485 STATIC_ASSERT(kSmiTagSize == 1); | 1483 STATIC_ASSERT(kSmiTagSize == 1); |
1486 STATIC_ASSERT(kSmiTag == 0); | 1484 STATIC_ASSERT(kSmiTag == 0); |
1487 __ add(Operand(eax), Immediate(Smi::FromInt(argc))); | 1485 __ add(Operand(eax), Immediate(Smi::FromInt(argc))); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1543 | 1541 |
1544 // We fit and could grow elements. | 1542 // We fit and could grow elements. |
1545 __ mov(Operand::StaticVariable(new_space_allocation_top), ecx); | 1543 __ mov(Operand::StaticVariable(new_space_allocation_top), ecx); |
1546 __ mov(ecx, Operand(esp, argc * kPointerSize)); | 1544 __ mov(ecx, Operand(esp, argc * kPointerSize)); |
1547 | 1545 |
1548 // Push the argument... | 1546 // Push the argument... |
1549 __ mov(Operand(edx, 0), ecx); | 1547 __ mov(Operand(edx, 0), ecx); |
1550 // ... and fill the rest with holes. | 1548 // ... and fill the rest with holes. |
1551 for (int i = 1; i < kAllocationDelta; i++) { | 1549 for (int i = 1; i < kAllocationDelta; i++) { |
1552 __ mov(Operand(edx, i * kPointerSize), | 1550 __ mov(Operand(edx, i * kPointerSize), |
1553 Immediate(FACTORY->the_hole_value())); | 1551 Immediate(factory()->the_hole_value())); |
1554 } | 1552 } |
1555 | 1553 |
1556 // Restore receiver to edx as finish sequence assumes it's here. | 1554 // Restore receiver to edx as finish sequence assumes it's here. |
1557 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1555 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1558 | 1556 |
1559 // Increment element's and array's sizes. | 1557 // Increment element's and array's sizes. |
1560 __ add(FieldOperand(ebx, FixedArray::kLengthOffset), | 1558 __ add(FieldOperand(ebx, FixedArray::kLengthOffset), |
1561 Immediate(Smi::FromInt(kAllocationDelta))); | 1559 Immediate(Smi::FromInt(kAllocationDelta))); |
1562 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); | 1560 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); |
1563 | 1561 |
(...skipping 25 matching lines...) Expand all Loading... |
1589 // ----------- S t a t e ------------- | 1587 // ----------- S t a t e ------------- |
1590 // -- ecx : name | 1588 // -- ecx : name |
1591 // -- esp[0] : return address | 1589 // -- esp[0] : return address |
1592 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1590 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1593 // -- ... | 1591 // -- ... |
1594 // -- esp[(argc + 1) * 4] : receiver | 1592 // -- esp[(argc + 1) * 4] : receiver |
1595 // ----------------------------------- | 1593 // ----------------------------------- |
1596 | 1594 |
1597 // If object is not an array, bail out to regular call. | 1595 // If object is not an array, bail out to regular call. |
1598 if (!object->IsJSArray() || cell != NULL) { | 1596 if (!object->IsJSArray() || cell != NULL) { |
1599 return isolate()->heap()->undefined_value(); | 1597 return heap()->undefined_value(); |
1600 } | 1598 } |
1601 | 1599 |
1602 Label miss, return_undefined, call_builtin; | 1600 Label miss, return_undefined, call_builtin; |
1603 | 1601 |
1604 GenerateNameCheck(name, &miss); | 1602 GenerateNameCheck(name, &miss); |
1605 | 1603 |
1606 // Get the receiver from the stack. | 1604 // Get the receiver from the stack. |
1607 const int argc = arguments().immediate(); | 1605 const int argc = arguments().immediate(); |
1608 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1606 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
1609 | 1607 |
1610 // Check that the receiver isn't a smi. | 1608 // Check that the receiver isn't a smi. |
1611 __ test(edx, Immediate(kSmiTagMask)); | 1609 __ test(edx, Immediate(kSmiTagMask)); |
1612 __ j(zero, &miss); | 1610 __ j(zero, &miss); |
1613 CheckPrototypes(JSObject::cast(object), edx, | 1611 CheckPrototypes(JSObject::cast(object), edx, |
1614 holder, ebx, | 1612 holder, ebx, |
1615 eax, edi, name, &miss); | 1613 eax, edi, name, &miss); |
1616 | 1614 |
1617 // Get the elements array of the object. | 1615 // Get the elements array of the object. |
1618 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); | 1616 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); |
1619 | 1617 |
1620 // Check that the elements are in fast mode and writable. | 1618 // Check that the elements are in fast mode and writable. |
1621 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), | 1619 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), |
1622 Immediate(FACTORY->fixed_array_map())); | 1620 Immediate(factory()->fixed_array_map())); |
1623 __ j(not_equal, &call_builtin); | 1621 __ j(not_equal, &call_builtin); |
1624 | 1622 |
1625 // Get the array's length into ecx and calculate new length. | 1623 // Get the array's length into ecx and calculate new length. |
1626 __ mov(ecx, FieldOperand(edx, JSArray::kLengthOffset)); | 1624 __ mov(ecx, FieldOperand(edx, JSArray::kLengthOffset)); |
1627 __ sub(Operand(ecx), Immediate(Smi::FromInt(1))); | 1625 __ sub(Operand(ecx), Immediate(Smi::FromInt(1))); |
1628 __ j(negative, &return_undefined); | 1626 __ j(negative, &return_undefined); |
1629 | 1627 |
1630 // Get the last element. | 1628 // Get the last element. |
1631 STATIC_ASSERT(kSmiTagSize == 1); | 1629 STATIC_ASSERT(kSmiTagSize == 1); |
1632 STATIC_ASSERT(kSmiTag == 0); | 1630 STATIC_ASSERT(kSmiTag == 0); |
1633 __ mov(eax, FieldOperand(ebx, | 1631 __ mov(eax, FieldOperand(ebx, |
1634 ecx, times_half_pointer_size, | 1632 ecx, times_half_pointer_size, |
1635 FixedArray::kHeaderSize)); | 1633 FixedArray::kHeaderSize)); |
1636 __ cmp(Operand(eax), Immediate(FACTORY->the_hole_value())); | 1634 __ cmp(Operand(eax), Immediate(factory()->the_hole_value())); |
1637 __ j(equal, &call_builtin); | 1635 __ j(equal, &call_builtin); |
1638 | 1636 |
1639 // Set the array's length. | 1637 // Set the array's length. |
1640 __ mov(FieldOperand(edx, JSArray::kLengthOffset), ecx); | 1638 __ mov(FieldOperand(edx, JSArray::kLengthOffset), ecx); |
1641 | 1639 |
1642 // Fill with the hole. | 1640 // Fill with the hole. |
1643 __ mov(FieldOperand(ebx, | 1641 __ mov(FieldOperand(ebx, |
1644 ecx, times_half_pointer_size, | 1642 ecx, times_half_pointer_size, |
1645 FixedArray::kHeaderSize), | 1643 FixedArray::kHeaderSize), |
1646 Immediate(FACTORY->the_hole_value())); | 1644 Immediate(factory()->the_hole_value())); |
1647 __ ret((argc + 1) * kPointerSize); | 1645 __ ret((argc + 1) * kPointerSize); |
1648 | 1646 |
1649 __ bind(&return_undefined); | 1647 __ bind(&return_undefined); |
1650 __ mov(eax, Immediate(FACTORY->undefined_value())); | 1648 __ mov(eax, Immediate(factory()->undefined_value())); |
1651 __ ret((argc + 1) * kPointerSize); | 1649 __ ret((argc + 1) * kPointerSize); |
1652 | 1650 |
1653 __ bind(&call_builtin); | 1651 __ bind(&call_builtin); |
1654 __ TailCallExternalReference( | 1652 __ TailCallExternalReference( |
1655 ExternalReference(Builtins::c_ArrayPop, isolate()), | 1653 ExternalReference(Builtins::c_ArrayPop, isolate()), |
1656 argc + 1, | 1654 argc + 1, |
1657 1); | 1655 1); |
1658 | 1656 |
1659 __ bind(&miss); | 1657 __ bind(&miss); |
1660 MaybeObject* maybe_result = GenerateMissBranch(); | 1658 MaybeObject* maybe_result = GenerateMissBranch(); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1707 ebx, edx, edi, name, &miss); | 1705 ebx, edx, edi, name, &miss); |
1708 | 1706 |
1709 Register receiver = ebx; | 1707 Register receiver = ebx; |
1710 Register index = edi; | 1708 Register index = edi; |
1711 Register scratch = edx; | 1709 Register scratch = edx; |
1712 Register result = eax; | 1710 Register result = eax; |
1713 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); | 1711 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); |
1714 if (argc > 0) { | 1712 if (argc > 0) { |
1715 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); | 1713 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); |
1716 } else { | 1714 } else { |
1717 __ Set(index, Immediate(FACTORY->undefined_value())); | 1715 __ Set(index, Immediate(factory()->undefined_value())); |
1718 } | 1716 } |
1719 | 1717 |
1720 StringCharCodeAtGenerator char_code_at_generator(receiver, | 1718 StringCharCodeAtGenerator char_code_at_generator(receiver, |
1721 index, | 1719 index, |
1722 scratch, | 1720 scratch, |
1723 result, | 1721 result, |
1724 &miss, // When not a string. | 1722 &miss, // When not a string. |
1725 &miss, // When not a number. | 1723 &miss, // When not a number. |
1726 index_out_of_range_label, | 1724 index_out_of_range_label, |
1727 STRING_INDEX_IS_NUMBER); | 1725 STRING_INDEX_IS_NUMBER); |
1728 char_code_at_generator.GenerateFast(masm()); | 1726 char_code_at_generator.GenerateFast(masm()); |
1729 __ ret((argc + 1) * kPointerSize); | 1727 __ ret((argc + 1) * kPointerSize); |
1730 | 1728 |
1731 StubRuntimeCallHelper call_helper; | 1729 StubRuntimeCallHelper call_helper; |
1732 char_code_at_generator.GenerateSlow(masm(), call_helper); | 1730 char_code_at_generator.GenerateSlow(masm(), call_helper); |
1733 | 1731 |
1734 if (index_out_of_range.is_linked()) { | 1732 if (index_out_of_range.is_linked()) { |
1735 __ bind(&index_out_of_range); | 1733 __ bind(&index_out_of_range); |
1736 __ Set(eax, Immediate(FACTORY->nan_value())); | 1734 __ Set(eax, Immediate(factory()->nan_value())); |
1737 __ ret((argc + 1) * kPointerSize); | 1735 __ ret((argc + 1) * kPointerSize); |
1738 } | 1736 } |
1739 | 1737 |
1740 __ bind(&miss); | 1738 __ bind(&miss); |
1741 // Restore function name in ecx. | 1739 // Restore function name in ecx. |
1742 __ Set(ecx, Immediate(Handle<String>(name))); | 1740 __ Set(ecx, Immediate(Handle<String>(name))); |
1743 __ bind(&name_miss); | 1741 __ bind(&name_miss); |
1744 MaybeObject* maybe_result = GenerateMissBranch(); | 1742 MaybeObject* maybe_result = GenerateMissBranch(); |
1745 if (maybe_result->IsFailure()) return maybe_result; | 1743 if (maybe_result->IsFailure()) return maybe_result; |
1746 | 1744 |
(...skipping 11 matching lines...) Expand all Loading... |
1758 // ----------- S t a t e ------------- | 1756 // ----------- S t a t e ------------- |
1759 // -- ecx : function name | 1757 // -- ecx : function name |
1760 // -- esp[0] : return address | 1758 // -- esp[0] : return address |
1761 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1759 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
1762 // -- ... | 1760 // -- ... |
1763 // -- esp[(argc + 1) * 4] : receiver | 1761 // -- esp[(argc + 1) * 4] : receiver |
1764 // ----------------------------------- | 1762 // ----------------------------------- |
1765 | 1763 |
1766 // If object is not a string, bail out to regular call. | 1764 // If object is not a string, bail out to regular call. |
1767 if (!object->IsString() || cell != NULL) { | 1765 if (!object->IsString() || cell != NULL) { |
1768 return isolate()->heap()->undefined_value(); | 1766 return heap()->undefined_value(); |
1769 } | 1767 } |
1770 | 1768 |
1771 const int argc = arguments().immediate(); | 1769 const int argc = arguments().immediate(); |
1772 | 1770 |
1773 Label miss; | 1771 Label miss; |
1774 Label name_miss; | 1772 Label name_miss; |
1775 Label index_out_of_range; | 1773 Label index_out_of_range; |
1776 Label* index_out_of_range_label = &index_out_of_range; | 1774 Label* index_out_of_range_label = &index_out_of_range; |
1777 | 1775 |
1778 if (kind_ == Code::CALL_IC && extra_ic_state_ == DEFAULT_STRING_STUB) { | 1776 if (kind_ == Code::CALL_IC && extra_ic_state_ == DEFAULT_STRING_STUB) { |
(...skipping 13 matching lines...) Expand all Loading... |
1792 | 1790 |
1793 Register receiver = eax; | 1791 Register receiver = eax; |
1794 Register index = edi; | 1792 Register index = edi; |
1795 Register scratch1 = ebx; | 1793 Register scratch1 = ebx; |
1796 Register scratch2 = edx; | 1794 Register scratch2 = edx; |
1797 Register result = eax; | 1795 Register result = eax; |
1798 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); | 1796 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); |
1799 if (argc > 0) { | 1797 if (argc > 0) { |
1800 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); | 1798 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); |
1801 } else { | 1799 } else { |
1802 __ Set(index, Immediate(FACTORY->undefined_value())); | 1800 __ Set(index, Immediate(factory()->undefined_value())); |
1803 } | 1801 } |
1804 | 1802 |
1805 StringCharAtGenerator char_at_generator(receiver, | 1803 StringCharAtGenerator char_at_generator(receiver, |
1806 index, | 1804 index, |
1807 scratch1, | 1805 scratch1, |
1808 scratch2, | 1806 scratch2, |
1809 result, | 1807 result, |
1810 &miss, // When not a string. | 1808 &miss, // When not a string. |
1811 &miss, // When not a number. | 1809 &miss, // When not a number. |
1812 index_out_of_range_label, | 1810 index_out_of_range_label, |
1813 STRING_INDEX_IS_NUMBER); | 1811 STRING_INDEX_IS_NUMBER); |
1814 char_at_generator.GenerateFast(masm()); | 1812 char_at_generator.GenerateFast(masm()); |
1815 __ ret((argc + 1) * kPointerSize); | 1813 __ ret((argc + 1) * kPointerSize); |
1816 | 1814 |
1817 StubRuntimeCallHelper call_helper; | 1815 StubRuntimeCallHelper call_helper; |
1818 char_at_generator.GenerateSlow(masm(), call_helper); | 1816 char_at_generator.GenerateSlow(masm(), call_helper); |
1819 | 1817 |
1820 if (index_out_of_range.is_linked()) { | 1818 if (index_out_of_range.is_linked()) { |
1821 __ bind(&index_out_of_range); | 1819 __ bind(&index_out_of_range); |
1822 __ Set(eax, Immediate(FACTORY->empty_string())); | 1820 __ Set(eax, Immediate(factory()->empty_string())); |
1823 __ ret((argc + 1) * kPointerSize); | 1821 __ ret((argc + 1) * kPointerSize); |
1824 } | 1822 } |
1825 | 1823 |
1826 __ bind(&miss); | 1824 __ bind(&miss); |
1827 // Restore function name in ecx. | 1825 // Restore function name in ecx. |
1828 __ Set(ecx, Immediate(Handle<String>(name))); | 1826 __ Set(ecx, Immediate(Handle<String>(name))); |
1829 __ bind(&name_miss); | 1827 __ bind(&name_miss); |
1830 MaybeObject* maybe_result = GenerateMissBranch(); | 1828 MaybeObject* maybe_result = GenerateMissBranch(); |
1831 if (maybe_result->IsFailure()) return maybe_result; | 1829 if (maybe_result->IsFailure()) return maybe_result; |
1832 | 1830 |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1959 __ mov(eax, Operand(esp, 1 * kPointerSize)); | 1957 __ mov(eax, Operand(esp, 1 * kPointerSize)); |
1960 | 1958 |
1961 // Check if the argument is a smi. | 1959 // Check if the argument is a smi. |
1962 Label smi; | 1960 Label smi; |
1963 STATIC_ASSERT(kSmiTag == 0); | 1961 STATIC_ASSERT(kSmiTag == 0); |
1964 __ test(eax, Immediate(kSmiTagMask)); | 1962 __ test(eax, Immediate(kSmiTagMask)); |
1965 __ j(zero, &smi); | 1963 __ j(zero, &smi); |
1966 | 1964 |
1967 // Check if the argument is a heap number and load its value into xmm0. | 1965 // Check if the argument is a heap number and load its value into xmm0. |
1968 Label slow; | 1966 Label slow; |
1969 __ CheckMap(eax, FACTORY->heap_number_map(), &slow, true); | 1967 __ CheckMap(eax, factory()->heap_number_map(), &slow, true); |
1970 __ movdbl(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); | 1968 __ movdbl(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); |
1971 | 1969 |
1972 // Check if the argument is strictly positive. Note this also | 1970 // Check if the argument is strictly positive. Note this also |
1973 // discards NaN. | 1971 // discards NaN. |
1974 __ xorpd(xmm1, xmm1); | 1972 __ xorpd(xmm1, xmm1); |
1975 __ ucomisd(xmm0, xmm1); | 1973 __ ucomisd(xmm0, xmm1); |
1976 __ j(below_equal, &slow); | 1974 __ j(below_equal, &slow); |
1977 | 1975 |
1978 // Do a truncating conversion. | 1976 // Do a truncating conversion. |
1979 __ cvttsd2si(eax, Operand(xmm0)); | 1977 __ cvttsd2si(eax, Operand(xmm0)); |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2103 // This only happens for the most negative smi. | 2101 // This only happens for the most negative smi. |
2104 Label slow; | 2102 Label slow; |
2105 __ j(negative, &slow); | 2103 __ j(negative, &slow); |
2106 | 2104 |
2107 // Smi case done. | 2105 // Smi case done. |
2108 __ ret(2 * kPointerSize); | 2106 __ ret(2 * kPointerSize); |
2109 | 2107 |
2110 // Check if the argument is a heap number and load its exponent and | 2108 // Check if the argument is a heap number and load its exponent and |
2111 // sign into ebx. | 2109 // sign into ebx. |
2112 __ bind(¬_smi); | 2110 __ bind(¬_smi); |
2113 __ CheckMap(eax, FACTORY->heap_number_map(), &slow, true); | 2111 __ CheckMap(eax, factory()->heap_number_map(), &slow, true); |
2114 __ mov(ebx, FieldOperand(eax, HeapNumber::kExponentOffset)); | 2112 __ mov(ebx, FieldOperand(eax, HeapNumber::kExponentOffset)); |
2115 | 2113 |
2116 // Check the sign of the argument. If the argument is positive, | 2114 // Check the sign of the argument. If the argument is positive, |
2117 // just return it. | 2115 // just return it. |
2118 Label negative_sign; | 2116 Label negative_sign; |
2119 __ test(ebx, Immediate(HeapNumber::kSignMask)); | 2117 __ test(ebx, Immediate(HeapNumber::kSignMask)); |
2120 __ j(not_zero, &negative_sign); | 2118 __ j(not_zero, &negative_sign); |
2121 __ ret(2 * kPointerSize); | 2119 __ ret(2 * kPointerSize); |
2122 | 2120 |
2123 // If the argument is negative, clear the sign, and return a new | 2121 // If the argument is negative, clear the sign, and return a new |
(...skipping 24 matching lines...) Expand all Loading... |
2148 MaybeObject* CallStubCompiler::CompileFastApiCall( | 2146 MaybeObject* CallStubCompiler::CompileFastApiCall( |
2149 const CallOptimization& optimization, | 2147 const CallOptimization& optimization, |
2150 Object* object, | 2148 Object* object, |
2151 JSObject* holder, | 2149 JSObject* holder, |
2152 JSGlobalPropertyCell* cell, | 2150 JSGlobalPropertyCell* cell, |
2153 JSFunction* function, | 2151 JSFunction* function, |
2154 String* name) { | 2152 String* name) { |
2155 ASSERT(optimization.is_simple_api_call()); | 2153 ASSERT(optimization.is_simple_api_call()); |
2156 // Bail out if object is a global object as we don't want to | 2154 // Bail out if object is a global object as we don't want to |
2157 // repatch it to global receiver. | 2155 // repatch it to global receiver. |
2158 Heap* heap = isolate()->heap(); | 2156 if (object->IsGlobalObject()) return heap()->undefined_value(); |
2159 if (object->IsGlobalObject()) return heap->undefined_value(); | 2157 if (cell != NULL) return heap()->undefined_value(); |
2160 if (cell != NULL) return heap->undefined_value(); | |
2161 int depth = optimization.GetPrototypeDepthOfExpectedType( | 2158 int depth = optimization.GetPrototypeDepthOfExpectedType( |
2162 JSObject::cast(object), holder); | 2159 JSObject::cast(object), holder); |
2163 if (depth == kInvalidProtoDepth) return heap->undefined_value(); | 2160 if (depth == kInvalidProtoDepth) return heap()->undefined_value(); |
2164 | 2161 |
2165 Label miss, miss_before_stack_reserved; | 2162 Label miss, miss_before_stack_reserved; |
2166 | 2163 |
2167 GenerateNameCheck(name, &miss_before_stack_reserved); | 2164 GenerateNameCheck(name, &miss_before_stack_reserved); |
2168 | 2165 |
2169 // Get the receiver from the stack. | 2166 // Get the receiver from the stack. |
2170 const int argc = arguments().immediate(); | 2167 const int argc = arguments().immediate(); |
2171 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2168 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
2172 | 2169 |
2173 // Check that the receiver isn't a smi. | 2170 // Check that the receiver isn't a smi. |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2304 } | 2301 } |
2305 | 2302 |
2306 case BOOLEAN_CHECK: { | 2303 case BOOLEAN_CHECK: { |
2307 if (!function->IsBuiltin() && !function_info->strict_mode()) { | 2304 if (!function->IsBuiltin() && !function_info->strict_mode()) { |
2308 // Calling non-strict non-builtins with a value as the receiver | 2305 // Calling non-strict non-builtins with a value as the receiver |
2309 // requires boxing. | 2306 // requires boxing. |
2310 __ jmp(&miss); | 2307 __ jmp(&miss); |
2311 } else { | 2308 } else { |
2312 Label fast; | 2309 Label fast; |
2313 // Check that the object is a boolean. | 2310 // Check that the object is a boolean. |
2314 __ cmp(edx, FACTORY->true_value()); | 2311 __ cmp(edx, factory()->true_value()); |
2315 __ j(equal, &fast, taken); | 2312 __ j(equal, &fast, taken); |
2316 __ cmp(edx, FACTORY->false_value()); | 2313 __ cmp(edx, factory()->false_value()); |
2317 __ j(not_equal, &miss, not_taken); | 2314 __ j(not_equal, &miss, not_taken); |
2318 __ bind(&fast); | 2315 __ bind(&fast); |
2319 // Check that the maps starting from the prototype haven't changed. | 2316 // Check that the maps starting from the prototype haven't changed. |
2320 GenerateDirectLoadGlobalFunctionPrototype( | 2317 GenerateDirectLoadGlobalFunctionPrototype( |
2321 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss); | 2318 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss); |
2322 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, | 2319 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, |
2323 ebx, edx, edi, name, &miss); | 2320 ebx, edx, edi, name, &miss); |
2324 } | 2321 } |
2325 break; | 2322 break; |
2326 } | 2323 } |
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2630 Operand cell_operand = Operand::Cell(Handle<JSGlobalPropertyCell>(cell)); | 2627 Operand cell_operand = Operand::Cell(Handle<JSGlobalPropertyCell>(cell)); |
2631 if (Serializer::enabled()) { | 2628 if (Serializer::enabled()) { |
2632 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); | 2629 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); |
2633 cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset); | 2630 cell_operand = FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset); |
2634 } | 2631 } |
2635 | 2632 |
2636 // Check that the value in the cell is not the hole. If it is, this | 2633 // Check that the value in the cell is not the hole. If it is, this |
2637 // cell could have been deleted and reintroducing the global needs | 2634 // cell could have been deleted and reintroducing the global needs |
2638 // to update the property details in the property dictionary of the | 2635 // to update the property details in the property dictionary of the |
2639 // global object. We bail out to the runtime system to do that. | 2636 // global object. We bail out to the runtime system to do that. |
2640 __ cmp(cell_operand, FACTORY->the_hole_value()); | 2637 __ cmp(cell_operand, factory()->the_hole_value()); |
2641 __ j(equal, &miss); | 2638 __ j(equal, &miss); |
2642 | 2639 |
2643 // Store the value in the cell. | 2640 // Store the value in the cell. |
2644 __ mov(cell_operand, eax); | 2641 __ mov(cell_operand, eax); |
2645 | 2642 |
2646 // Return the value (register eax). | 2643 // Return the value (register eax). |
2647 Counters* counters = isolate()->counters(); | 2644 Counters* counters = isolate()->counters(); |
2648 __ IncrementCounter(counters->named_store_global_inline(), 1); | 2645 __ IncrementCounter(counters->named_store_global_inline(), 1); |
2649 __ ret(0); | 2646 __ ret(0); |
2650 | 2647 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2716 Immediate(Handle<Map>(receiver->map()))); | 2713 Immediate(Handle<Map>(receiver->map()))); |
2717 __ j(not_equal, &miss, not_taken); | 2714 __ j(not_equal, &miss, not_taken); |
2718 | 2715 |
2719 // Check that the key is a smi. | 2716 // Check that the key is a smi. |
2720 __ test(ecx, Immediate(kSmiTagMask)); | 2717 __ test(ecx, Immediate(kSmiTagMask)); |
2721 __ j(not_zero, &miss, not_taken); | 2718 __ j(not_zero, &miss, not_taken); |
2722 | 2719 |
2723 // Get the elements array and make sure it is a fast element array, not 'cow'. | 2720 // Get the elements array and make sure it is a fast element array, not 'cow'. |
2724 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | 2721 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
2725 __ cmp(FieldOperand(edi, HeapObject::kMapOffset), | 2722 __ cmp(FieldOperand(edi, HeapObject::kMapOffset), |
2726 Immediate(FACTORY->fixed_array_map())); | 2723 Immediate(factory()->fixed_array_map())); |
2727 __ j(not_equal, &miss, not_taken); | 2724 __ j(not_equal, &miss, not_taken); |
2728 | 2725 |
2729 // Check that the key is within bounds. | 2726 // Check that the key is within bounds. |
2730 if (receiver->IsJSArray()) { | 2727 if (receiver->IsJSArray()) { |
2731 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. | 2728 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. |
2732 __ j(above_equal, &miss, not_taken); | 2729 __ j(above_equal, &miss, not_taken); |
2733 } else { | 2730 } else { |
2734 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // Compare smis. | 2731 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // Compare smis. |
2735 __ j(above_equal, &miss, not_taken); | 2732 __ j(above_equal, &miss, not_taken); |
2736 } | 2733 } |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2928 // Get the value from the cell. | 2925 // Get the value from the cell. |
2929 if (Serializer::enabled()) { | 2926 if (Serializer::enabled()) { |
2930 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); | 2927 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); |
2931 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); | 2928 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); |
2932 } else { | 2929 } else { |
2933 __ mov(ebx, Operand::Cell(Handle<JSGlobalPropertyCell>(cell))); | 2930 __ mov(ebx, Operand::Cell(Handle<JSGlobalPropertyCell>(cell))); |
2934 } | 2931 } |
2935 | 2932 |
2936 // Check for deleted property if property can actually be deleted. | 2933 // Check for deleted property if property can actually be deleted. |
2937 if (!is_dont_delete) { | 2934 if (!is_dont_delete) { |
2938 __ cmp(ebx, FACTORY->the_hole_value()); | 2935 __ cmp(ebx, factory()->the_hole_value()); |
2939 __ j(equal, &miss, not_taken); | 2936 __ j(equal, &miss, not_taken); |
2940 } else if (FLAG_debug_code) { | 2937 } else if (FLAG_debug_code) { |
2941 __ cmp(ebx, FACTORY->the_hole_value()); | 2938 __ cmp(ebx, factory()->the_hole_value()); |
2942 __ Check(not_equal, "DontDelete cells can't contain the hole"); | 2939 __ Check(not_equal, "DontDelete cells can't contain the hole"); |
2943 } | 2940 } |
2944 | 2941 |
2945 Counters* counters = isolate()->counters(); | 2942 Counters* counters = isolate()->counters(); |
2946 __ IncrementCounter(counters->named_load_global_stub(), 1); | 2943 __ IncrementCounter(counters->named_load_global_stub(), 1); |
2947 __ mov(eax, ebx); | 2944 __ mov(eax, ebx); |
2948 __ ret(0); | 2945 __ ret(0); |
2949 | 2946 |
2950 __ bind(&miss); | 2947 __ bind(&miss); |
2951 __ IncrementCounter(counters->named_load_global_stub_miss(), 1); | 2948 __ IncrementCounter(counters->named_load_global_stub_miss(), 1); |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3188 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); | 3185 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); |
3189 __ AssertFastElements(ecx); | 3186 __ AssertFastElements(ecx); |
3190 | 3187 |
3191 // Check that the key is within bounds. | 3188 // Check that the key is within bounds. |
3192 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); | 3189 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); |
3193 __ j(above_equal, &miss, not_taken); | 3190 __ j(above_equal, &miss, not_taken); |
3194 | 3191 |
3195 // Load the result and make sure it's not the hole. | 3192 // Load the result and make sure it's not the hole. |
3196 __ mov(ebx, Operand(ecx, eax, times_2, | 3193 __ mov(ebx, Operand(ecx, eax, times_2, |
3197 FixedArray::kHeaderSize - kHeapObjectTag)); | 3194 FixedArray::kHeaderSize - kHeapObjectTag)); |
3198 __ cmp(ebx, FACTORY->the_hole_value()); | 3195 __ cmp(ebx, factory()->the_hole_value()); |
3199 __ j(equal, &miss, not_taken); | 3196 __ j(equal, &miss, not_taken); |
3200 __ mov(eax, ebx); | 3197 __ mov(eax, ebx); |
3201 __ ret(0); | 3198 __ ret(0); |
3202 | 3199 |
3203 __ bind(&miss); | 3200 __ bind(&miss); |
3204 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3201 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3205 | 3202 |
3206 // Return the generated code. | 3203 // Return the generated code. |
3207 return GetCode(NORMAL, NULL); | 3204 return GetCode(NORMAL, NULL); |
3208 } | 3205 } |
3209 | 3206 |
3210 | 3207 |
3211 // Specialized stub for constructing objects from functions which only have only | 3208 // Specialized stub for constructing objects from functions which only have only |
3212 // simple assignments of the form this.x = ...; in their body. | 3209 // simple assignments of the form this.x = ...; in their body. |
3213 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { | 3210 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { |
3214 // ----------- S t a t e ------------- | 3211 // ----------- S t a t e ------------- |
3215 // -- eax : argc | 3212 // -- eax : argc |
3216 // -- edi : constructor | 3213 // -- edi : constructor |
3217 // -- esp[0] : return address | 3214 // -- esp[0] : return address |
3218 // -- esp[4] : last argument | 3215 // -- esp[4] : last argument |
3219 // ----------------------------------- | 3216 // ----------------------------------- |
3220 Label generic_stub_call; | 3217 Label generic_stub_call; |
3221 #ifdef ENABLE_DEBUGGER_SUPPORT | 3218 #ifdef ENABLE_DEBUGGER_SUPPORT |
3222 // Check to see whether there are any break points in the function code. If | 3219 // Check to see whether there are any break points in the function code. If |
3223 // there are jump to the generic constructor stub which calls the actual | 3220 // there are jump to the generic constructor stub which calls the actual |
3224 // code for the function thereby hitting the break points. | 3221 // code for the function thereby hitting the break points. |
3225 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 3222 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
3226 __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kDebugInfoOffset)); | 3223 __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kDebugInfoOffset)); |
3227 __ cmp(ebx, FACTORY->undefined_value()); | 3224 __ cmp(ebx, factory()->undefined_value()); |
3228 __ j(not_equal, &generic_stub_call, not_taken); | 3225 __ j(not_equal, &generic_stub_call, not_taken); |
3229 #endif | 3226 #endif |
3230 | 3227 |
3231 // Load the initial map and verify that it is in fact a map. | 3228 // Load the initial map and verify that it is in fact a map. |
3232 __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); | 3229 __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); |
3233 // Will both indicate a NULL and a Smi. | 3230 // Will both indicate a NULL and a Smi. |
3234 __ test(ebx, Immediate(kSmiTagMask)); | 3231 __ test(ebx, Immediate(kSmiTagMask)); |
3235 __ j(zero, &generic_stub_call); | 3232 __ j(zero, &generic_stub_call); |
3236 __ CmpObjectType(ebx, MAP_TYPE, ecx); | 3233 __ CmpObjectType(ebx, MAP_TYPE, ecx); |
3237 __ j(not_equal, &generic_stub_call); | 3234 __ j(not_equal, &generic_stub_call); |
(...skipping 16 matching lines...) Expand all Loading... |
3254 edx, | 3251 edx, |
3255 ecx, | 3252 ecx, |
3256 no_reg, | 3253 no_reg, |
3257 &generic_stub_call, | 3254 &generic_stub_call, |
3258 NO_ALLOCATION_FLAGS); | 3255 NO_ALLOCATION_FLAGS); |
3259 | 3256 |
3260 // Allocated the JSObject, now initialize the fields and add the heap tag. | 3257 // Allocated the JSObject, now initialize the fields and add the heap tag. |
3261 // ebx: initial map | 3258 // ebx: initial map |
3262 // edx: JSObject (untagged) | 3259 // edx: JSObject (untagged) |
3263 __ mov(Operand(edx, JSObject::kMapOffset), ebx); | 3260 __ mov(Operand(edx, JSObject::kMapOffset), ebx); |
3264 __ mov(ebx, FACTORY->empty_fixed_array()); | 3261 __ mov(ebx, factory()->empty_fixed_array()); |
3265 __ mov(Operand(edx, JSObject::kPropertiesOffset), ebx); | 3262 __ mov(Operand(edx, JSObject::kPropertiesOffset), ebx); |
3266 __ mov(Operand(edx, JSObject::kElementsOffset), ebx); | 3263 __ mov(Operand(edx, JSObject::kElementsOffset), ebx); |
3267 | 3264 |
3268 // Push the allocated object to the stack. This is the object that will be | 3265 // Push the allocated object to the stack. This is the object that will be |
3269 // returned (after it is tagged). | 3266 // returned (after it is tagged). |
3270 __ push(edx); | 3267 __ push(edx); |
3271 | 3268 |
3272 // eax: argc | 3269 // eax: argc |
3273 // edx: JSObject (untagged) | 3270 // edx: JSObject (untagged) |
3274 // Load the address of the first in-object property into edx. | 3271 // Load the address of the first in-object property into edx. |
3275 __ lea(edx, Operand(edx, JSObject::kHeaderSize)); | 3272 __ lea(edx, Operand(edx, JSObject::kHeaderSize)); |
3276 // Calculate the location of the first argument. The stack contains the | 3273 // Calculate the location of the first argument. The stack contains the |
3277 // allocated object and the return address on top of the argc arguments. | 3274 // allocated object and the return address on top of the argc arguments. |
3278 __ lea(ecx, Operand(esp, eax, times_4, 1 * kPointerSize)); | 3275 __ lea(ecx, Operand(esp, eax, times_4, 1 * kPointerSize)); |
3279 | 3276 |
3280 // Use edi for holding undefined which is used in several places below. | 3277 // Use edi for holding undefined which is used in several places below. |
3281 __ mov(edi, FACTORY->undefined_value()); | 3278 __ mov(edi, factory()->undefined_value()); |
3282 | 3279 |
3283 // eax: argc | 3280 // eax: argc |
3284 // ecx: first argument | 3281 // ecx: first argument |
3285 // edx: first in-object property of the JSObject | 3282 // edx: first in-object property of the JSObject |
3286 // edi: undefined | 3283 // edi: undefined |
3287 // Fill the initialized properties with a constant value or a passed argument | 3284 // Fill the initialized properties with a constant value or a passed argument |
3288 // depending on the this.x = ...; assignment in the function. | 3285 // depending on the this.x = ...; assignment in the function. |
3289 SharedFunctionInfo* shared = function->shared(); | 3286 SharedFunctionInfo* shared = function->shared(); |
3290 for (int i = 0; i < shared->this_property_assignments_count(); i++) { | 3287 for (int i = 0; i < shared->this_property_assignments_count(); i++) { |
3291 if (shared->IsThisPropertyAssignmentArgument(i)) { | 3288 if (shared->IsThisPropertyAssignmentArgument(i)) { |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3586 | 3583 |
3587 // TODO(danno): handle heap number -> pixel array conversion | 3584 // TODO(danno): handle heap number -> pixel array conversion |
3588 if (array_type != kExternalPixelArray) { | 3585 if (array_type != kExternalPixelArray) { |
3589 __ bind(&check_heap_number); | 3586 __ bind(&check_heap_number); |
3590 // eax: value | 3587 // eax: value |
3591 // edx: receiver | 3588 // edx: receiver |
3592 // ecx: key | 3589 // ecx: key |
3593 // edi: elements array | 3590 // edi: elements array |
3594 // ebx: untagged index | 3591 // ebx: untagged index |
3595 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | 3592 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), |
3596 Immediate(FACTORY->heap_number_map())); | 3593 Immediate(factory()->heap_number_map())); |
3597 __ j(not_equal, &slow); | 3594 __ j(not_equal, &slow); |
3598 | 3595 |
3599 // The WebGL specification leaves the behavior of storing NaN and | 3596 // The WebGL specification leaves the behavior of storing NaN and |
3600 // +/-Infinity into integer arrays basically undefined. For more | 3597 // +/-Infinity into integer arrays basically undefined. For more |
3601 // reproducible behavior, convert these to zero. | 3598 // reproducible behavior, convert these to zero. |
3602 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); | 3599 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); |
3603 // ebx: untagged index | 3600 // ebx: untagged index |
3604 // edi: base pointer of external storage | 3601 // edi: base pointer of external storage |
3605 if (array_type == kExternalFloatArray) { | 3602 if (array_type == kExternalFloatArray) { |
3606 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 3603 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3704 | 3701 |
3705 return GetCode(flags); | 3702 return GetCode(flags); |
3706 } | 3703 } |
3707 | 3704 |
3708 | 3705 |
3709 #undef __ | 3706 #undef __ |
3710 | 3707 |
3711 } } // namespace v8::internal | 3708 } } // namespace v8::internal |
3712 | 3709 |
3713 #endif // V8_TARGET_ARCH_IA32 | 3710 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |