| 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 627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 638 if (can_do_fast_api_call) { | 638 if (can_do_fast_api_call) { |
| 639 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1); | 639 __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1); |
| 640 ReserveSpaceForFastApiCall(masm, scratch1); | 640 ReserveSpaceForFastApiCall(masm, scratch1); |
| 641 } | 641 } |
| 642 | 642 |
| 643 // Check that the maps from receiver to interceptor's holder | 643 // Check that the maps from receiver to interceptor's holder |
| 644 // haven't changed and thus we can invoke interceptor. | 644 // haven't changed and thus we can invoke interceptor. |
| 645 Label miss_cleanup; | 645 Label miss_cleanup; |
| 646 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; | 646 Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; |
| 647 Register holder = | 647 Register holder = |
| 648 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, | 648 stub_compiler_->CheckPrototypes( |
| 649 scratch1, scratch2, scratch3, | 649 IC::CurrentTypeOf(object, masm->isolate()), receiver, |
| 650 name, depth1, miss); | 650 interceptor_holder, scratch1, scratch2, scratch3, |
| 651 name, depth1, miss); |
| 651 | 652 |
| 652 // Invoke an interceptor and if it provides a value, | 653 // Invoke an interceptor and if it provides a value, |
| 653 // branch to |regular_invoke|. | 654 // branch to |regular_invoke|. |
| 654 Label regular_invoke; | 655 Label regular_invoke; |
| 655 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, | 656 LoadWithInterceptor(masm, receiver, holder, interceptor_holder, |
| 656 ®ular_invoke); | 657 ®ular_invoke); |
| 657 | 658 |
| 658 // Interceptor returned nothing for this property. Try to use cached | 659 // Interceptor returned nothing for this property. Try to use cached |
| 659 // constant function. | 660 // constant function. |
| 660 | 661 |
| 661 // Check that the maps from interceptor's holder to constant function's | 662 // Check that the maps from interceptor's holder to constant function's |
| 662 // holder haven't changed and thus we can use cached constant function. | 663 // holder haven't changed and thus we can use cached constant function. |
| 663 if (*interceptor_holder != lookup->holder()) { | 664 if (*interceptor_holder != lookup->holder()) { |
| 664 stub_compiler_->CheckPrototypes(interceptor_holder, receiver, | 665 stub_compiler_->CheckPrototypes( |
| 665 Handle<JSObject>(lookup->holder()), | 666 IC::CurrentTypeOf(interceptor_holder, masm->isolate()), receiver, |
| 666 scratch1, scratch2, scratch3, | 667 handle(lookup->holder()), scratch1, scratch2, scratch3, |
| 667 name, depth2, miss); | 668 name, depth2, miss); |
| 668 } else { | 669 } else { |
| 669 // CheckPrototypes has a side effect of fetching a 'holder' | 670 // CheckPrototypes has a side effect of fetching a 'holder' |
| 670 // for API (object which is instanceof for the signature). It's | 671 // for API (object which is instanceof for the signature). It's |
| 671 // safe to omit it here, as if present, it should be fetched | 672 // safe to omit it here, as if present, it should be fetched |
| 672 // by the previous CheckPrototypes. | 673 // by the previous CheckPrototypes. |
| 673 ASSERT(depth2 == kInvalidProtoDepth); | 674 ASSERT(depth2 == kInvalidProtoDepth); |
| 674 } | 675 } |
| 675 | 676 |
| 676 // Invoke function. | 677 // Invoke function. |
| 677 if (can_do_fast_api_call) { | 678 if (can_do_fast_api_call) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 703 void CompileRegular(MacroAssembler* masm, | 704 void CompileRegular(MacroAssembler* masm, |
| 704 Handle<JSObject> object, | 705 Handle<JSObject> object, |
| 705 Register receiver, | 706 Register receiver, |
| 706 Register scratch1, | 707 Register scratch1, |
| 707 Register scratch2, | 708 Register scratch2, |
| 708 Register scratch3, | 709 Register scratch3, |
| 709 Handle<Name> name, | 710 Handle<Name> name, |
| 710 Handle<JSObject> interceptor_holder, | 711 Handle<JSObject> interceptor_holder, |
| 711 Label* miss_label) { | 712 Label* miss_label) { |
| 712 Register holder = | 713 Register holder = |
| 713 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, | 714 stub_compiler_->CheckPrototypes( |
| 714 scratch1, scratch2, scratch3, | 715 IC::CurrentTypeOf(object, masm->isolate()), receiver, |
| 715 name, miss_label); | 716 interceptor_holder, scratch1, scratch2, scratch3, name, miss_label); |
| 716 | 717 |
| 717 FrameScope scope(masm, StackFrame::INTERNAL); | 718 FrameScope scope(masm, StackFrame::INTERNAL); |
| 718 // Save the name_ register across the call. | 719 // Save the name_ register across the call. |
| 719 __ push(name_); | 720 __ push(name_); |
| 720 | 721 |
| 721 PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder); | 722 PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder); |
| 722 | 723 |
| 723 __ CallExternalReference( | 724 __ CallExternalReference( |
| 724 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), | 725 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), |
| 725 masm->isolate()), | 726 masm->isolate()), |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1040 EMIT_REMEMBERED_SET, smi_check); | 1041 EMIT_REMEMBERED_SET, smi_check); |
| 1041 } | 1042 } |
| 1042 } | 1043 } |
| 1043 | 1044 |
| 1044 // Return the value (register rax). | 1045 // Return the value (register rax). |
| 1045 ASSERT(value_reg.is(rax)); | 1046 ASSERT(value_reg.is(rax)); |
| 1046 __ ret(0); | 1047 __ ret(0); |
| 1047 } | 1048 } |
| 1048 | 1049 |
| 1049 | 1050 |
| 1050 void StubCompiler::GenerateCheckPropertyCells(MacroAssembler* masm, | |
| 1051 Handle<JSObject> object, | |
| 1052 Handle<JSObject> holder, | |
| 1053 Handle<Name> name, | |
| 1054 Register scratch, | |
| 1055 Label* miss) { | |
| 1056 Handle<JSObject> current = object; | |
| 1057 while (!current.is_identical_to(holder)) { | |
| 1058 if (current->IsJSGlobalObject()) { | |
| 1059 GenerateCheckPropertyCell(masm, | |
| 1060 Handle<JSGlobalObject>::cast(current), | |
| 1061 name, | |
| 1062 scratch, | |
| 1063 miss); | |
| 1064 } | |
| 1065 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); | |
| 1066 } | |
| 1067 } | |
| 1068 | |
| 1069 | |
| 1070 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { | 1051 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { |
| 1071 __ jmp(code, RelocInfo::CODE_TARGET); | 1052 __ jmp(code, RelocInfo::CODE_TARGET); |
| 1072 } | 1053 } |
| 1073 | 1054 |
| 1074 | 1055 |
| 1075 #undef __ | 1056 #undef __ |
| 1076 #define __ ACCESS_MASM((masm())) | 1057 #define __ ACCESS_MASM((masm())) |
| 1077 | 1058 |
| 1078 | 1059 |
| 1079 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, | 1060 Register StubCompiler::CheckPrototypes(Handle<Type> type, |
| 1080 Register object_reg, | 1061 Register object_reg, |
| 1081 Handle<JSObject> holder, | 1062 Handle<JSObject> holder, |
| 1082 Register holder_reg, | 1063 Register holder_reg, |
| 1083 Register scratch1, | 1064 Register scratch1, |
| 1084 Register scratch2, | 1065 Register scratch2, |
| 1085 Handle<Name> name, | 1066 Handle<Name> name, |
| 1086 int save_at_depth, | 1067 int save_at_depth, |
| 1087 Label* miss, | 1068 Label* miss, |
| 1088 PrototypeCheckType check) { | 1069 PrototypeCheckType check) { |
| 1070 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); |
| 1089 // Make sure that the type feedback oracle harvests the receiver map. | 1071 // Make sure that the type feedback oracle harvests the receiver map. |
| 1090 // TODO(svenpanne) Remove this hack when all ICs are reworked. | 1072 // TODO(svenpanne) Remove this hack when all ICs are reworked. |
| 1091 __ Move(scratch1, Handle<Map>(object->map())); | 1073 __ Move(scratch1, receiver_map); |
| 1092 | 1074 |
| 1093 Handle<JSObject> first = object; | |
| 1094 // Make sure there's no overlap between holder and object registers. | 1075 // Make sure there's no overlap between holder and object registers. |
| 1095 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 1076 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
| 1096 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 1077 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
| 1097 && !scratch2.is(scratch1)); | 1078 && !scratch2.is(scratch1)); |
| 1098 | 1079 |
| 1099 // Keep track of the current object in register reg. On the first | 1080 // Keep track of the current object in register reg. On the first |
| 1100 // iteration, reg is an alias for object_reg, on later iterations, | 1081 // iteration, reg is an alias for object_reg, on later iterations, |
| 1101 // it is an alias for holder_reg. | 1082 // it is an alias for holder_reg. |
| 1102 Register reg = object_reg; | 1083 Register reg = object_reg; |
| 1103 int depth = 0; | 1084 int depth = 0; |
| 1104 | 1085 |
| 1105 StackArgumentsAccessor args(rsp, kFastApiCallArguments, | 1086 StackArgumentsAccessor args(rsp, kFastApiCallArguments, |
| 1106 ARGUMENTS_DONT_CONTAIN_RECEIVER); | 1087 ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 1107 const int kHolderIndex = kFastApiCallArguments - 1 - | 1088 const int kHolderIndex = kFastApiCallArguments - 1 - |
| 1108 FunctionCallbackArguments::kHolderIndex; | 1089 FunctionCallbackArguments::kHolderIndex; |
| 1109 | 1090 |
| 1110 if (save_at_depth == depth) { | 1091 if (save_at_depth == depth) { |
| 1111 __ movq(args.GetArgumentOperand(kHolderIndex), object_reg); | 1092 __ movq(args.GetArgumentOperand(kHolderIndex), object_reg); |
| 1112 } | 1093 } |
| 1113 | 1094 |
| 1114 // Check the maps in the prototype chain. | 1095 Handle<JSObject> current = Handle<JSObject>::null(); |
| 1115 // Traverse the prototype chain from the object and do map checks. | 1096 if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant()); |
| 1116 Handle<JSObject> current = object; | 1097 Handle<JSObject> prototype = Handle<JSObject>::null(); |
| 1117 while (!current.is_identical_to(holder)) { | 1098 Handle<Map> current_map = receiver_map; |
| 1099 Handle<Map> holder_map(holder->map()); |
| 1100 // Traverse the prototype chain and check the maps in the prototype chain for |
| 1101 // fast and global objects or do negative lookup for normal objects. |
| 1102 while (!current_map.is_identical_to(holder_map)) { |
| 1118 ++depth; | 1103 ++depth; |
| 1119 | 1104 |
| 1120 // Only global objects and objects that do not require access | 1105 // Only global objects and objects that do not require access |
| 1121 // checks are allowed in stubs. | 1106 // checks are allowed in stubs. |
| 1122 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); | 1107 ASSERT(current_map->IsJSGlobalProxyMap() || |
| 1108 !current_map->is_access_check_needed()); |
| 1123 | 1109 |
| 1124 Handle<JSObject> prototype(JSObject::cast(current->GetPrototype())); | 1110 prototype = handle(JSObject::cast(current_map->prototype())); |
| 1125 if (!current->HasFastProperties() && | 1111 if (current_map->is_dictionary_map() && |
| 1126 !current->IsJSGlobalObject() && | 1112 !current_map->IsJSGlobalObjectMap() && |
| 1127 !current->IsJSGlobalProxy()) { | 1113 !current_map->IsJSGlobalProxyMap()) { |
| 1128 if (!name->IsUniqueName()) { | 1114 if (!name->IsUniqueName()) { |
| 1129 ASSERT(name->IsString()); | 1115 ASSERT(name->IsString()); |
| 1130 name = factory()->InternalizeString(Handle<String>::cast(name)); | 1116 name = factory()->InternalizeString(Handle<String>::cast(name)); |
| 1131 } | 1117 } |
| 1132 ASSERT(current->property_dictionary()->FindEntry(*name) == | 1118 ASSERT(current.is_null() || |
| 1119 current->property_dictionary()->FindEntry(*name) == |
| 1133 NameDictionary::kNotFound); | 1120 NameDictionary::kNotFound); |
| 1134 | 1121 |
| 1135 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, | 1122 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, |
| 1136 scratch1, scratch2); | 1123 scratch1, scratch2); |
| 1137 | 1124 |
| 1138 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 1125 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1139 reg = holder_reg; // From now on the object will be in holder_reg. | 1126 reg = holder_reg; // From now on the object will be in holder_reg. |
| 1140 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 1127 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 1141 } else { | 1128 } else { |
| 1142 bool in_new_space = heap()->InNewSpace(*prototype); | 1129 bool in_new_space = heap()->InNewSpace(*prototype); |
| 1143 Handle<Map> current_map(current->map()); | |
| 1144 if (in_new_space) { | 1130 if (in_new_space) { |
| 1145 // Save the map in scratch1 for later. | 1131 // Save the map in scratch1 for later. |
| 1146 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 1132 __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1147 } | 1133 } |
| 1148 if (!current.is_identical_to(first) || check == CHECK_ALL_MAPS) { | 1134 if (depth != 1 || check == CHECK_ALL_MAPS) { |
| 1149 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK); | 1135 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK); |
| 1150 } | 1136 } |
| 1151 | 1137 |
| 1152 // Check access rights to the global object. This has to happen after | 1138 // Check access rights to the global object. This has to happen after |
| 1153 // the map check so that we know that the object is actually a global | 1139 // the map check so that we know that the object is actually a global |
| 1154 // object. | 1140 // object. |
| 1155 if (current->IsJSGlobalProxy()) { | 1141 if (current_map->IsJSGlobalProxyMap()) { |
| 1156 __ CheckAccessGlobalProxy(reg, scratch2, miss); | 1142 __ CheckAccessGlobalProxy(reg, scratch2, miss); |
| 1143 } else if (current_map->IsJSGlobalObjectMap()) { |
| 1144 GenerateCheckPropertyCell( |
| 1145 masm(), Handle<JSGlobalObject>::cast(current), name, |
| 1146 scratch2, miss); |
| 1157 } | 1147 } |
| 1158 reg = holder_reg; // From now on the object will be in holder_reg. | 1148 reg = holder_reg; // From now on the object will be in holder_reg. |
| 1159 | 1149 |
| 1160 if (in_new_space) { | 1150 if (in_new_space) { |
| 1161 // The prototype is in new space; we cannot store a reference to it | 1151 // The prototype is in new space; we cannot store a reference to it |
| 1162 // in the code. Load it from the map. | 1152 // in the code. Load it from the map. |
| 1163 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 1153 __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 1164 } else { | 1154 } else { |
| 1165 // The prototype is in old space; load it directly. | 1155 // The prototype is in old space; load it directly. |
| 1166 __ Move(reg, prototype); | 1156 __ Move(reg, prototype); |
| 1167 } | 1157 } |
| 1168 } | 1158 } |
| 1169 | 1159 |
| 1170 if (save_at_depth == depth) { | 1160 if (save_at_depth == depth) { |
| 1171 __ movq(args.GetArgumentOperand(kHolderIndex), reg); | 1161 __ movq(args.GetArgumentOperand(kHolderIndex), reg); |
| 1172 } | 1162 } |
| 1173 | 1163 |
| 1174 // Go to the next object in the prototype chain. | 1164 // Go to the next object in the prototype chain. |
| 1175 current = prototype; | 1165 current = prototype; |
| 1166 current_map = handle(current->map()); |
| 1176 } | 1167 } |
| 1177 ASSERT(current.is_identical_to(holder)); | |
| 1178 | 1168 |
| 1179 // Log the check depth. | 1169 // Log the check depth. |
| 1180 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 1170 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
| 1181 | 1171 |
| 1182 if (!holder.is_identical_to(first) || check == CHECK_ALL_MAPS) { | 1172 if (depth != 0 || check == CHECK_ALL_MAPS) { |
| 1183 // Check the holder map. | 1173 // Check the holder map. |
| 1184 __ CheckMap(reg, Handle<Map>(holder->map()), miss, DONT_DO_SMI_CHECK); | 1174 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK); |
| 1185 } | 1175 } |
| 1186 | 1176 |
| 1187 // Perform security check for access to the global object. | 1177 // Perform security check for access to the global object. |
| 1188 ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); | 1178 ASSERT(current_map->IsJSGlobalProxyMap() || |
| 1189 if (current->IsJSGlobalProxy()) { | 1179 !current_map->is_access_check_needed()); |
| 1180 if (current_map->IsJSGlobalProxyMap()) { |
| 1190 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 1181 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| 1191 } | 1182 } |
| 1192 | 1183 |
| 1193 // If we've skipped any global objects, it's not enough to verify that | |
| 1194 // their maps haven't changed. We also need to check that the property | |
| 1195 // cell for the property is still empty. | |
| 1196 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); | |
| 1197 | |
| 1198 // Return the register containing the holder. | 1184 // Return the register containing the holder. |
| 1199 return reg; | 1185 return reg; |
| 1200 } | 1186 } |
| 1201 | 1187 |
| 1202 | 1188 |
| 1203 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { | 1189 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { |
| 1204 if (!miss->is_unused()) { | 1190 if (!miss->is_unused()) { |
| 1205 Label success; | 1191 Label success; |
| 1206 __ jmp(&success); | 1192 __ jmp(&success); |
| 1207 __ bind(miss); | 1193 __ bind(miss); |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1492 Handle<Name> name, | 1478 Handle<Name> name, |
| 1493 Label* miss) { | 1479 Label* miss) { |
| 1494 ASSERT(holder->IsGlobalObject()); | 1480 ASSERT(holder->IsGlobalObject()); |
| 1495 | 1481 |
| 1496 StackArgumentsAccessor args(rsp, arguments()); | 1482 StackArgumentsAccessor args(rsp, arguments()); |
| 1497 __ movq(rdx, args.GetReceiverOperand()); | 1483 __ movq(rdx, args.GetReceiverOperand()); |
| 1498 | 1484 |
| 1499 | 1485 |
| 1500 // Check that the maps haven't changed. | 1486 // Check that the maps haven't changed. |
| 1501 __ JumpIfSmi(rdx, miss); | 1487 __ JumpIfSmi(rdx, miss); |
| 1502 CheckPrototypes(object, rdx, holder, rbx, rax, rdi, name, miss); | 1488 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, |
| 1489 rbx, rax, rdi, name, miss); |
| 1503 } | 1490 } |
| 1504 | 1491 |
| 1505 | 1492 |
| 1506 void CallStubCompiler::GenerateLoadFunctionFromCell( | 1493 void CallStubCompiler::GenerateLoadFunctionFromCell( |
| 1507 Handle<Cell> cell, | 1494 Handle<Cell> cell, |
| 1508 Handle<JSFunction> function, | 1495 Handle<JSFunction> function, |
| 1509 Label* miss) { | 1496 Label* miss) { |
| 1510 // Get the value from the cell. | 1497 // Get the value from the cell. |
| 1511 __ Move(rdi, cell); | 1498 __ Move(rdi, cell); |
| 1512 __ movq(rdi, FieldOperand(rdi, Cell::kValueOffset)); | 1499 __ movq(rdi, FieldOperand(rdi, Cell::kValueOffset)); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1558 | 1545 |
| 1559 GenerateNameCheck(name, &miss); | 1546 GenerateNameCheck(name, &miss); |
| 1560 | 1547 |
| 1561 StackArgumentsAccessor args(rsp, arguments()); | 1548 StackArgumentsAccessor args(rsp, arguments()); |
| 1562 __ movq(rdx, args.GetReceiverOperand()); | 1549 __ movq(rdx, args.GetReceiverOperand()); |
| 1563 | 1550 |
| 1564 // Check that the receiver isn't a smi. | 1551 // Check that the receiver isn't a smi. |
| 1565 __ JumpIfSmi(rdx, &miss); | 1552 __ JumpIfSmi(rdx, &miss); |
| 1566 | 1553 |
| 1567 // Do the right check and compute the holder register. | 1554 // Do the right check and compute the holder register. |
| 1568 Register reg = CheckPrototypes(object, rdx, holder, rbx, rax, rdi, | 1555 Register reg = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, |
| 1569 name, &miss); | 1556 holder, rbx, rax, rdi, name, &miss); |
| 1570 | 1557 |
| 1571 GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder), | 1558 GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder), |
| 1572 index.translate(holder), Representation::Tagged()); | 1559 index.translate(holder), Representation::Tagged()); |
| 1573 | 1560 |
| 1574 // Check that the function really is a function. | 1561 // Check that the function really is a function. |
| 1575 __ JumpIfSmi(rdi, &miss); | 1562 __ JumpIfSmi(rdi, &miss); |
| 1576 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx); | 1563 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx); |
| 1577 __ j(not_equal, &miss); | 1564 __ j(not_equal, &miss); |
| 1578 | 1565 |
| 1579 // Patch the receiver on the stack with the global proxy if | 1566 // Patch the receiver on the stack with the global proxy if |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1611 // Check that function is still array | 1598 // Check that function is still array |
| 1612 const int argc = arguments().immediate(); | 1599 const int argc = arguments().immediate(); |
| 1613 StackArgumentsAccessor args(rsp, argc); | 1600 StackArgumentsAccessor args(rsp, argc); |
| 1614 GenerateNameCheck(name, &miss); | 1601 GenerateNameCheck(name, &miss); |
| 1615 | 1602 |
| 1616 if (cell.is_null()) { | 1603 if (cell.is_null()) { |
| 1617 __ movq(rdx, args.GetReceiverOperand()); | 1604 __ movq(rdx, args.GetReceiverOperand()); |
| 1618 | 1605 |
| 1619 // Check that the receiver isn't a smi. | 1606 // Check that the receiver isn't a smi. |
| 1620 __ JumpIfSmi(rdx, &miss); | 1607 __ JumpIfSmi(rdx, &miss); |
| 1621 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | 1608 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, |
| 1622 name, &miss); | 1609 rbx, rax, rdi, name, &miss); |
| 1623 } else { | 1610 } else { |
| 1624 ASSERT(cell->value() == *function); | 1611 ASSERT(cell->value() == *function); |
| 1625 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 1612 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 1626 &miss); | 1613 &miss); |
| 1627 GenerateLoadFunctionFromCell(cell, function, &miss); | 1614 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 1628 } | 1615 } |
| 1629 | 1616 |
| 1630 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); | 1617 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); |
| 1631 site->SetElementsKind(GetInitialFastElementsKind()); | 1618 site->SetElementsKind(GetInitialFastElementsKind()); |
| 1632 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); | 1619 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1670 Label miss; | 1657 Label miss; |
| 1671 GenerateNameCheck(name, &miss); | 1658 GenerateNameCheck(name, &miss); |
| 1672 | 1659 |
| 1673 const int argc = arguments().immediate(); | 1660 const int argc = arguments().immediate(); |
| 1674 StackArgumentsAccessor args(rsp, argc); | 1661 StackArgumentsAccessor args(rsp, argc); |
| 1675 __ movq(rdx, args.GetReceiverOperand()); | 1662 __ movq(rdx, args.GetReceiverOperand()); |
| 1676 | 1663 |
| 1677 // Check that the receiver isn't a smi. | 1664 // Check that the receiver isn't a smi. |
| 1678 __ JumpIfSmi(rdx, &miss); | 1665 __ JumpIfSmi(rdx, &miss); |
| 1679 | 1666 |
| 1680 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | 1667 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, |
| 1681 name, &miss); | 1668 rbx, rax, rdi, name, &miss); |
| 1682 | 1669 |
| 1683 if (argc == 0) { | 1670 if (argc == 0) { |
| 1684 // Noop, return the length. | 1671 // Noop, return the length. |
| 1685 __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset)); | 1672 __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset)); |
| 1686 __ ret((argc + 1) * kPointerSize); | 1673 __ ret((argc + 1) * kPointerSize); |
| 1687 } else { | 1674 } else { |
| 1688 Label call_builtin; | 1675 Label call_builtin; |
| 1689 | 1676 |
| 1690 if (argc == 1) { // Otherwise fall through to call builtin. | 1677 if (argc == 1) { // Otherwise fall through to call builtin. |
| 1691 Label attempt_to_grow_elements, with_write_barrier, check_double; | 1678 Label attempt_to_grow_elements, with_write_barrier, check_double; |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1925 Label miss, return_undefined, call_builtin; | 1912 Label miss, return_undefined, call_builtin; |
| 1926 GenerateNameCheck(name, &miss); | 1913 GenerateNameCheck(name, &miss); |
| 1927 | 1914 |
| 1928 const int argc = arguments().immediate(); | 1915 const int argc = arguments().immediate(); |
| 1929 StackArgumentsAccessor args(rsp, argc); | 1916 StackArgumentsAccessor args(rsp, argc); |
| 1930 __ movq(rdx, args.GetReceiverOperand()); | 1917 __ movq(rdx, args.GetReceiverOperand()); |
| 1931 | 1918 |
| 1932 // Check that the receiver isn't a smi. | 1919 // Check that the receiver isn't a smi. |
| 1933 __ JumpIfSmi(rdx, &miss); | 1920 __ JumpIfSmi(rdx, &miss); |
| 1934 | 1921 |
| 1935 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | 1922 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, |
| 1936 name, &miss); | 1923 rbx, rax, rdi, name, &miss); |
| 1937 | 1924 |
| 1938 // Get the elements array of the object. | 1925 // Get the elements array of the object. |
| 1939 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); | 1926 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); |
| 1940 | 1927 |
| 1941 // Check that the elements are in fast mode and writable. | 1928 // Check that the elements are in fast mode and writable. |
| 1942 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), | 1929 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), |
| 1943 Heap::kFixedArrayMapRootIndex); | 1930 Heap::kFixedArrayMapRootIndex); |
| 1944 __ j(not_equal, &call_builtin); | 1931 __ j(not_equal, &call_builtin); |
| 1945 | 1932 |
| 1946 // Get the array's length into rcx and calculate new length. | 1933 // Get the array's length into rcx and calculate new length. |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2017 index_out_of_range_label = &miss; | 2004 index_out_of_range_label = &miss; |
| 2018 } | 2005 } |
| 2019 GenerateNameCheck(name, &name_miss); | 2006 GenerateNameCheck(name, &name_miss); |
| 2020 | 2007 |
| 2021 // Check that the maps starting from the prototype haven't changed. | 2008 // Check that the maps starting from the prototype haven't changed. |
| 2022 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 2009 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 2023 Context::STRING_FUNCTION_INDEX, | 2010 Context::STRING_FUNCTION_INDEX, |
| 2024 rax, | 2011 rax, |
| 2025 &miss); | 2012 &miss); |
| 2026 ASSERT(!object.is_identical_to(holder)); | 2013 ASSERT(!object.is_identical_to(holder)); |
| 2014 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2027 CheckPrototypes( | 2015 CheckPrototypes( |
| 2028 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2016 IC::CurrentTypeOf(prototype, isolate()), |
| 2029 rax, holder, rbx, rdx, rdi, name, &miss); | 2017 rax, holder, rbx, rdx, rdi, name, &miss); |
| 2030 | 2018 |
| 2031 Register receiver = rbx; | 2019 Register receiver = rbx; |
| 2032 Register index = rdi; | 2020 Register index = rdi; |
| 2033 Register result = rax; | 2021 Register result = rax; |
| 2034 __ movq(receiver, args.GetReceiverOperand()); | 2022 __ movq(receiver, args.GetReceiverOperand()); |
| 2035 if (argc > 0) { | 2023 if (argc > 0) { |
| 2036 __ movq(index, args.GetArgumentOperand(1)); | 2024 __ movq(index, args.GetArgumentOperand(1)); |
| 2037 } else { | 2025 } else { |
| 2038 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | 2026 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2099 index_out_of_range_label = &miss; | 2087 index_out_of_range_label = &miss; |
| 2100 } | 2088 } |
| 2101 GenerateNameCheck(name, &name_miss); | 2089 GenerateNameCheck(name, &name_miss); |
| 2102 | 2090 |
| 2103 // Check that the maps starting from the prototype haven't changed. | 2091 // Check that the maps starting from the prototype haven't changed. |
| 2104 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 2092 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 2105 Context::STRING_FUNCTION_INDEX, | 2093 Context::STRING_FUNCTION_INDEX, |
| 2106 rax, | 2094 rax, |
| 2107 &miss); | 2095 &miss); |
| 2108 ASSERT(!object.is_identical_to(holder)); | 2096 ASSERT(!object.is_identical_to(holder)); |
| 2097 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2109 CheckPrototypes( | 2098 CheckPrototypes( |
| 2110 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2099 IC::CurrentTypeOf(prototype, isolate()), |
| 2111 rax, holder, rbx, rdx, rdi, name, &miss); | 2100 rax, holder, rbx, rdx, rdi, name, &miss); |
| 2112 | 2101 |
| 2113 Register receiver = rax; | 2102 Register receiver = rax; |
| 2114 Register index = rdi; | 2103 Register index = rdi; |
| 2115 Register scratch = rdx; | 2104 Register scratch = rdx; |
| 2116 Register result = rax; | 2105 Register result = rax; |
| 2117 __ movq(receiver, args.GetReceiverOperand()); | 2106 __ movq(receiver, args.GetReceiverOperand()); |
| 2118 if (argc > 0) { | 2107 if (argc > 0) { |
| 2119 __ movq(index, args.GetArgumentOperand(1)); | 2108 __ movq(index, args.GetArgumentOperand(1)); |
| 2120 } else { | 2109 } else { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2171 const int argc = arguments().immediate(); | 2160 const int argc = arguments().immediate(); |
| 2172 StackArgumentsAccessor args(rsp, argc); | 2161 StackArgumentsAccessor args(rsp, argc); |
| 2173 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2162 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2174 | 2163 |
| 2175 Label miss; | 2164 Label miss; |
| 2176 GenerateNameCheck(name, &miss); | 2165 GenerateNameCheck(name, &miss); |
| 2177 | 2166 |
| 2178 if (cell.is_null()) { | 2167 if (cell.is_null()) { |
| 2179 __ movq(rdx, args.GetReceiverOperand()); | 2168 __ movq(rdx, args.GetReceiverOperand()); |
| 2180 __ JumpIfSmi(rdx, &miss); | 2169 __ JumpIfSmi(rdx, &miss); |
| 2181 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | 2170 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, |
| 2182 name, &miss); | 2171 rbx, rax, rdi, name, &miss); |
| 2183 } else { | 2172 } else { |
| 2184 ASSERT(cell->value() == *function); | 2173 ASSERT(cell->value() == *function); |
| 2185 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 2174 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 2186 &miss); | 2175 &miss); |
| 2187 GenerateLoadFunctionFromCell(cell, function, &miss); | 2176 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2188 } | 2177 } |
| 2189 | 2178 |
| 2190 // Load the char code argument. | 2179 // Load the char code argument. |
| 2191 Register code = rbx; | 2180 Register code = rbx; |
| 2192 __ movq(code, args.GetArgumentOperand(1)); | 2181 __ movq(code, args.GetArgumentOperand(1)); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2249 | 2238 |
| 2250 Label miss; | 2239 Label miss; |
| 2251 GenerateNameCheck(name, &miss); | 2240 GenerateNameCheck(name, &miss); |
| 2252 | 2241 |
| 2253 if (cell.is_null()) { | 2242 if (cell.is_null()) { |
| 2254 __ movq(rdx, args.GetReceiverOperand()); | 2243 __ movq(rdx, args.GetReceiverOperand()); |
| 2255 | 2244 |
| 2256 STATIC_ASSERT(kSmiTag == 0); | 2245 STATIC_ASSERT(kSmiTag == 0); |
| 2257 __ JumpIfSmi(rdx, &miss); | 2246 __ JumpIfSmi(rdx, &miss); |
| 2258 | 2247 |
| 2259 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | 2248 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, |
| 2260 name, &miss); | 2249 rbx, rax, rdi, name, &miss); |
| 2261 } else { | 2250 } else { |
| 2262 ASSERT(cell->value() == *function); | 2251 ASSERT(cell->value() == *function); |
| 2263 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 2252 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 2264 &miss); | 2253 &miss); |
| 2265 GenerateLoadFunctionFromCell(cell, function, &miss); | 2254 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2266 } | 2255 } |
| 2267 | 2256 |
| 2268 // Load the (only) argument into rax. | 2257 // Load the (only) argument into rax. |
| 2269 __ movq(rax, args.GetArgumentOperand(1)); | 2258 __ movq(rax, args.GetArgumentOperand(1)); |
| 2270 | 2259 |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2372 const int argc = arguments().immediate(); | 2361 const int argc = arguments().immediate(); |
| 2373 StackArgumentsAccessor args(rsp, argc); | 2362 StackArgumentsAccessor args(rsp, argc); |
| 2374 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2363 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2375 | 2364 |
| 2376 Label miss; | 2365 Label miss; |
| 2377 GenerateNameCheck(name, &miss); | 2366 GenerateNameCheck(name, &miss); |
| 2378 | 2367 |
| 2379 if (cell.is_null()) { | 2368 if (cell.is_null()) { |
| 2380 __ movq(rdx, args.GetReceiverOperand()); | 2369 __ movq(rdx, args.GetReceiverOperand()); |
| 2381 __ JumpIfSmi(rdx, &miss); | 2370 __ JumpIfSmi(rdx, &miss); |
| 2382 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | 2371 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, |
| 2383 name, &miss); | 2372 rbx, rax, rdi, name, &miss); |
| 2384 } else { | 2373 } else { |
| 2385 ASSERT(cell->value() == *function); | 2374 ASSERT(cell->value() == *function); |
| 2386 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | 2375 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, |
| 2387 &miss); | 2376 &miss); |
| 2388 GenerateLoadFunctionFromCell(cell, function, &miss); | 2377 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2389 } | 2378 } |
| 2390 // Load the (only) argument into rax. | 2379 // Load the (only) argument into rax. |
| 2391 __ movq(rax, args.GetArgumentOperand(1)); | 2380 __ movq(rax, args.GetArgumentOperand(1)); |
| 2392 | 2381 |
| 2393 // Check if the argument is a smi. | 2382 // Check if the argument is a smi. |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2486 | 2475 |
| 2487 Counters* counters = isolate()->counters(); | 2476 Counters* counters = isolate()->counters(); |
| 2488 __ IncrementCounter(counters->call_const(), 1); | 2477 __ IncrementCounter(counters->call_const(), 1); |
| 2489 __ IncrementCounter(counters->call_const_fast_api(), 1); | 2478 __ IncrementCounter(counters->call_const_fast_api(), 1); |
| 2490 | 2479 |
| 2491 // Allocate space for v8::Arguments implicit values. Must be initialized | 2480 // Allocate space for v8::Arguments implicit values. Must be initialized |
| 2492 // before calling any runtime function. | 2481 // before calling any runtime function. |
| 2493 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); | 2482 __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); |
| 2494 | 2483 |
| 2495 // Check that the maps haven't changed and find a Holder as a side effect. | 2484 // Check that the maps haven't changed and find a Holder as a side effect. |
| 2496 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, | 2485 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, |
| 2497 name, depth, &miss); | 2486 rbx, rax, rdi, name, depth, &miss); |
| 2498 | 2487 |
| 2499 // Move the return address on top of the stack. | 2488 // Move the return address on top of the stack. |
| 2500 __ movq(rax, | 2489 __ movq(rax, |
| 2501 StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize)); | 2490 StackOperandForReturnAddress(kFastApiCallArguments * kPointerSize)); |
| 2502 __ movq(StackOperandForReturnAddress(0), rax); | 2491 __ movq(StackOperandForReturnAddress(0), rax); |
| 2503 | 2492 |
| 2504 GenerateFastApiCall(masm(), optimization, argc, false); | 2493 GenerateFastApiCall(masm(), optimization, argc, false); |
| 2505 | 2494 |
| 2506 __ bind(&miss); | 2495 __ bind(&miss); |
| 2507 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); | 2496 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2552 // Make sure that it's okay not to patch the on stack receiver | 2541 // Make sure that it's okay not to patch the on stack receiver |
| 2553 // unless we're doing a receiver map check. | 2542 // unless we're doing a receiver map check. |
| 2554 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2543 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
| 2555 | 2544 |
| 2556 Counters* counters = isolate()->counters(); | 2545 Counters* counters = isolate()->counters(); |
| 2557 switch (check) { | 2546 switch (check) { |
| 2558 case RECEIVER_MAP_CHECK: | 2547 case RECEIVER_MAP_CHECK: |
| 2559 __ IncrementCounter(counters->call_const(), 1); | 2548 __ IncrementCounter(counters->call_const(), 1); |
| 2560 | 2549 |
| 2561 // Check that the maps haven't changed. | 2550 // Check that the maps haven't changed. |
| 2562 CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, | 2551 CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder, |
| 2563 rdi, name, &miss); | 2552 rbx, rax, rdi, name, &miss); |
| 2564 | 2553 |
| 2565 // Patch the receiver on the stack with the global proxy if | 2554 // Patch the receiver on the stack with the global proxy if |
| 2566 // necessary. | 2555 // necessary. |
| 2567 if (object->IsGlobalObject()) { | 2556 if (object->IsGlobalObject()) { |
| 2568 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 2557 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 2569 __ movq(args.GetReceiverOperand(), rdx); | 2558 __ movq(args.GetReceiverOperand(), rdx); |
| 2570 } | 2559 } |
| 2571 break; | 2560 break; |
| 2572 | 2561 |
| 2573 case STRING_CHECK: | 2562 case STRING_CHECK: { |
| 2574 // Check that the object is a string. | 2563 // Check that the object is a string. |
| 2575 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax); | 2564 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax); |
| 2576 __ j(above_equal, &miss); | 2565 __ j(above_equal, &miss); |
| 2577 // Check that the maps starting from the prototype haven't changed. | 2566 // Check that the maps starting from the prototype haven't changed. |
| 2578 GenerateDirectLoadGlobalFunctionPrototype( | 2567 GenerateDirectLoadGlobalFunctionPrototype( |
| 2579 masm(), Context::STRING_FUNCTION_INDEX, rax, &miss); | 2568 masm(), Context::STRING_FUNCTION_INDEX, rax, &miss); |
| 2569 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2580 CheckPrototypes( | 2570 CheckPrototypes( |
| 2581 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2571 IC::CurrentTypeOf(prototype, isolate()), |
| 2582 rax, holder, rbx, rdx, rdi, name, &miss); | 2572 rax, holder, rbx, rdx, rdi, name, &miss); |
| 2583 break; | 2573 break; |
| 2584 | 2574 } |
| 2585 case SYMBOL_CHECK: | 2575 case SYMBOL_CHECK: { |
| 2586 // Check that the object is a symbol. | 2576 // Check that the object is a symbol. |
| 2587 __ CmpObjectType(rdx, SYMBOL_TYPE, rax); | 2577 __ CmpObjectType(rdx, SYMBOL_TYPE, rax); |
| 2588 __ j(not_equal, &miss); | 2578 __ j(not_equal, &miss); |
| 2589 // Check that the maps starting from the prototype haven't changed. | 2579 // Check that the maps starting from the prototype haven't changed. |
| 2590 GenerateDirectLoadGlobalFunctionPrototype( | 2580 GenerateDirectLoadGlobalFunctionPrototype( |
| 2591 masm(), Context::SYMBOL_FUNCTION_INDEX, rax, &miss); | 2581 masm(), Context::SYMBOL_FUNCTION_INDEX, rax, &miss); |
| 2582 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2592 CheckPrototypes( | 2583 CheckPrototypes( |
| 2593 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2584 IC::CurrentTypeOf(prototype, isolate()), |
| 2594 rax, holder, rbx, rdx, rdi, name, &miss); | 2585 rax, holder, rbx, rdx, rdi, name, &miss); |
| 2595 break; | 2586 break; |
| 2596 | 2587 } |
| 2597 case NUMBER_CHECK: { | 2588 case NUMBER_CHECK: { |
| 2598 Label fast; | 2589 Label fast; |
| 2599 // Check that the object is a smi or a heap number. | 2590 // Check that the object is a smi or a heap number. |
| 2600 __ JumpIfSmi(rdx, &fast); | 2591 __ JumpIfSmi(rdx, &fast); |
| 2601 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rax); | 2592 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rax); |
| 2602 __ j(not_equal, &miss); | 2593 __ j(not_equal, &miss); |
| 2603 __ bind(&fast); | 2594 __ bind(&fast); |
| 2604 // Check that the maps starting from the prototype haven't changed. | 2595 // Check that the maps starting from the prototype haven't changed. |
| 2605 GenerateDirectLoadGlobalFunctionPrototype( | 2596 GenerateDirectLoadGlobalFunctionPrototype( |
| 2606 masm(), Context::NUMBER_FUNCTION_INDEX, rax, &miss); | 2597 masm(), Context::NUMBER_FUNCTION_INDEX, rax, &miss); |
| 2598 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2607 CheckPrototypes( | 2599 CheckPrototypes( |
| 2608 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2600 IC::CurrentTypeOf(prototype, isolate()), |
| 2609 rax, holder, rbx, rdx, rdi, name, &miss); | 2601 rax, holder, rbx, rdx, rdi, name, &miss); |
| 2610 break; | 2602 break; |
| 2611 } | 2603 } |
| 2612 case BOOLEAN_CHECK: { | 2604 case BOOLEAN_CHECK: { |
| 2613 GenerateBooleanCheck(rdx, &miss); | 2605 GenerateBooleanCheck(rdx, &miss); |
| 2614 // Check that the maps starting from the prototype haven't changed. | 2606 // Check that the maps starting from the prototype haven't changed. |
| 2615 GenerateDirectLoadGlobalFunctionPrototype( | 2607 GenerateDirectLoadGlobalFunctionPrototype( |
| 2616 masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, &miss); | 2608 masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, &miss); |
| 2609 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2617 CheckPrototypes( | 2610 CheckPrototypes( |
| 2618 Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate()))), | 2611 IC::CurrentTypeOf(prototype, isolate()), |
| 2619 rax, holder, rbx, rdx, rdi, name, &miss); | 2612 rax, holder, rbx, rdx, rdi, name, &miss); |
| 2620 break; | 2613 break; |
| 2621 } | 2614 } |
| 2622 } | 2615 } |
| 2623 | 2616 |
| 2624 Label success; | 2617 Label success; |
| 2625 __ jmp(&success); | 2618 __ jmp(&success); |
| 2626 | 2619 |
| 2627 // Handle call cache miss. | 2620 // Handle call cache miss. |
| 2628 __ bind(&miss); | 2621 __ bind(&miss); |
| (...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3157 // ----------------------------------- | 3150 // ----------------------------------- |
| 3158 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 3151 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 3159 } | 3152 } |
| 3160 | 3153 |
| 3161 | 3154 |
| 3162 #undef __ | 3155 #undef __ |
| 3163 | 3156 |
| 3164 } } // namespace v8::internal | 3157 } } // namespace v8::internal |
| 3165 | 3158 |
| 3166 #endif // V8_TARGET_ARCH_X64 | 3159 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |