| 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 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 370 | 370 |
| 371 | 371 |
| 372 // Load a fast property out of a holder object (src). In-object properties | 372 // Load a fast property out of a holder object (src). In-object properties |
| 373 // are loaded directly otherwise the property is loaded from the properties | 373 // are loaded directly otherwise the property is loaded from the properties |
| 374 // fixed array. | 374 // fixed array. |
| 375 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, | 375 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, |
| 376 Register dst, | 376 Register dst, |
| 377 Register src, | 377 Register src, |
| 378 Handle<JSObject> holder, | 378 Handle<JSObject> holder, |
| 379 PropertyIndex index) { | 379 PropertyIndex index) { |
| 380 if (index.is_header_index()) { | 380 DoGenerateFastPropertyLoad( |
| 381 int offset = index.header_index() * kPointerSize; | 381 masm, dst, src, index.is_inobject(holder), index.translate(holder)); |
| 382 __ mov(dst, FieldOperand(src, offset)); | |
| 383 } else { | |
| 384 // Adjust for the number of properties stored in the holder. | |
| 385 int slot = index.field_index() - holder->map()->inobject_properties(); | |
| 386 if (slot < 0) { | |
| 387 // Get the property straight out of the holder. | |
| 388 int offset = holder->map()->instance_size() + (slot * kPointerSize); | |
| 389 __ mov(dst, FieldOperand(src, offset)); | |
| 390 } else { | |
| 391 // Calculate the offset into the properties array. | |
| 392 int offset = slot * kPointerSize + FixedArray::kHeaderSize; | |
| 393 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); | |
| 394 __ mov(dst, FieldOperand(dst, offset)); | |
| 395 } | |
| 396 } | |
| 397 } | 382 } |
| 398 | 383 |
| 399 | 384 |
| 385 void StubCompiler::DoGenerateFastPropertyLoad(MacroAssembler* masm, |
| 386 Register dst, |
| 387 Register src, |
| 388 bool inobject, |
| 389 int index) { |
| 390 int offset = index * kPointerSize; |
| 391 if (!inobject) { |
| 392 // Calculate the offset into the properties array. |
| 393 offset = offset + FixedArray::kHeaderSize; |
| 394 __ mov(dst, FieldOperand(src, JSObject::kPropertiesOffset)); |
| 395 src = dst; |
| 396 } |
| 397 __ mov(dst, FieldOperand(src, offset)); |
| 398 } |
| 399 |
| 400 |
| 400 static void PushInterceptorArguments(MacroAssembler* masm, | 401 static void PushInterceptorArguments(MacroAssembler* masm, |
| 401 Register receiver, | 402 Register receiver, |
| 402 Register holder, | 403 Register holder, |
| 403 Register name, | 404 Register name, |
| 404 Handle<JSObject> holder_obj) { | 405 Handle<JSObject> holder_obj) { |
| 405 __ push(name); | 406 __ push(name); |
| 406 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); | 407 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); |
| 407 ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor)); | 408 ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor)); |
| 408 Register scratch = name; | 409 Register scratch = name; |
| 409 __ mov(scratch, Immediate(interceptor)); | 410 __ mov(scratch, Immediate(interceptor)); |
| (...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 937 | 938 |
| 938 | 939 |
| 939 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, | 940 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, |
| 940 Register object_reg, | 941 Register object_reg, |
| 941 Handle<JSObject> holder, | 942 Handle<JSObject> holder, |
| 942 Register holder_reg, | 943 Register holder_reg, |
| 943 Register scratch1, | 944 Register scratch1, |
| 944 Register scratch2, | 945 Register scratch2, |
| 945 Handle<String> name, | 946 Handle<String> name, |
| 946 int save_at_depth, | 947 int save_at_depth, |
| 947 Label* miss) { | 948 Label* miss, |
| 949 PrototypeCheckType check) { |
| 950 Handle<JSObject> first = object; |
| 948 // Make sure there's no overlap between holder and object registers. | 951 // Make sure there's no overlap between holder and object registers. |
| 949 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 952 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
| 950 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 953 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
| 951 && !scratch2.is(scratch1)); | 954 && !scratch2.is(scratch1)); |
| 952 | 955 |
| 953 // Keep track of the current object in register reg. | 956 // Keep track of the current object in register reg. |
| 954 Register reg = object_reg; | 957 Register reg = object_reg; |
| 955 Handle<JSObject> current = object; | 958 Handle<JSObject> current = object; |
| 956 int depth = 0; | 959 int depth = 0; |
| 957 | 960 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 984 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 987 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 985 reg = holder_reg; // From now on the object will be in holder_reg. | 988 reg = holder_reg; // From now on the object will be in holder_reg. |
| 986 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 989 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
| 987 } else { | 990 } else { |
| 988 bool in_new_space = heap()->InNewSpace(*prototype); | 991 bool in_new_space = heap()->InNewSpace(*prototype); |
| 989 Handle<Map> current_map(current->map()); | 992 Handle<Map> current_map(current->map()); |
| 990 if (in_new_space) { | 993 if (in_new_space) { |
| 991 // Save the map in scratch1 for later. | 994 // Save the map in scratch1 for later. |
| 992 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 995 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
| 993 } | 996 } |
| 994 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK, | 997 if (!current.is_identical_to(first) || check == CHECK_ALL_MAPS) { |
| 995 ALLOW_ELEMENT_TRANSITION_MAPS); | 998 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK, |
| 999 ALLOW_ELEMENT_TRANSITION_MAPS); |
| 1000 } |
| 996 | 1001 |
| 997 // Check access rights to the global object. This has to happen after | 1002 // Check access rights to the global object. This has to happen after |
| 998 // the map check so that we know that the object is actually a global | 1003 // the map check so that we know that the object is actually a global |
| 999 // object. | 1004 // object. |
| 1000 if (current->IsJSGlobalProxy()) { | 1005 if (current->IsJSGlobalProxy()) { |
| 1001 __ CheckAccessGlobalProxy(reg, scratch2, miss); | 1006 __ CheckAccessGlobalProxy(reg, scratch2, miss); |
| 1002 } | 1007 } |
| 1003 reg = holder_reg; // From now on the object will be in holder_reg. | 1008 reg = holder_reg; // From now on the object will be in holder_reg. |
| 1004 | 1009 |
| 1005 if (in_new_space) { | 1010 if (in_new_space) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1017 } | 1022 } |
| 1018 | 1023 |
| 1019 // Go to the next object in the prototype chain. | 1024 // Go to the next object in the prototype chain. |
| 1020 current = prototype; | 1025 current = prototype; |
| 1021 } | 1026 } |
| 1022 ASSERT(current.is_identical_to(holder)); | 1027 ASSERT(current.is_identical_to(holder)); |
| 1023 | 1028 |
| 1024 // Log the check depth. | 1029 // Log the check depth. |
| 1025 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 1030 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
| 1026 | 1031 |
| 1027 // Check the holder map. | 1032 if (!holder.is_identical_to(first) || check == CHECK_ALL_MAPS) { |
| 1028 __ CheckMap(reg, Handle<Map>(holder->map()), | 1033 // Check the holder map. |
| 1029 miss, DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); | 1034 __ CheckMap(reg, Handle<Map>(holder->map()), |
| 1035 miss, DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); |
| 1036 } |
| 1030 | 1037 |
| 1031 // Perform security check for access to the global object. | 1038 // Perform security check for access to the global object. |
| 1032 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 1039 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
| 1033 if (holder->IsJSGlobalProxy()) { | 1040 if (holder->IsJSGlobalProxy()) { |
| 1034 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 1041 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
| 1035 } | 1042 } |
| 1036 | 1043 |
| 1037 // If we've skipped any global objects, it's not enough to verify that | 1044 // If we've skipped any global objects, it's not enough to verify that |
| 1038 // their maps haven't changed. We also need to check that the property | 1045 // their maps haven't changed. We also need to check that the property |
| 1039 // cell for the property is still empty. | 1046 // cell for the property is still empty. |
| 1040 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); | 1047 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); |
| 1041 | 1048 |
| 1042 // Return the register containing the holder. | 1049 // Return the register containing the holder. |
| 1043 return reg; | 1050 return reg; |
| 1044 } | 1051 } |
| 1045 | 1052 |
| 1046 | 1053 |
| 1047 void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success, | 1054 void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success, |
| 1048 Label* miss) { | 1055 Label* miss) { |
| 1049 __ jmp(success); | 1056 if (!miss->is_unused()) { |
| 1050 __ bind(miss); | 1057 __ jmp(success); |
| 1051 GenerateLoadMiss(masm(), kind()); | 1058 __ bind(miss); |
| 1059 GenerateLoadMiss(masm(), kind()); |
| 1060 } |
| 1052 } | 1061 } |
| 1053 | 1062 |
| 1054 | 1063 |
| 1055 Register BaseLoadStubCompiler::CallbackHandlerFrontend( | 1064 Register BaseLoadStubCompiler::CallbackHandlerFrontend( |
| 1056 Handle<JSObject> object, | 1065 Handle<JSObject> object, |
| 1057 Register object_reg, | 1066 Register object_reg, |
| 1058 Handle<JSObject> holder, | 1067 Handle<JSObject> holder, |
| 1059 Handle<String> name, | 1068 Handle<String> name, |
| 1060 Label* success, | 1069 Label* success, |
| 1061 FrontendCheckType check, | |
| 1062 Handle<ExecutableAccessorInfo> callback) { | 1070 Handle<ExecutableAccessorInfo> callback) { |
| 1063 Label miss; | 1071 Label miss; |
| 1064 | 1072 |
| 1065 Register reg = HandlerFrontendHeader( | 1073 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); |
| 1066 object, object_reg, holder, name, &miss, check); | |
| 1067 | 1074 |
| 1068 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 1075 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { |
| 1069 ASSERT(!reg.is(scratch2())); | 1076 ASSERT(!reg.is(scratch2())); |
| 1070 ASSERT(!reg.is(scratch3())); | 1077 ASSERT(!reg.is(scratch3())); |
| 1071 Register dictionary = scratch1(); | 1078 Register dictionary = scratch1(); |
| 1072 bool must_preserve_dictionary_reg = reg.is(dictionary); | 1079 bool must_preserve_dictionary_reg = reg.is(dictionary); |
| 1073 | 1080 |
| 1074 // Load the properties dictionary. | 1081 // Load the properties dictionary. |
| 1075 if (must_preserve_dictionary_reg) { | 1082 if (must_preserve_dictionary_reg) { |
| 1076 __ push(dictionary); | 1083 __ push(dictionary); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1115 | 1122 |
| 1116 | 1123 |
| 1117 void BaseLoadStubCompiler::NonexistentHandlerFrontend( | 1124 void BaseLoadStubCompiler::NonexistentHandlerFrontend( |
| 1118 Handle<JSObject> object, | 1125 Handle<JSObject> object, |
| 1119 Handle<JSObject> last, | 1126 Handle<JSObject> last, |
| 1120 Handle<String> name, | 1127 Handle<String> name, |
| 1121 Label* success, | 1128 Label* success, |
| 1122 Handle<GlobalObject> global) { | 1129 Handle<GlobalObject> global) { |
| 1123 Label miss; | 1130 Label miss; |
| 1124 | 1131 |
| 1125 Register reg = HandlerFrontendHeader( | 1132 Register reg = HandlerFrontendHeader(object, receiver(), last, name, &miss); |
| 1126 object, receiver(), last, name, &miss, PERFORM_INITIAL_CHECKS); | |
| 1127 | 1133 |
| 1128 // If the last object in the prototype chain is a global object, | 1134 // If the last object in the prototype chain is a global object, |
| 1129 // check that the global property cell is empty. | 1135 // check that the global property cell is empty. |
| 1130 if (!global.is_null()) { | 1136 if (!global.is_null()) { |
| 1131 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); | 1137 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); |
| 1132 } | 1138 } |
| 1133 | 1139 |
| 1134 if (!last->HasFastProperties()) { | 1140 if (!last->HasFastProperties()) { |
| 1135 __ mov(scratch2(), FieldOperand(reg, HeapObject::kMapOffset)); | 1141 __ mov(scratch2(), FieldOperand(reg, HeapObject::kMapOffset)); |
| 1136 __ mov(scratch2(), FieldOperand(scratch2(), Map::kPrototypeOffset)); | 1142 __ mov(scratch2(), FieldOperand(scratch2(), Map::kPrototypeOffset)); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1155 Register reg, | 1161 Register reg, |
| 1156 Handle<ExecutableAccessorInfo> callback) { | 1162 Handle<ExecutableAccessorInfo> callback) { |
| 1157 // Insert additional parameters into the stack frame above return address. | 1163 // Insert additional parameters into the stack frame above return address. |
| 1158 ASSERT(!scratch3().is(reg)); | 1164 ASSERT(!scratch3().is(reg)); |
| 1159 __ pop(scratch3()); // Get return address to place it below. | 1165 __ pop(scratch3()); // Get return address to place it below. |
| 1160 | 1166 |
| 1161 __ push(receiver()); // receiver | 1167 __ push(receiver()); // receiver |
| 1162 __ mov(scratch2(), esp); | 1168 __ mov(scratch2(), esp); |
| 1163 ASSERT(!scratch2().is(reg)); | 1169 ASSERT(!scratch2().is(reg)); |
| 1164 __ push(reg); // holder | 1170 __ push(reg); // holder |
| 1165 // Push data from AccessorInfo. | 1171 // Push data from ExecutableAccessorInfo. |
| 1166 if (isolate()->heap()->InNewSpace(callback->data())) { | 1172 if (isolate()->heap()->InNewSpace(callback->data())) { |
| 1167 __ mov(scratch1(), Immediate(callback)); | 1173 __ mov(scratch1(), Immediate(callback)); |
| 1168 __ push(FieldOperand(scratch1(), ExecutableAccessorInfo::kDataOffset)); | 1174 __ push(FieldOperand(scratch1(), ExecutableAccessorInfo::kDataOffset)); |
| 1169 } else { | 1175 } else { |
| 1170 __ push(Immediate(Handle<Object>(callback->data(), isolate()))); | 1176 __ push(Immediate(Handle<Object>(callback->data(), isolate()))); |
| 1171 } | 1177 } |
| 1172 __ push(Immediate(reinterpret_cast<int>(isolate()))); | 1178 __ push(Immediate(reinterpret_cast<int>(isolate()))); |
| 1173 | 1179 |
| 1174 // Save a pointer to where we pushed the arguments pointer. | 1180 // Save a pointer to where we pushed the arguments pointer. This will be |
| 1175 // This will be passed as the const AccessorInfo& to the C++ callback. | 1181 // passed as the const ExecutableAccessorInfo& to the C++ callback. |
| 1176 __ push(scratch2()); | 1182 __ push(scratch2()); |
| 1177 | 1183 |
| 1178 __ push(name()); // name | 1184 __ push(name()); // name |
| 1179 __ mov(ebx, esp); // esp points to reference to name (handler). | 1185 __ mov(ebx, esp); // esp points to reference to name (handler). |
| 1180 | 1186 |
| 1181 __ push(scratch3()); // Restore return address. | 1187 __ push(scratch3()); // Restore return address. |
| 1182 | 1188 |
| 1183 // 4 elements array for v8::Arguments::values_, handler for name and pointer | 1189 // 4 elements array for v8::Arguments::values_, handler for name and pointer |
| 1184 // to the values (it considered as smi in GC). | 1190 // to the values (it considered as smi in GC). |
| 1185 const int kStackSpace = 6; | 1191 const int kStackSpace = 6; |
| (...skipping 1734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2920 | 2926 |
| 2921 NonexistentHandlerFrontend(object, last, name, &success, global); | 2927 NonexistentHandlerFrontend(object, last, name, &success, global); |
| 2922 | 2928 |
| 2923 __ bind(&success); | 2929 __ bind(&success); |
| 2924 // Return undefined if maps of the full prototype chain are still the | 2930 // Return undefined if maps of the full prototype chain are still the |
| 2925 // same and no global property with this name contains a value. | 2931 // same and no global property with this name contains a value. |
| 2926 __ mov(eax, isolate()->factory()->undefined_value()); | 2932 __ mov(eax, isolate()->factory()->undefined_value()); |
| 2927 __ ret(0); | 2933 __ ret(0); |
| 2928 | 2934 |
| 2929 // Return the generated code. | 2935 // Return the generated code. |
| 2930 return GetCode(Code::NONEXISTENT, factory()->empty_string()); | 2936 return GetCode(Code::HANDLER_FRAGMENT, Code::NONEXISTENT, name); |
| 2931 } | 2937 } |
| 2932 | 2938 |
| 2933 | 2939 |
| 2934 Register* LoadStubCompiler::registers() { | 2940 Register* LoadStubCompiler::registers() { |
| 2935 // receiver, name, scratch1, scratch2, scratch3, scratch4. | 2941 // receiver, name, scratch1, scratch2, scratch3, scratch4. |
| 2936 static Register registers[] = { edx, ecx, ebx, eax, edi, no_reg }; | 2942 static Register registers[] = { edx, ecx, ebx, eax, edi, no_reg }; |
| 2937 return registers; | 2943 return registers; |
| 2938 } | 2944 } |
| 2939 | 2945 |
| 2940 | 2946 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2991 | 2997 |
| 2992 | 2998 |
| 2993 Handle<Code> LoadStubCompiler::CompileLoadGlobal( | 2999 Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
| 2994 Handle<JSObject> object, | 3000 Handle<JSObject> object, |
| 2995 Handle<GlobalObject> global, | 3001 Handle<GlobalObject> global, |
| 2996 Handle<JSGlobalPropertyCell> cell, | 3002 Handle<JSGlobalPropertyCell> cell, |
| 2997 Handle<String> name, | 3003 Handle<String> name, |
| 2998 bool is_dont_delete) { | 3004 bool is_dont_delete) { |
| 2999 Label success, miss; | 3005 Label success, miss; |
| 3000 | 3006 |
| 3001 HandlerFrontendHeader(object, receiver(), Handle<JSObject>::cast(global), | 3007 __ CheckMap(receiver(), Handle<Map>(object->map()), &miss, DO_SMI_CHECK); |
| 3002 name, &miss, PERFORM_INITIAL_CHECKS); | 3008 HandlerFrontendHeader( |
| 3009 object, receiver(), Handle<JSObject>::cast(global), name, &miss); |
| 3003 // Get the value from the cell. | 3010 // Get the value from the cell. |
| 3004 if (Serializer::enabled()) { | 3011 if (Serializer::enabled()) { |
| 3005 __ mov(eax, Immediate(cell)); | 3012 __ mov(eax, Immediate(cell)); |
| 3006 __ mov(eax, FieldOperand(eax, JSGlobalPropertyCell::kValueOffset)); | 3013 __ mov(eax, FieldOperand(eax, JSGlobalPropertyCell::kValueOffset)); |
| 3007 } else { | 3014 } else { |
| 3008 __ mov(eax, Operand::Cell(cell)); | 3015 __ mov(eax, Operand::Cell(cell)); |
| 3009 } | 3016 } |
| 3010 | 3017 |
| 3011 // Check for deleted property if property can actually be deleted. | 3018 // Check for deleted property if property can actually be deleted. |
| 3012 if (!is_dont_delete) { | 3019 if (!is_dont_delete) { |
| 3013 __ cmp(eax, factory()->the_hole_value()); | 3020 __ cmp(eax, factory()->the_hole_value()); |
| 3014 __ j(equal, &miss); | 3021 __ j(equal, &miss); |
| 3015 } else if (FLAG_debug_code) { | 3022 } else if (FLAG_debug_code) { |
| 3016 __ cmp(eax, factory()->the_hole_value()); | 3023 __ cmp(eax, factory()->the_hole_value()); |
| 3017 __ Check(not_equal, "DontDelete cells can't contain the hole"); | 3024 __ Check(not_equal, "DontDelete cells can't contain the hole"); |
| 3018 } | 3025 } |
| 3019 | 3026 |
| 3020 HandlerFrontendFooter(&success, &miss); | 3027 HandlerFrontendFooter(&success, &miss); |
| 3021 __ bind(&success); | 3028 __ bind(&success); |
| 3022 | 3029 |
| 3023 Counters* counters = isolate()->counters(); | 3030 Counters* counters = isolate()->counters(); |
| 3024 __ IncrementCounter(counters->named_load_global_stub(), 1); | 3031 __ IncrementCounter(counters->named_load_global_stub(), 1); |
| 3025 // The code above already loads the result into the return register. | 3032 // The code above already loads the result into the return register. |
| 3026 __ ret(0); | 3033 __ ret(0); |
| 3027 | 3034 |
| 3028 // Return the generated code. | 3035 // Return the generated code. |
| 3029 return GetCode(Code::NORMAL, name); | 3036 return GetCode(Code::IC_FRAGMENT, Code::NORMAL, name); |
| 3030 } | 3037 } |
| 3031 | 3038 |
| 3032 | 3039 |
| 3033 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( | 3040 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( |
| 3034 Handle<Map> receiver_map) { | 3041 Handle<Map> receiver_map) { |
| 3035 // ----------- S t a t e ------------- | 3042 // ----------- S t a t e ------------- |
| 3036 // -- ecx : key | 3043 // -- ecx : key |
| 3037 // -- edx : receiver | 3044 // -- edx : receiver |
| 3038 // -- esp[0] : return address | 3045 // -- esp[0] : return address |
| 3039 // ----------------------------------- | 3046 // ----------------------------------- |
| 3040 | 3047 |
| 3041 ElementsKind elements_kind = receiver_map->elements_kind(); | 3048 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 3042 if (receiver_map->has_fast_elements() || | 3049 if (receiver_map->has_fast_elements() || |
| 3043 receiver_map->has_external_array_elements()) { | 3050 receiver_map->has_external_array_elements()) { |
| 3044 Handle<Code> stub = KeyedLoadFastElementStub( | 3051 Handle<Code> stub = KeyedLoadFastElementStub( |
| 3045 receiver_map->instance_type() == JS_ARRAY_TYPE, | 3052 receiver_map->instance_type() == JS_ARRAY_TYPE, |
| 3046 elements_kind).GetCode(isolate()); | 3053 elements_kind).GetCode(isolate()); |
| 3047 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); | 3054 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); |
| 3048 } else { | 3055 } else { |
| 3049 Handle<Code> stub = | 3056 Handle<Code> stub = |
| 3050 KeyedLoadDictionaryElementStub().GetCode(isolate()); | 3057 KeyedLoadDictionaryElementStub().GetCode(isolate()); |
| 3051 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); | 3058 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); |
| 3052 } | 3059 } |
| 3053 | 3060 |
| 3054 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3061 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3055 | 3062 |
| 3056 // Return the generated code. | 3063 // Return the generated code. |
| 3057 return GetCode(Code::NORMAL, factory()->empty_string()); | 3064 return GetCode(Code::IC_FRAGMENT, Code::NORMAL, factory()->empty_string()); |
| 3058 } | 3065 } |
| 3059 | 3066 |
| 3060 | 3067 |
| 3061 Handle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( | 3068 Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC( |
| 3062 MapHandleList* receiver_maps, | 3069 MapHandleList* receiver_maps, |
| 3063 CodeHandleList* handler_ics) { | 3070 CodeHandleList* handlers, |
| 3064 // ----------- S t a t e ------------- | 3071 Handle<String> name, |
| 3065 // -- ecx : key | 3072 Code::StubType type, |
| 3066 // -- edx : receiver | 3073 IcCheckType check) { |
| 3067 // -- esp[0] : return address | |
| 3068 // ----------------------------------- | |
| 3069 Label miss; | 3074 Label miss; |
| 3070 __ JumpIfSmi(edx, &miss); | |
| 3071 | 3075 |
| 3072 Register map_reg = ebx; | 3076 if (check == PROPERTY) { |
| 3073 __ mov(map_reg, FieldOperand(edx, HeapObject::kMapOffset)); | 3077 GenerateNameCheck(name, this->name(), &miss); |
| 3078 } |
| 3079 |
| 3080 __ JumpIfSmi(receiver(), &miss); |
| 3081 Register map_reg = scratch1(); |
| 3082 __ mov(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); |
| 3074 int receiver_count = receiver_maps->length(); | 3083 int receiver_count = receiver_maps->length(); |
| 3075 for (int current = 0; current < receiver_count; ++current) { | 3084 for (int current = 0; current < receiver_count; ++current) { |
| 3076 __ cmp(map_reg, receiver_maps->at(current)); | 3085 __ cmp(map_reg, receiver_maps->at(current)); |
| 3077 __ j(equal, handler_ics->at(current)); | 3086 __ j(equal, handlers->at(current)); |
| 3078 } | 3087 } |
| 3079 | 3088 |
| 3080 __ bind(&miss); | 3089 __ bind(&miss); |
| 3081 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3090 GenerateLoadMiss(masm(), kind()); |
| 3082 | 3091 |
| 3083 // Return the generated code. | 3092 // Return the generated code. |
| 3084 return GetCode(Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | 3093 InlineCacheState state = |
| 3094 receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC; |
| 3095 return GetCode(Code::IC_FRAGMENT, type, name, state); |
| 3085 } | 3096 } |
| 3086 | 3097 |
| 3087 | 3098 |
| 3088 // Specialized stub for constructing objects from functions which only have only | 3099 // Specialized stub for constructing objects from functions which only have only |
| 3089 // simple assignments of the form this.x = ...; in their body. | 3100 // simple assignments of the form this.x = ...; in their body. |
| 3090 Handle<Code> ConstructStubCompiler::CompileConstructStub( | 3101 Handle<Code> ConstructStubCompiler::CompileConstructStub( |
| 3091 Handle<JSFunction> function) { | 3102 Handle<JSFunction> function) { |
| 3092 // ----------- S t a t e ------------- | 3103 // ----------- S t a t e ------------- |
| 3093 // -- eax : argc | 3104 // -- eax : argc |
| 3094 // -- edi : constructor | 3105 // -- edi : constructor |
| (...skipping 707 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3802 __ jmp(ic_slow, RelocInfo::CODE_TARGET); | 3813 __ jmp(ic_slow, RelocInfo::CODE_TARGET); |
| 3803 } | 3814 } |
| 3804 } | 3815 } |
| 3805 | 3816 |
| 3806 | 3817 |
| 3807 #undef __ | 3818 #undef __ |
| 3808 | 3819 |
| 3809 } } // namespace v8::internal | 3820 } } // namespace v8::internal |
| 3810 | 3821 |
| 3811 #endif // V8_TARGET_ARCH_IA32 | 3822 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |