Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

Side by Side Diff: src/ia32/stub-cache-ia32.cc

Issue 78023002: Use Type in CheckPrototypes. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/stub-cache-arm.cc ('k') | src/ic.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 &regular_invoke); 669 &regular_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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/arm/stub-cache-arm.cc ('k') | src/ic.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698