| 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 |