| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 639 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 650 if (can_do_fast_api_call) { | 650 if (can_do_fast_api_call) { |
| 651 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1); | 651 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1); |
| 652 ReserveSpaceForFastApiCall(masm, scratch1); | 652 ReserveSpaceForFastApiCall(masm, scratch1); |
| 653 } | 653 } |
| 654 | 654 |
| 655 // Check that the maps from receiver to interceptor's holder | 655 // Check that the maps from receiver to interceptor's holder |
| 656 // haven't changed and thus we can invoke interceptor. | 656 // haven't changed and thus we can invoke interceptor. |
| 657 Label miss_cleanup; | 657 Label miss_cleanup; |
| 658 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; | 658 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; |
| 659 Register holder = | 659 Register holder = |
| 660 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, | 660 stub_compiler_->CheckPrototypes( |
| 661 scratch1, scratch2, scratch3, | 661 IC::CurrentTypeOf(object, masm->isolate()), receiver, |
| 662 name, depth1, miss); | 662 interceptor_holder, scratch1, scratch2, scratch3, |
| 663 name, depth1, miss); |
| 663 | 664 |
| 664 // Invoke an interceptor and if it provides a value, | 665 // Invoke an interceptor and if it provides a value, |
| 665 // branch to |regular_invoke|. | 666 // branch to |regular_invoke|. |
| 666 Label regular_invoke; | 667 Label regular_invoke; |
| 667 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, | 668 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, |
| 668 ®ular_invoke); | 669 ®ular_invoke); |
| 669 | 670 |
| 670 // Interceptor returned nothing for this property. Try to use cached | 671 // Interceptor returned nothing for this property. Try to use cached |
| 671 // constant function. | 672 // constant function. |
| 672 | 673 |
| 673 // Check that the maps from interceptor's holder to constant function's | 674 // Check that the maps from interceptor's holder to constant function's |
| 674 // holder haven't changed and thus we can use cached constant function. | 675 // holder haven't changed and thus we can use cached constant function. |
| 675 if (*interceptor_holder != lookup->holder()) { | 676 if (*interceptor_holder != lookup->holder()) { |
| 676 stub_compiler_->CheckPrototypes(interceptor_holder, receiver, | 677 stub_compiler_->CheckPrototypes( |
| 677 Handle<JSObject>(lookup->holder()), | 678 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), receiver, |
| 678 scratch1, scratch2, scratch3, | 679 handle(lookup->holder()), scratch1, scratch2, scratch3, |
| 679 name, depth2, miss); | 680 name, depth2, miss); |
| 680 } else { | 681 } else { |
| 681 // CheckPrototypes has a side effect of fetching a 'holder' | 682 // CheckPrototypes has a side effect of fetching a 'holder' |
| 682 // for API (object which is instanceof for the signature). It's | 683 // for API (object which is instanceof for the signature). It's |
| 683 // safe to omit it here, as if present, it should be fetched | 684 // safe to omit it here, as if present, it should be fetched |
| 684 // by the previous CheckPrototypes. | 685 // by the previous CheckPrototypes. |
| 685 ASSERT(depth2 == kInvalidProtoDepth); | 686 ASSERT(depth2 == kInvalidProtoDepth); |
| 686 } | 687 } |
| 687 | 688 |
| 688 // Invoke function. | 689 // Invoke function. |
| 689 if (can_do_fast_api_call) { | 690 if (can_do_fast_api_call) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 715 void CompileRegular(MacroAssembler* masm, | 716 void CompileRegular(MacroAssembler* masm, |
| 716 Handle<JSObject> object, | 717 Handle<JSObject> object, |
| 717 Register receiver, | 718 Register receiver, |
| 718 Register scratch1, | 719 Register scratch1, |
| 719 Register scratch2, | 720 Register scratch2, |
| 720 Register scratch3, | 721 Register scratch3, |
| 721 Handle<Name> name, | 722 Handle<Name> name, |
| 722 Handle<JSObject> interceptor_holder, | 723 Handle<JSObject> interceptor_holder, |
| 723 Label* miss_label) { | 724 Label* miss_label) { |
| 724 Register holder = | 725 Register holder = |
| 725 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, | 726 stub_compiler_->CheckPrototypes( |
| 726 scratch1, scratch2, scratch3, | 727 IC::CurrentTypeOf(object, masm->isolate()), receiver, |
| 727 name, miss_label); | 728 interceptor_holder, scratch1, scratch2, scratch3, name, miss_label); |
| 728 | 729 |
| 729 FrameScope scope(masm, StackFrame::INTERNAL); | 730 FrameScope scope(masm, StackFrame::INTERNAL); |
| 730 // Save the name_ register across the call. | 731 // Save the name_ register across the call. |
| 731 __ push(name_); | 732 __ push(name_); |
| 732 | 733 |
| 733 PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder); | 734 PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder); |
| 734 | 735 |
| 735 __ CallExternalReference( | 736 __ CallExternalReference( |
| 736 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), | 737 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), |
| 737 masm->isolate()), | 738 masm->isolate()), |
| (...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1111 smi_check); | 1112 smi_check); |
| 1112 } | 1113 } |
| 1113 } | 1114 } |
| 1114 | 1115 |
| 1115 // Return the value (register eax). | 1116 // Return the value (register eax). |
| 1116 ASSERT(value_reg.is(eax)); | 1117 ASSERT(value_reg.is(eax)); |
| 1117 __ ret(0); | 1118 __ ret(0); |
| 1118 } | 1119 } |
| 1119 | 1120 |
| 1120 | 1121 |
| 1121 void StubCompiler::GenerateCheckPropertyCells(MacroAssembler* masm, | |
| 1122 Handle<JSObject> object, | |
| 1123 Handle<JSObject> holder, | |
| 1124 Handle<Name> name, | |
| 1125 Register scratch, | |
| 1126 Label* miss) { | |
| 1127 Handle<JSObject> current = object; | |
| 1128 while (!current.is_identical_to(holder)) { | |
| 1129 if (current->IsJSGlobalObject()) { | |
| 1130 GenerateCheckPropertyCell(masm, | |
| 1131 Handle<JSGlobalObject>::cast(current), | |
| 1132 name, | |
| 1133 scratch, | |
| 1134 miss); | |
| 1135 } | |
| 1136 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); | |
| 1137 } | |
| 1138 } | |
| 1139 | |
| 1140 | |
| 1141 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { | 1122 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { |
| 1142 __ jmp(code, RelocInfo::CODE_TARGET); | 1123 __ jmp(code, RelocInfo::CODE_TARGET); |
| 1143 } | 1124 } |
| 1144 | 1125 |
| 1145 | 1126 |
| 1146 #undef __ | 1127 #undef __ |
| 1147 #define __ ACCESS_MASM(masm()) | 1128 #define __ ACCESS_MASM(masm()) |
| 1148 | 1129 |
| 1149 | 1130 |
| 1150 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, | 1131 Register StubCompiler::CheckPrototypes(Handle<Type> type, |
| 1151 Register object_reg, | 1132 Register object_reg, |
| 1152 Handle<JSObject> holder, | 1133 Handle<JSObject> holder, |
| 1153 Register holder_reg, | 1134 Register holder_reg, |
| 1154 Register scratch1, | 1135 Register scratch1, |
| 1155 Register scratch2, | 1136 Register scratch2, |
| 1156 Handle<Name> name, | 1137 Handle<Name> name, |
| 1157 int save_at_depth, | 1138 int save_at_depth, |
| 1158 Label* miss, | 1139 Label* miss, |
| 1159 PrototypeCheckType check) { | 1140 PrototypeCheckType check) { |
| 1160 const int kHolderIndex = FunctionCallbackArguments::kHolderIndex + 1; | 1141 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); |
| 1161 // Make sure that the type feedback oracle harvests the receiver map. | 1142 // Make sure that the type feedback oracle harvests the receiver map. |
| 1162 // TODO(svenpanne) Remove this hack when all ICs are reworked. | 1143 // TODO(svenpanne) Remove this hack when all ICs are reworked. |
| 1163 __ mov(scratch1, Handle<Map>(object->map())); | 1144 __ mov(scratch1, receiver_map); |
| 1164 | 1145 |
| 1165 Handle<JSObject> first = object; | |
| 1166 // Make sure there's no overlap between holder and object registers. | 1146 // Make sure there's no overlap between holder and object registers. |
| 1167 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 1147 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
| 1168 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 1148 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
| 1169 && !scratch2.is(scratch1)); | 1149 && !scratch2.is(scratch1)); |
| 1170 | 1150 |
| 1171 // Keep track of the current object in register reg. | 1151 // Keep track of the current object in register reg. |
| 1172 Register reg = object_reg; | 1152 Register reg = object_reg; |
| 1173 Handle<JSObject> current = object; | |
| 1174 int depth = 0; | 1153 int depth = 0; |
| 1175 | 1154 |
| 1155 const int kHolderIndex = FunctionCallbackArguments::kHolderIndex + 1; |
| 1176 if (save_at_depth == depth) { | 1156 if (save_at_depth == depth) { |
| 1177 __ mov(Operand(esp, kHolderIndex * kPointerSize), reg); | 1157 __ mov(Operand(esp, kHolderIndex * kPointerSize), reg); |
| 1178 } | 1158 } |
| 1179 | 1159 |
| 1160 Handle<JSObject> current = Handle<JSObject>::null(); |
| 1161 if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant()); |
| 1162 Handle<JSObject> prototype = Handle<JSObject>::null(); |
| 1163 Handle<Map> current_map = receiver_map; |
| 1164 Handle<Map> holder_map(holder->map()); |
| 1180 // Traverse the prototype chain and check the maps in the prototype chain for | 1165 // Traverse the prototype chain and check the maps in the prototype chain for |
| 1181 // fast and global objects or do negative lookup for normal objects. | 1166 // fast and global objects or do negative lookup for normal objects. |
| 1182 while (!current.is_identical_to(holder)) { | 1167 while (!current_map.is_identical_to(holder_map)) { |
| 1183 ++depth; | 1168 ++depth; |
| 1184 | 1169 |
| 1185 // Only global objects and objects that do not require access | 1170 // Only global objects and objects that do not require access |
| 1186 // checks are allowed in stubs. | 1171 // checks are allowed in stubs. |
| 1187 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); | 1172 ASSERT(current_map->IsJSGlobalProxyMap() || |
| 1173 !current_map->is_access_check_needed()); |
| 1188 | 1174 |
| 1189 Handle<JSObject> prototype(JSObject::cast(current->GetPrototype())); | 1175 prototype = handle(JSObject::cast(current_map->prototype())); |
| 1190 if (!current->HasFastProperties() && | 1176 if (current_map->is_dictionary_map() && |
| 1191 !current->IsJSGlobalObject() && | 1177 !current_map->IsJSGlobalObjectMap() && |
| 1192 !current->IsJSGlobalProxy()) { | 1178 !current_map->IsJSGlobalProxyMap()) { |
| 1193 if (!name->IsUniqueName()) { | 1179 if (!name->IsUniqueName()) { |
| 1194 ASSERT(name->IsString()); | 1180 ASSERT(name->IsString()); |
| 1195 name = factory()->InternalizeString(Handle<String>::cast(name)); | 1181 name = factory()->InternalizeString(Handle<String>::cast(name)); |
| 1196 } | 1182 } |
| 1197 ASSERT(current->property_dictionary()->FindEntry(*name) == | 1183 ASSERT(current.is_null() || |
| 1184 current->property_dictionary()->FindEntry(*name) == |
| 1198 NameDictionary::kNotFound); | 1185 NameDictionary::kNotFound); |
| 1199 | 1186 |
| 1200 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, | 1187 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, |
| 1201 scratch1, scratch2); | 1188 scratch1, scratch2); |
| 1202 | 1189 |
| 1203 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 1190 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1204 reg = holder_reg; // From now on the object will be in holder_reg. | 1191 reg = holder_reg; // From now on the object will be in holder_reg. |
| 1205 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 1192 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 1206 } else { | 1193 } else { |
| 1207 bool in_new_space = heap()->InNewSpace(*prototype); | 1194 bool in_new_space = heap()->InNewSpace(*prototype); |
| 1208 Handle<Map> current_map(current->map()); | 1195 if (depth != 1 || check == CHECK_ALL_MAPS) { |
| 1209 if (!current.is_identical_to(first) || check == CHECK_ALL_MAPS) { | |
| 1210 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK); | 1196 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK); |
| 1211 } | 1197 } |
| 1212 | 1198 |
| 1213 // Check access rights to the global object. This has to happen after | 1199 // Check access rights to the global object. This has to happen after |
| 1214 // the map check so that we know that the object is actually a global | 1200 // the map check so that we know that the object is actually a global |
| 1215 // object. | 1201 // object. |
| 1216 if (current->IsJSGlobalProxy()) { | 1202 if (current_map->IsJSGlobalProxyMap()) { |
| 1217 __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss); | 1203 __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss); |
| 1204 } else if (current_map->IsJSGlobalObjectMap()) { |
| 1205 GenerateCheckPropertyCell( |
| 1206 masm(), Handle<JSGlobalObject>::cast(current), name, |
| 1207 scratch2, miss); |
| 1218 } | 1208 } |
| 1219 | 1209 |
| 1220 if (in_new_space) { | 1210 if (in_new_space) { |
| 1221 // Save the map in scratch1 for later. | 1211 // Save the map in scratch1 for later. |
| 1222 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 1212 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1223 } | 1213 } |
| 1224 | 1214 |
| 1225 reg = holder_reg; // From now on the object will be in holder_reg. | 1215 reg = holder_reg; // From now on the object will be in holder_reg. |
| 1226 | 1216 |
| 1227 if (in_new_space) { | 1217 if (in_new_space) { |
| 1228 // The prototype is in new space; we cannot store a reference to it | 1218 // The prototype is in new space; we cannot store a reference to it |
| 1229 // in the code. Load it from the map. | 1219 // in the code. Load it from the map. |
| 1230 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 1220 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 1231 } else { | 1221 } else { |
| 1232 // The prototype is in old space; load it directly. | 1222 // The prototype is in old space; load it directly. |
| 1233 __ mov(reg, prototype); | 1223 __ mov(reg, prototype); |
| 1234 } | 1224 } |
| 1235 } | 1225 } |
| 1236 | 1226 |
| 1237 if (save_at_depth == depth) { | 1227 if (save_at_depth == depth) { |
| 1238 __ mov(Operand(esp, kHolderIndex * kPointerSize), reg); | 1228 __ mov(Operand(esp, kHolderIndex * kPointerSize), reg); |
| 1239 } | 1229 } |
| 1240 | 1230 |
| 1241 // Go to the next object in the prototype chain. | 1231 // Go to the next object in the prototype chain. |
| 1242 current = prototype; | 1232 current = prototype; |
| 1233 current_map = handle(current->map()); |
| 1243 } | 1234 } |
| 1244 ASSERT(current.is_identical_to(holder)); | |
| 1245 | 1235 |
| 1246 // Log the check depth. | 1236 // Log the check depth. |
| 1247 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 1237 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
| 1248 | 1238 |
| 1249 if (!holder.is_identical_to(first) || check == CHECK_ALL_MAPS) { | 1239 if (depth != 0 || check == CHECK_ALL_MAPS) { |
| 1250 // Check the holder map. | 1240 // Check the holder map. |
| 1251 __ CheckMap(reg, Handle<Map>(holder->map()), miss, DONT_DO_SMI_CHECK); | 1241 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK); |
| 1252 } | 1242 } |
| 1253 | 1243 |
| 1254 // Perform security check for access to the global object. | 1244 // Perform security check for access to the global object. |
| 1255 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 1245 ASSERT(current_map->IsJSGlobalProxyMap() || |
| 1256 if (holder->IsJSGlobalProxy()) { | 1246 !current_map->is_access_check_needed()); |
| 1247 if (current_map->IsJSGlobalProxyMap()) { |
| 1257 __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss); | 1248 __ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss); |
| 1258 } | 1249 } |
| 1259 | 1250 |
| 1260 // If we've skipped any global objects, it's not enough to verify that | |
| 1261 // their maps haven't changed. We also need to check that the property | |
| 1262 // cell for the property is still empty. | |
| 1263 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); | |
| 1264 | |
| 1265 // Return the register containing the holder. | 1251 // Return the register containing the holder. |
| 1266 return reg; | 1252 return reg; |
| 1267 } | 1253 } |
| 1268 | 1254 |
| 1269 | 1255 |
| 1270 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { | 1256 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { |
| 1271 if (!miss->is_unused()) { | 1257 if (!miss->is_unused()) { |
| 1272 Label success; | 1258 Label success; |
| 1273 __ jmp(&success); | 1259 __ jmp(&success); |
| 1274 __ bind(miss); | 1260 __ bind(miss); |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1564 | 1550 |
| 1565 // Get the number of arguments. | 1551 // Get the number of arguments. |
| 1566 const int argc = arguments().immediate(); | 1552 const int argc = arguments().immediate(); |
| 1567 | 1553 |
| 1568 // Get the receiver from the stack. | 1554 // Get the receiver from the stack. |
| 1569 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1555 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1570 | 1556 |
| 1571 | 1557 |
| 1572 // Check that the maps haven't changed. | 1558 // Check that the maps haven't changed. |
| 1573 __ JumpIfSmi(edx, miss); | 1559 __ JumpIfSmi(edx, miss); |
| 1574 CheckPrototypes(object, edx, holder, ebx, eax, edi, name, miss); | 1560 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, |
| 1561 ebx, eax, edi, name, miss); |
| 1575 } | 1562 } |
| 1576 | 1563 |
| 1577 | 1564 |
| 1578 void CallStubCompiler::GenerateLoadFunctionFromCell( | 1565 void CallStubCompiler::GenerateLoadFunctionFromCell( |
| 1579 Handle<Cell> cell, | 1566 Handle<Cell> cell, |
| 1580 Handle<JSFunction> function, | 1567 Handle<JSFunction> function, |
| 1581 Label* miss) { | 1568 Label* miss) { |
| 1582 // Get the value from the cell. | 1569 // Get the value from the cell. |
| 1583 if (Serializer::enabled()) { | 1570 if (Serializer::enabled()) { |
| 1584 __ mov(edi, Immediate(cell)); | 1571 __ mov(edi, Immediate(cell)); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1633 GenerateNameCheck(name, &miss); | 1620 GenerateNameCheck(name, &miss); |
| 1634 | 1621 |
| 1635 // Get the receiver from the stack. | 1622 // Get the receiver from the stack. |
| 1636 const int argc = arguments().immediate(); | 1623 const int argc = arguments().immediate(); |
| 1637 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1624 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1638 | 1625 |
| 1639 // Check that the receiver isn't a smi. | 1626 // Check that the receiver isn't a smi. |
| 1640 __ JumpIfSmi(edx, &miss); | 1627 __ JumpIfSmi(edx, &miss); |
| 1641 | 1628 |
| 1642 // Do the right check and compute the holder register. | 1629 // Do the right check and compute the holder register. |
| 1643 Register reg = CheckPrototypes(object, edx, holder, ebx, eax, edi, | 1630 Register reg = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, |
| 1644 name, &miss); | 1631 holder, ebx, eax, edi, name, &miss); |
| 1645 | 1632 |
| 1646 GenerateFastPropertyLoad( | 1633 GenerateFastPropertyLoad( |
| 1647 masm(), edi, reg, index.is_inobject(holder), | 1634 masm(), edi, reg, index.is_inobject(holder), |
| 1648 index.translate(holder), Representation::Tagged()); | 1635 index.translate(holder), Representation::Tagged()); |
| 1649 | 1636 |
| 1650 // Check that the function really is a function. | 1637 // Check that the function really is a function. |
| 1651 __ JumpIfSmi(edi, &miss); | 1638 __ JumpIfSmi(edi, &miss); |
| 1652 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); | 1639 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); |
| 1653 __ j(not_equal, &miss); | 1640 __ j(not_equal, &miss); |
| 1654 | 1641 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1687 // Check that function is still array | 1674 // Check that function is still array |
| 1688 const int argc = arguments().immediate(); | 1675 const int argc = arguments().immediate(); |
| 1689 GenerateNameCheck(name, &miss); | 1676 GenerateNameCheck(name, &miss); |
| 1690 | 1677 |
| 1691 if (cell.is_null()) { | 1678 if (cell.is_null()) { |
| 1692 // Get the receiver from the stack. | 1679 // Get the receiver from the stack. |
| 1693 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1680 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1694 | 1681 |
| 1695 // Check that the receiver isn't a smi. | 1682 // Check that the receiver isn't a smi. |
| 1696 __ JumpIfSmi(edx, &miss); | 1683 __ JumpIfSmi(edx, &miss); |
| 1697 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, | 1684 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, |
| 1698 name, &miss); | 1685 ebx, eax, edi, name, &miss); |
| 1699 } else { | 1686 } else { |
| 1700 ASSERT(cell->value() == *function); | 1687 ASSERT(cell->value() == *function); |
| 1701 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 1688 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 1702 &miss); | 1689 &miss); |
| 1703 GenerateLoadFunctionFromCell(cell, function, &miss); | 1690 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 1704 } | 1691 } |
| 1705 | 1692 |
| 1706 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); | 1693 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); |
| 1707 site->SetElementsKind(GetInitialFastElementsKind()); | 1694 site->SetElementsKind(GetInitialFastElementsKind()); |
| 1708 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); | 1695 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1747 | 1734 |
| 1748 GenerateNameCheck(name, &miss); | 1735 GenerateNameCheck(name, &miss); |
| 1749 | 1736 |
| 1750 // Get the receiver from the stack. | 1737 // Get the receiver from the stack. |
| 1751 const int argc = arguments().immediate(); | 1738 const int argc = arguments().immediate(); |
| 1752 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1739 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1753 | 1740 |
| 1754 // Check that the receiver isn't a smi. | 1741 // Check that the receiver isn't a smi. |
| 1755 __ JumpIfSmi(edx, &miss); | 1742 __ JumpIfSmi(edx, &miss); |
| 1756 | 1743 |
| 1757 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, | 1744 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, |
| 1758 name, &miss); | 1745 ebx, eax, edi, name, &miss); |
| 1759 | 1746 |
| 1760 if (argc == 0) { | 1747 if (argc == 0) { |
| 1761 // Noop, return the length. | 1748 // Noop, return the length. |
| 1762 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); | 1749 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); |
| 1763 __ ret((argc + 1) * kPointerSize); | 1750 __ ret((argc + 1) * kPointerSize); |
| 1764 } else { | 1751 } else { |
| 1765 Label call_builtin; | 1752 Label call_builtin; |
| 1766 | 1753 |
| 1767 if (argc == 1) { // Otherwise fall through to call builtin. | 1754 if (argc == 1) { // Otherwise fall through to call builtin. |
| 1768 Label attempt_to_grow_elements, with_write_barrier, check_double; | 1755 Label attempt_to_grow_elements, with_write_barrier, check_double; |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2007 Label miss, return_undefined, call_builtin; | 1994 Label miss, return_undefined, call_builtin; |
| 2008 | 1995 |
| 2009 GenerateNameCheck(name, &miss); | 1996 GenerateNameCheck(name, &miss); |
| 2010 | 1997 |
| 2011 // Get the receiver from the stack. | 1998 // Get the receiver from the stack. |
| 2012 const int argc = arguments().immediate(); | 1999 const int argc = arguments().immediate(); |
| 2013 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 2000 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 2014 | 2001 |
| 2015 // Check that the receiver isn't a smi. | 2002 // Check that the receiver isn't a smi. |
| 2016 __ JumpIfSmi(edx, &miss); | 2003 __ JumpIfSmi(edx, &miss); |
| 2017 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, | 2004 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, |
| 2018 name, &miss); | 2005 ebx, eax, edi, name, &miss); |
| 2019 | 2006 |
| 2020 // Get the elements array of the object. | 2007 // Get the elements array of the object. |
| 2021 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); | 2008 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); |
| 2022 | 2009 |
| 2023 // Check that the elements are in fast mode and writable. | 2010 // Check that the elements are in fast mode and writable. |
| 2024 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), | 2011 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), |
| 2025 Immediate(factory()->fixed_array_map())); | 2012 Immediate(factory()->fixed_array_map())); |
| 2026 __ j(not_equal, &call_builtin); | 2013 __ j(not_equal, &call_builtin); |
| 2027 | 2014 |
| 2028 // Get the array's length into ecx and calculate new length. | 2015 // Get the array's length into ecx and calculate new length. |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2101 } | 2088 } |
| 2102 | 2089 |
| 2103 GenerateNameCheck(name, &name_miss); | 2090 GenerateNameCheck(name, &name_miss); |
| 2104 | 2091 |
| 2105 // Check that the maps starting from the prototype haven't changed. | 2092 // Check that the maps starting from the prototype haven't changed. |
| 2106 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 2093 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 2107 Context::STRING_FUNCTION_INDEX, | 2094 Context::STRING_FUNCTION_INDEX, |
| 2108 eax, | 2095 eax, |
| 2109 &miss); | 2096 &miss); |
| 2110 ASSERT(!object.is_identical_to(holder)); | 2097 ASSERT(!object.is_identical_to(holder)); |
| 2098 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2111 CheckPrototypes( | 2099 CheckPrototypes( |
| 2112 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2100 IC::CurrentTypeOf(prototype, isolate()), |
| 2113 eax, holder, ebx, edx, edi, name, &miss); | 2101 eax, holder, ebx, edx, edi, name, &miss); |
| 2114 | 2102 |
| 2115 Register receiver = ebx; | 2103 Register receiver = ebx; |
| 2116 Register index = edi; | 2104 Register index = edi; |
| 2117 Register result = eax; | 2105 Register result = eax; |
| 2118 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); | 2106 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); |
| 2119 if (argc > 0) { | 2107 if (argc > 0) { |
| 2120 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); | 2108 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); |
| 2121 } else { | 2109 } else { |
| 2122 __ Set(index, Immediate(factory()->undefined_value())); | 2110 __ Set(index, Immediate(factory()->undefined_value())); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2186 } | 2174 } |
| 2187 | 2175 |
| 2188 GenerateNameCheck(name, &name_miss); | 2176 GenerateNameCheck(name, &name_miss); |
| 2189 | 2177 |
| 2190 // Check that the maps starting from the prototype haven't changed. | 2178 // Check that the maps starting from the prototype haven't changed. |
| 2191 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 2179 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 2192 Context::STRING_FUNCTION_INDEX, | 2180 Context::STRING_FUNCTION_INDEX, |
| 2193 eax, | 2181 eax, |
| 2194 &miss); | 2182 &miss); |
| 2195 ASSERT(!object.is_identical_to(holder)); | 2183 ASSERT(!object.is_identical_to(holder)); |
| 2184 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2196 CheckPrototypes( | 2185 CheckPrototypes( |
| 2197 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2186 IC::CurrentTypeOf(prototype, isolate()), |
| 2198 eax, holder, ebx, edx, edi, name, &miss); | 2187 eax, holder, ebx, edx, edi, name, &miss); |
| 2199 | 2188 |
| 2200 Register receiver = eax; | 2189 Register receiver = eax; |
| 2201 Register index = edi; | 2190 Register index = edi; |
| 2202 Register scratch = edx; | 2191 Register scratch = edx; |
| 2203 Register result = eax; | 2192 Register result = eax; |
| 2204 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); | 2193 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); |
| 2205 if (argc > 0) { | 2194 if (argc > 0) { |
| 2206 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); | 2195 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); |
| 2207 } else { | 2196 } else { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2262 return Handle<Code>::null(); | 2251 return Handle<Code>::null(); |
| 2263 } | 2252 } |
| 2264 | 2253 |
| 2265 Label miss; | 2254 Label miss; |
| 2266 GenerateNameCheck(name, &miss); | 2255 GenerateNameCheck(name, &miss); |
| 2267 | 2256 |
| 2268 if (cell.is_null()) { | 2257 if (cell.is_null()) { |
| 2269 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 2258 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
| 2270 STATIC_ASSERT(kSmiTag == 0); | 2259 STATIC_ASSERT(kSmiTag == 0); |
| 2271 __ JumpIfSmi(edx, &miss); | 2260 __ JumpIfSmi(edx, &miss); |
| 2272 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, | 2261 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, |
| 2273 name, &miss); | 2262 ebx, eax, edi, name, &miss); |
| 2274 } else { | 2263 } else { |
| 2275 ASSERT(cell->value() == *function); | 2264 ASSERT(cell->value() == *function); |
| 2276 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 2265 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 2277 &miss); | 2266 &miss); |
| 2278 GenerateLoadFunctionFromCell(cell, function, &miss); | 2267 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2279 } | 2268 } |
| 2280 | 2269 |
| 2281 // Load the char code argument. | 2270 // Load the char code argument. |
| 2282 Register code = ebx; | 2271 Register code = ebx; |
| 2283 __ mov(code, Operand(esp, 1 * kPointerSize)); | 2272 __ mov(code, Operand(esp, 1 * kPointerSize)); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2347 | 2336 |
| 2348 Label miss; | 2337 Label miss; |
| 2349 GenerateNameCheck(name, &miss); | 2338 GenerateNameCheck(name, &miss); |
| 2350 | 2339 |
| 2351 if (cell.is_null()) { | 2340 if (cell.is_null()) { |
| 2352 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 2341 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
| 2353 | 2342 |
| 2354 STATIC_ASSERT(kSmiTag == 0); | 2343 STATIC_ASSERT(kSmiTag == 0); |
| 2355 __ JumpIfSmi(edx, &miss); | 2344 __ JumpIfSmi(edx, &miss); |
| 2356 | 2345 |
| 2357 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, | 2346 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, |
| 2358 name, &miss); | 2347 ebx, eax, edi, name, &miss); |
| 2359 } else { | 2348 } else { |
| 2360 ASSERT(cell->value() == *function); | 2349 ASSERT(cell->value() == *function); |
| 2361 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 2350 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 2362 &miss); | 2351 &miss); |
| 2363 GenerateLoadFunctionFromCell(cell, function, &miss); | 2352 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2364 } | 2353 } |
| 2365 | 2354 |
| 2366 // Load the (only) argument into eax. | 2355 // Load the (only) argument into eax. |
| 2367 __ mov(eax, Operand(esp, 1 * kPointerSize)); | 2356 __ mov(eax, Operand(esp, 1 * kPointerSize)); |
| 2368 | 2357 |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2473 | 2462 |
| 2474 Label miss; | 2463 Label miss; |
| 2475 GenerateNameCheck(name, &miss); | 2464 GenerateNameCheck(name, &miss); |
| 2476 | 2465 |
| 2477 if (cell.is_null()) { | 2466 if (cell.is_null()) { |
| 2478 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 2467 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
| 2479 | 2468 |
| 2480 STATIC_ASSERT(kSmiTag == 0); | 2469 STATIC_ASSERT(kSmiTag == 0); |
| 2481 __ JumpIfSmi(edx, &miss); | 2470 __ JumpIfSmi(edx, &miss); |
| 2482 | 2471 |
| 2483 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, | 2472 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, |
| 2484 name, &miss); | 2473 ebx, eax, edi, name, &miss); |
| 2485 } else { | 2474 } else { |
| 2486 ASSERT(cell->value() == *function); | 2475 ASSERT(cell->value() == *function); |
| 2487 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 2476 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 2488 &miss); | 2477 &miss); |
| 2489 GenerateLoadFunctionFromCell(cell, function, &miss); | 2478 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2490 } | 2479 } |
| 2491 | 2480 |
| 2492 // Load the (only) argument into eax. | 2481 // Load the (only) argument into eax. |
| 2493 __ mov(eax, Operand(esp, 1 * kPointerSize)); | 2482 __ mov(eax, Operand(esp, 1 * kPointerSize)); |
| 2494 | 2483 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2587 | 2576 |
| 2588 Counters* counters = isolate()->counters(); | 2577 Counters* counters = isolate()->counters(); |
| 2589 __ IncrementCounter(counters->call_const(), 1); | 2578 __ IncrementCounter(counters->call_const(), 1); |
| 2590 __ IncrementCounter(counters->call_const_fast_api(), 1); | 2579 __ IncrementCounter(counters->call_const_fast_api(), 1); |
| 2591 | 2580 |
| 2592 // Allocate space for v8::Arguments implicit values. Must be initialized | 2581 // Allocate space for v8::Arguments implicit values. Must be initialized |
| 2593 // before calling any runtime function. | 2582 // before calling any runtime function. |
| 2594 __ sub(esp, Immediate(kFastApiCallArguments * kPointerSize)); | 2583 __ sub(esp, Immediate(kFastApiCallArguments * kPointerSize)); |
| 2595 | 2584 |
| 2596 // Check that the maps haven't changed and find a Holder as a side effect. | 2585 // Check that the maps haven't changed and find a Holder as a side effect. |
| 2597 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi, | 2586 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, |
| 2598 name, depth, &miss); | 2587 ebx, eax, edi, name, depth, &miss); |
| 2599 | 2588 |
| 2600 // Move the return address on top of the stack. | 2589 // Move the return address on top of the stack. |
| 2601 __ mov(eax, Operand(esp, kFastApiCallArguments * kPointerSize)); | 2590 __ mov(eax, Operand(esp, kFastApiCallArguments * kPointerSize)); |
| 2602 __ mov(Operand(esp, 0 * kPointerSize), eax); | 2591 __ mov(Operand(esp, 0 * kPointerSize), eax); |
| 2603 | 2592 |
| 2604 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains | 2593 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains |
| 2605 // duplicate of return address and will be overwritten. | 2594 // duplicate of return address and will be overwritten. |
| 2606 GenerateFastApiCall(masm(), optimization, argc, false); | 2595 GenerateFastApiCall(masm(), optimization, argc, false); |
| 2607 | 2596 |
| 2608 __ bind(&miss); | 2597 __ bind(&miss); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2651 } | 2640 } |
| 2652 | 2641 |
| 2653 // Make sure that it's okay not to patch the on stack receiver | 2642 // Make sure that it's okay not to patch the on stack receiver |
| 2654 // unless we're doing a receiver map check. | 2643 // unless we're doing a receiver map check. |
| 2655 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2644 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
| 2656 switch (check) { | 2645 switch (check) { |
| 2657 case RECEIVER_MAP_CHECK: | 2646 case RECEIVER_MAP_CHECK: |
| 2658 __ IncrementCounter(isolate()->counters()->call_const(), 1); | 2647 __ IncrementCounter(isolate()->counters()->call_const(), 1); |
| 2659 | 2648 |
| 2660 // Check that the maps haven't changed. | 2649 // Check that the maps haven't changed. |
| 2661 CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, | 2650 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), edx, holder, |
| 2662 edi, name, &miss); | 2651 ebx, eax, edi, name, &miss); |
| 2663 | 2652 |
| 2664 // Patch the receiver on the stack with the global proxy if | 2653 // Patch the receiver on the stack with the global proxy if |
| 2665 // necessary. | 2654 // necessary. |
| 2666 if (object->IsGlobalObject()) { | 2655 if (object->IsGlobalObject()) { |
| 2667 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 2656 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
| 2668 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 2657 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
| 2669 } | 2658 } |
| 2670 break; | 2659 break; |
| 2671 | 2660 |
| 2672 case STRING_CHECK: | 2661 case STRING_CHECK: { |
| 2673 // Check that the object is a string. | 2662 // Check that the object is a string. |
| 2674 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax); | 2663 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax); |
| 2675 __ j(above_equal, &miss); | 2664 __ j(above_equal, &miss); |
| 2676 // Check that the maps starting from the prototype haven't changed. | 2665 // Check that the maps starting from the prototype haven't changed. |
| 2677 GenerateDirectLoadGlobalFunctionPrototype( | 2666 GenerateDirectLoadGlobalFunctionPrototype( |
| 2678 masm(), Context::STRING_FUNCTION_INDEX, eax, &miss); | 2667 masm(), Context::STRING_FUNCTION_INDEX, eax, &miss); |
| 2668 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2679 CheckPrototypes( | 2669 CheckPrototypes( |
| 2680 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2670 IC::CurrentTypeOf(prototype, isolate()), |
| 2681 eax, holder, ebx, edx, edi, name, &miss); | 2671 eax, holder, ebx, edx, edi, name, &miss); |
| 2682 break; | 2672 break; |
| 2683 | 2673 } |
| 2684 case SYMBOL_CHECK: | 2674 case SYMBOL_CHECK: { |
| 2685 // Check that the object is a symbol. | 2675 // Check that the object is a symbol. |
| 2686 __ CmpObjectType(edx, SYMBOL_TYPE, eax); | 2676 __ CmpObjectType(edx, SYMBOL_TYPE, eax); |
| 2687 __ j(not_equal, &miss); | 2677 __ j(not_equal, &miss); |
| 2688 // Check that the maps starting from the prototype haven't changed. | 2678 // Check that the maps starting from the prototype haven't changed. |
| 2689 GenerateDirectLoadGlobalFunctionPrototype( | 2679 GenerateDirectLoadGlobalFunctionPrototype( |
| 2690 masm(), Context::SYMBOL_FUNCTION_INDEX, eax, &miss); | 2680 masm(), Context::SYMBOL_FUNCTION_INDEX, eax, &miss); |
| 2681 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2691 CheckPrototypes( | 2682 CheckPrototypes( |
| 2692 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2683 IC::CurrentTypeOf(prototype, isolate()), |
| 2693 eax, holder, ebx, edx, edi, name, &miss); | 2684 eax, holder, ebx, edx, edi, name, &miss); |
| 2694 break; | 2685 break; |
| 2695 | 2686 } |
| 2696 case NUMBER_CHECK: { | 2687 case NUMBER_CHECK: { |
| 2697 Label fast; | 2688 Label fast; |
| 2698 // Check that the object is a smi or a heap number. | 2689 // Check that the object is a smi or a heap number. |
| 2699 __ JumpIfSmi(edx, &fast); | 2690 __ JumpIfSmi(edx, &fast); |
| 2700 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax); | 2691 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax); |
| 2701 __ j(not_equal, &miss); | 2692 __ j(not_equal, &miss); |
| 2702 __ bind(&fast); | 2693 __ bind(&fast); |
| 2703 // Check that the maps starting from the prototype haven't changed. | 2694 // Check that the maps starting from the prototype haven't changed. |
| 2704 GenerateDirectLoadGlobalFunctionPrototype( | 2695 GenerateDirectLoadGlobalFunctionPrototype( |
| 2705 masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss); | 2696 masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss); |
| 2697 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2706 CheckPrototypes( | 2698 CheckPrototypes( |
| 2707 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2699 IC::CurrentTypeOf(prototype, isolate()), |
| 2708 eax, holder, ebx, edx, edi, name, &miss); | 2700 eax, holder, ebx, edx, edi, name, &miss); |
| 2709 break; | 2701 break; |
| 2710 } | 2702 } |
| 2711 case BOOLEAN_CHECK: { | 2703 case BOOLEAN_CHECK: { |
| 2712 GenerateBooleanCheck(edx, &miss); | 2704 GenerateBooleanCheck(edx, &miss); |
| 2713 // Check that the maps starting from the prototype haven't changed. | 2705 // Check that the maps starting from the prototype haven't changed. |
| 2714 GenerateDirectLoadGlobalFunctionPrototype( | 2706 GenerateDirectLoadGlobalFunctionPrototype( |
| 2715 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss); | 2707 masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss); |
| 2708 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2716 CheckPrototypes( | 2709 CheckPrototypes( |
| 2717 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2710 IC::CurrentTypeOf(prototype, isolate()), |
| 2718 eax, holder, ebx, edx, edi, name, &miss); | 2711 eax, holder, ebx, edx, edi, name, &miss); |
| 2719 break; | 2712 break; |
| 2720 } | 2713 } |
| 2721 } | 2714 } |
| 2722 | 2715 |
| 2723 Label success; | 2716 Label success; |
| 2724 __ jmp(&success); | 2717 __ jmp(&success); |
| 2725 | 2718 |
| 2726 // Handle call cache miss. | 2719 // Handle call cache miss. |
| 2727 __ bind(&miss); | 2720 __ bind(&miss); |
| (...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3246 // ----------------------------------- | 3239 // ----------------------------------- |
| 3247 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 3240 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 3248 } | 3241 } |
| 3249 | 3242 |
| 3250 | 3243 |
| 3251 #undef __ | 3244 #undef __ |
| 3252 | 3245 |
| 3253 } } // namespace v8::internal | 3246 } } // namespace v8::internal |
| 3254 | 3247 |
| 3255 #endif // V8_TARGET_ARCH_IA32 | 3248 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |