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 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
929 miss); | 930 miss); |
930 } | 931 } |
931 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); | 932 current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); |
932 } | 933 } |
933 } | 934 } |
934 | 935 |
935 #undef __ | 936 #undef __ |
936 #define __ ACCESS_MASM(masm()) | 937 #define __ ACCESS_MASM(masm()) |
937 | 938 |
938 | 939 |
| 940 void StubCompiler::GenerateTailCall(Handle<Code> code) { |
| 941 __ jmp(code, RelocInfo::CODE_TARGET); |
| 942 } |
| 943 |
| 944 |
939 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, | 945 Register StubCompiler::CheckPrototypes(Handle<JSObject> object, |
940 Register object_reg, | 946 Register object_reg, |
941 Handle<JSObject> holder, | 947 Handle<JSObject> holder, |
942 Register holder_reg, | 948 Register holder_reg, |
943 Register scratch1, | 949 Register scratch1, |
944 Register scratch2, | 950 Register scratch2, |
945 Handle<String> name, | 951 Handle<String> name, |
946 int save_at_depth, | 952 int save_at_depth, |
947 Label* miss) { | 953 Label* miss, |
| 954 PrototypeCheckType check) { |
| 955 Handle<JSObject> first = object; |
948 // Make sure there's no overlap between holder and object registers. | 956 // Make sure there's no overlap between holder and object registers. |
949 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 957 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
950 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 958 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
951 && !scratch2.is(scratch1)); | 959 && !scratch2.is(scratch1)); |
952 | 960 |
953 // Keep track of the current object in register reg. | 961 // Keep track of the current object in register reg. |
954 Register reg = object_reg; | 962 Register reg = object_reg; |
955 Handle<JSObject> current = object; | 963 Handle<JSObject> current = object; |
956 int depth = 0; | 964 int depth = 0; |
957 | 965 |
(...skipping 26 matching lines...) Expand all Loading... |
984 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 992 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
985 reg = holder_reg; // From now on the object will be in holder_reg. | 993 reg = holder_reg; // From now on the object will be in holder_reg. |
986 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 994 __ mov(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
987 } else { | 995 } else { |
988 bool in_new_space = heap()->InNewSpace(*prototype); | 996 bool in_new_space = heap()->InNewSpace(*prototype); |
989 Handle<Map> current_map(current->map()); | 997 Handle<Map> current_map(current->map()); |
990 if (in_new_space) { | 998 if (in_new_space) { |
991 // Save the map in scratch1 for later. | 999 // Save the map in scratch1 for later. |
992 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 1000 __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
993 } | 1001 } |
994 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK, | 1002 if (!current.is_identical_to(first) || check == CHECK_ALL_MAPS) { |
995 ALLOW_ELEMENT_TRANSITION_MAPS); | 1003 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK, |
| 1004 ALLOW_ELEMENT_TRANSITION_MAPS); |
| 1005 } |
996 | 1006 |
997 // Check access rights to the global object. This has to happen after | 1007 // 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 | 1008 // the map check so that we know that the object is actually a global |
999 // object. | 1009 // object. |
1000 if (current->IsJSGlobalProxy()) { | 1010 if (current->IsJSGlobalProxy()) { |
1001 __ CheckAccessGlobalProxy(reg, scratch2, miss); | 1011 __ CheckAccessGlobalProxy(reg, scratch2, miss); |
1002 } | 1012 } |
1003 reg = holder_reg; // From now on the object will be in holder_reg. | 1013 reg = holder_reg; // From now on the object will be in holder_reg. |
1004 | 1014 |
1005 if (in_new_space) { | 1015 if (in_new_space) { |
(...skipping 11 matching lines...) Expand all Loading... |
1017 } | 1027 } |
1018 | 1028 |
1019 // Go to the next object in the prototype chain. | 1029 // Go to the next object in the prototype chain. |
1020 current = prototype; | 1030 current = prototype; |
1021 } | 1031 } |
1022 ASSERT(current.is_identical_to(holder)); | 1032 ASSERT(current.is_identical_to(holder)); |
1023 | 1033 |
1024 // Log the check depth. | 1034 // Log the check depth. |
1025 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 1035 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
1026 | 1036 |
1027 // Check the holder map. | 1037 if (!holder.is_identical_to(first) || check == CHECK_ALL_MAPS) { |
1028 __ CheckMap(reg, Handle<Map>(holder->map()), | 1038 // Check the holder map. |
1029 miss, DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); | 1039 __ CheckMap(reg, Handle<Map>(holder->map()), |
| 1040 miss, DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); |
| 1041 } |
1030 | 1042 |
1031 // Perform security check for access to the global object. | 1043 // Perform security check for access to the global object. |
1032 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); | 1044 ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); |
1033 if (holder->IsJSGlobalProxy()) { | 1045 if (holder->IsJSGlobalProxy()) { |
1034 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 1046 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
1035 } | 1047 } |
1036 | 1048 |
1037 // If we've skipped any global objects, it's not enough to verify that | 1049 // 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 | 1050 // their maps haven't changed. We also need to check that the property |
1039 // cell for the property is still empty. | 1051 // cell for the property is still empty. |
1040 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); | 1052 GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); |
1041 | 1053 |
1042 // Return the register containing the holder. | 1054 // Return the register containing the holder. |
1043 return reg; | 1055 return reg; |
1044 } | 1056 } |
1045 | 1057 |
1046 | 1058 |
1047 void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success, | 1059 void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success, |
1048 Label* miss) { | 1060 Label* miss) { |
1049 __ jmp(success); | 1061 if (!miss->is_unused()) { |
1050 __ bind(miss); | 1062 __ jmp(success); |
1051 GenerateLoadMiss(masm(), kind()); | 1063 __ bind(miss); |
| 1064 GenerateLoadMiss(masm(), kind()); |
| 1065 } |
1052 } | 1066 } |
1053 | 1067 |
1054 | 1068 |
1055 Register BaseLoadStubCompiler::CallbackHandlerFrontend( | 1069 Register BaseLoadStubCompiler::CallbackHandlerFrontend( |
1056 Handle<JSObject> object, | 1070 Handle<JSObject> object, |
1057 Register object_reg, | 1071 Register object_reg, |
1058 Handle<JSObject> holder, | 1072 Handle<JSObject> holder, |
1059 Handle<String> name, | 1073 Handle<String> name, |
1060 Label* success, | 1074 Label* success, |
1061 FrontendCheckType check, | |
1062 Handle<ExecutableAccessorInfo> callback) { | 1075 Handle<ExecutableAccessorInfo> callback) { |
1063 Label miss; | 1076 Label miss; |
1064 | 1077 |
1065 Register reg = HandlerFrontendHeader( | 1078 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); |
1066 object, object_reg, holder, name, &miss, check); | |
1067 | 1079 |
1068 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 1080 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { |
1069 ASSERT(!reg.is(scratch2())); | 1081 ASSERT(!reg.is(scratch2())); |
1070 ASSERT(!reg.is(scratch3())); | 1082 ASSERT(!reg.is(scratch3())); |
1071 Register dictionary = scratch1(); | 1083 Register dictionary = scratch1(); |
1072 bool must_preserve_dictionary_reg = reg.is(dictionary); | 1084 bool must_preserve_dictionary_reg = reg.is(dictionary); |
1073 | 1085 |
1074 // Load the properties dictionary. | 1086 // Load the properties dictionary. |
1075 if (must_preserve_dictionary_reg) { | 1087 if (must_preserve_dictionary_reg) { |
1076 __ push(dictionary); | 1088 __ push(dictionary); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1115 | 1127 |
1116 | 1128 |
1117 void BaseLoadStubCompiler::NonexistentHandlerFrontend( | 1129 void BaseLoadStubCompiler::NonexistentHandlerFrontend( |
1118 Handle<JSObject> object, | 1130 Handle<JSObject> object, |
1119 Handle<JSObject> last, | 1131 Handle<JSObject> last, |
1120 Handle<String> name, | 1132 Handle<String> name, |
1121 Label* success, | 1133 Label* success, |
1122 Handle<GlobalObject> global) { | 1134 Handle<GlobalObject> global) { |
1123 Label miss; | 1135 Label miss; |
1124 | 1136 |
1125 Register reg = HandlerFrontendHeader( | 1137 Register reg = HandlerFrontendHeader(object, receiver(), last, name, &miss); |
1126 object, receiver(), last, name, &miss, PERFORM_INITIAL_CHECKS); | |
1127 | 1138 |
1128 // If the last object in the prototype chain is a global object, | 1139 // If the last object in the prototype chain is a global object, |
1129 // check that the global property cell is empty. | 1140 // check that the global property cell is empty. |
1130 if (!global.is_null()) { | 1141 if (!global.is_null()) { |
1131 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); | 1142 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); |
1132 } | 1143 } |
1133 | 1144 |
1134 if (!last->HasFastProperties()) { | 1145 if (!last->HasFastProperties()) { |
1135 __ mov(scratch2(), FieldOperand(reg, HeapObject::kMapOffset)); | 1146 __ mov(scratch2(), FieldOperand(reg, HeapObject::kMapOffset)); |
1136 __ mov(scratch2(), FieldOperand(scratch2(), Map::kPrototypeOffset)); | 1147 __ mov(scratch2(), FieldOperand(scratch2(), Map::kPrototypeOffset)); |
(...skipping 18 matching lines...) Expand all Loading... |
1155 Register reg, | 1166 Register reg, |
1156 Handle<ExecutableAccessorInfo> callback) { | 1167 Handle<ExecutableAccessorInfo> callback) { |
1157 // Insert additional parameters into the stack frame above return address. | 1168 // Insert additional parameters into the stack frame above return address. |
1158 ASSERT(!scratch3().is(reg)); | 1169 ASSERT(!scratch3().is(reg)); |
1159 __ pop(scratch3()); // Get return address to place it below. | 1170 __ pop(scratch3()); // Get return address to place it below. |
1160 | 1171 |
1161 __ push(receiver()); // receiver | 1172 __ push(receiver()); // receiver |
1162 __ mov(scratch2(), esp); | 1173 __ mov(scratch2(), esp); |
1163 ASSERT(!scratch2().is(reg)); | 1174 ASSERT(!scratch2().is(reg)); |
1164 __ push(reg); // holder | 1175 __ push(reg); // holder |
1165 // Push data from AccessorInfo. | 1176 // Push data from ExecutableAccessorInfo. |
1166 if (isolate()->heap()->InNewSpace(callback->data())) { | 1177 if (isolate()->heap()->InNewSpace(callback->data())) { |
1167 __ mov(scratch1(), Immediate(callback)); | 1178 __ mov(scratch1(), Immediate(callback)); |
1168 __ push(FieldOperand(scratch1(), ExecutableAccessorInfo::kDataOffset)); | 1179 __ push(FieldOperand(scratch1(), ExecutableAccessorInfo::kDataOffset)); |
1169 } else { | 1180 } else { |
1170 __ push(Immediate(Handle<Object>(callback->data(), isolate()))); | 1181 __ push(Immediate(Handle<Object>(callback->data(), isolate()))); |
1171 } | 1182 } |
1172 __ push(Immediate(reinterpret_cast<int>(isolate()))); | 1183 __ push(Immediate(reinterpret_cast<int>(isolate()))); |
1173 | 1184 |
1174 // Save a pointer to where we pushed the arguments pointer. | 1185 // 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. | 1186 // passed as the const ExecutableAccessorInfo& to the C++ callback. |
1176 __ push(scratch2()); | 1187 __ push(scratch2()); |
1177 | 1188 |
1178 __ push(name()); // name | 1189 __ push(name()); // name |
1179 __ mov(ebx, esp); // esp points to reference to name (handler). | 1190 __ mov(ebx, esp); // esp points to reference to name (handler). |
1180 | 1191 |
1181 __ push(scratch3()); // Restore return address. | 1192 __ push(scratch3()); // Restore return address. |
1182 | 1193 |
1183 // 4 elements array for v8::Arguments::values_, handler for name and pointer | 1194 // 4 elements array for v8::Arguments::values_, handler for name and pointer |
1184 // to the values (it considered as smi in GC). | 1195 // to the values (it considered as smi in GC). |
1185 const int kStackSpace = 6; | 1196 const int kStackSpace = 6; |
(...skipping 1740 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2926 | 2937 |
2927 NonexistentHandlerFrontend(object, last, name, &success, global); | 2938 NonexistentHandlerFrontend(object, last, name, &success, global); |
2928 | 2939 |
2929 __ bind(&success); | 2940 __ bind(&success); |
2930 // Return undefined if maps of the full prototype chain are still the | 2941 // Return undefined if maps of the full prototype chain are still the |
2931 // same and no global property with this name contains a value. | 2942 // same and no global property with this name contains a value. |
2932 __ mov(eax, isolate()->factory()->undefined_value()); | 2943 __ mov(eax, isolate()->factory()->undefined_value()); |
2933 __ ret(0); | 2944 __ ret(0); |
2934 | 2945 |
2935 // Return the generated code. | 2946 // Return the generated code. |
2936 return GetCode(Code::NONEXISTENT, factory()->empty_string()); | 2947 return GetCode(Code::HANDLER_FRAGMENT, Code::NONEXISTENT, name); |
2937 } | 2948 } |
2938 | 2949 |
2939 | 2950 |
2940 Register* LoadStubCompiler::registers() { | 2951 Register* LoadStubCompiler::registers() { |
2941 // receiver, name, scratch1, scratch2, scratch3, scratch4. | 2952 // receiver, name, scratch1, scratch2, scratch3, scratch4. |
2942 static Register registers[] = { edx, ecx, ebx, eax, edi, no_reg }; | 2953 static Register registers[] = { edx, ecx, ebx, eax, edi, no_reg }; |
2943 return registers; | 2954 return registers; |
2944 } | 2955 } |
2945 | 2956 |
2946 | 2957 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2997 | 3008 |
2998 | 3009 |
2999 Handle<Code> LoadStubCompiler::CompileLoadGlobal( | 3010 Handle<Code> LoadStubCompiler::CompileLoadGlobal( |
3000 Handle<JSObject> object, | 3011 Handle<JSObject> object, |
3001 Handle<GlobalObject> global, | 3012 Handle<GlobalObject> global, |
3002 Handle<JSGlobalPropertyCell> cell, | 3013 Handle<JSGlobalPropertyCell> cell, |
3003 Handle<String> name, | 3014 Handle<String> name, |
3004 bool is_dont_delete) { | 3015 bool is_dont_delete) { |
3005 Label success, miss; | 3016 Label success, miss; |
3006 | 3017 |
3007 HandlerFrontendHeader(object, receiver(), Handle<JSObject>::cast(global), | 3018 __ CheckMap(receiver(), Handle<Map>(object->map()), &miss, DO_SMI_CHECK); |
3008 name, &miss, PERFORM_INITIAL_CHECKS); | 3019 HandlerFrontendHeader( |
| 3020 object, receiver(), Handle<JSObject>::cast(global), name, &miss); |
3009 // Get the value from the cell. | 3021 // Get the value from the cell. |
3010 if (Serializer::enabled()) { | 3022 if (Serializer::enabled()) { |
3011 __ mov(eax, Immediate(cell)); | 3023 __ mov(eax, Immediate(cell)); |
3012 __ mov(eax, FieldOperand(eax, JSGlobalPropertyCell::kValueOffset)); | 3024 __ mov(eax, FieldOperand(eax, JSGlobalPropertyCell::kValueOffset)); |
3013 } else { | 3025 } else { |
3014 __ mov(eax, Operand::Cell(cell)); | 3026 __ mov(eax, Operand::Cell(cell)); |
3015 } | 3027 } |
3016 | 3028 |
3017 // Check for deleted property if property can actually be deleted. | 3029 // Check for deleted property if property can actually be deleted. |
3018 if (!is_dont_delete) { | 3030 if (!is_dont_delete) { |
3019 __ cmp(eax, factory()->the_hole_value()); | 3031 __ cmp(eax, factory()->the_hole_value()); |
3020 __ j(equal, &miss); | 3032 __ j(equal, &miss); |
3021 } else if (FLAG_debug_code) { | 3033 } else if (FLAG_debug_code) { |
3022 __ cmp(eax, factory()->the_hole_value()); | 3034 __ cmp(eax, factory()->the_hole_value()); |
3023 __ Check(not_equal, "DontDelete cells can't contain the hole"); | 3035 __ Check(not_equal, "DontDelete cells can't contain the hole"); |
3024 } | 3036 } |
3025 | 3037 |
3026 HandlerFrontendFooter(&success, &miss); | 3038 HandlerFrontendFooter(&success, &miss); |
3027 __ bind(&success); | 3039 __ bind(&success); |
3028 | 3040 |
3029 Counters* counters = isolate()->counters(); | 3041 Counters* counters = isolate()->counters(); |
3030 __ IncrementCounter(counters->named_load_global_stub(), 1); | 3042 __ IncrementCounter(counters->named_load_global_stub(), 1); |
3031 // The code above already loads the result into the return register. | 3043 // The code above already loads the result into the return register. |
3032 __ ret(0); | 3044 __ ret(0); |
3033 | 3045 |
3034 // Return the generated code. | 3046 // Return the generated code. |
3035 return GetCode(Code::NORMAL, name); | 3047 return GetCode(Code::IC_FRAGMENT, Code::NORMAL, name); |
3036 } | 3048 } |
3037 | 3049 |
3038 | 3050 |
3039 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( | 3051 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( |
3040 Handle<Map> receiver_map) { | 3052 Handle<Map> receiver_map) { |
3041 // ----------- S t a t e ------------- | 3053 // ----------- S t a t e ------------- |
3042 // -- ecx : key | 3054 // -- ecx : key |
3043 // -- edx : receiver | 3055 // -- edx : receiver |
3044 // -- esp[0] : return address | 3056 // -- esp[0] : return address |
3045 // ----------------------------------- | 3057 // ----------------------------------- |
3046 | 3058 |
3047 ElementsKind elements_kind = receiver_map->elements_kind(); | 3059 ElementsKind elements_kind = receiver_map->elements_kind(); |
3048 if (receiver_map->has_fast_elements() || | 3060 if (receiver_map->has_fast_elements() || |
3049 receiver_map->has_external_array_elements()) { | 3061 receiver_map->has_external_array_elements()) { |
3050 Handle<Code> stub = KeyedLoadFastElementStub( | 3062 Handle<Code> stub = KeyedLoadFastElementStub( |
3051 receiver_map->instance_type() == JS_ARRAY_TYPE, | 3063 receiver_map->instance_type() == JS_ARRAY_TYPE, |
3052 elements_kind).GetCode(isolate()); | 3064 elements_kind).GetCode(isolate()); |
3053 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); | 3065 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); |
3054 } else { | 3066 } else { |
3055 Handle<Code> stub = | 3067 Handle<Code> stub = |
3056 KeyedLoadDictionaryElementStub().GetCode(isolate()); | 3068 KeyedLoadDictionaryElementStub().GetCode(isolate()); |
3057 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); | 3069 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); |
3058 } | 3070 } |
3059 | 3071 |
3060 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3072 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3061 | 3073 |
3062 // Return the generated code. | 3074 // Return the generated code. |
3063 return GetCode(Code::NORMAL, factory()->empty_string()); | 3075 return GetCode(Code::IC_FRAGMENT, Code::NORMAL, factory()->empty_string()); |
3064 } | 3076 } |
3065 | 3077 |
3066 | 3078 |
3067 Handle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( | 3079 Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC( |
3068 MapHandleList* receiver_maps, | 3080 MapHandleList* receiver_maps, |
3069 CodeHandleList* handler_ics) { | 3081 CodeHandleList* handlers, |
3070 // ----------- S t a t e ------------- | 3082 Handle<String> name, |
3071 // -- ecx : key | 3083 Code::StubType type, |
3072 // -- edx : receiver | 3084 IcCheckType check) { |
3073 // -- esp[0] : return address | |
3074 // ----------------------------------- | |
3075 Label miss; | 3085 Label miss; |
3076 __ JumpIfSmi(edx, &miss); | |
3077 | 3086 |
3078 Register map_reg = ebx; | 3087 if (check == PROPERTY) { |
3079 __ mov(map_reg, FieldOperand(edx, HeapObject::kMapOffset)); | 3088 GenerateNameCheck(name, this->name(), &miss); |
| 3089 } |
| 3090 |
| 3091 __ JumpIfSmi(receiver(), &miss); |
| 3092 Register map_reg = scratch1(); |
| 3093 __ mov(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); |
3080 int receiver_count = receiver_maps->length(); | 3094 int receiver_count = receiver_maps->length(); |
3081 for (int current = 0; current < receiver_count; ++current) { | 3095 for (int current = 0; current < receiver_count; ++current) { |
3082 __ cmp(map_reg, receiver_maps->at(current)); | 3096 __ cmp(map_reg, receiver_maps->at(current)); |
3083 __ j(equal, handler_ics->at(current)); | 3097 __ j(equal, handlers->at(current)); |
3084 } | 3098 } |
3085 | 3099 |
3086 __ bind(&miss); | 3100 __ bind(&miss); |
3087 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3101 GenerateLoadMiss(masm(), kind()); |
3088 | 3102 |
3089 // Return the generated code. | 3103 // Return the generated code. |
3090 return GetCode(Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | 3104 InlineCacheState state = |
| 3105 receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC; |
| 3106 return GetCode(Code::IC_FRAGMENT, type, name, state); |
3091 } | 3107 } |
3092 | 3108 |
3093 | 3109 |
3094 // Specialized stub for constructing objects from functions which only have only | 3110 // Specialized stub for constructing objects from functions which only have only |
3095 // simple assignments of the form this.x = ...; in their body. | 3111 // simple assignments of the form this.x = ...; in their body. |
3096 Handle<Code> ConstructStubCompiler::CompileConstructStub( | 3112 Handle<Code> ConstructStubCompiler::CompileConstructStub( |
3097 Handle<JSFunction> function) { | 3113 Handle<JSFunction> function) { |
3098 // ----------- S t a t e ------------- | 3114 // ----------- S t a t e ------------- |
3099 // -- eax : argc | 3115 // -- eax : argc |
3100 // -- edi : constructor | 3116 // -- edi : constructor |
(...skipping 707 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3808 __ jmp(ic_slow, RelocInfo::CODE_TARGET); | 3824 __ jmp(ic_slow, RelocInfo::CODE_TARGET); |
3809 } | 3825 } |
3810 } | 3826 } |
3811 | 3827 |
3812 | 3828 |
3813 #undef __ | 3829 #undef __ |
3814 | 3830 |
3815 } } // namespace v8::internal | 3831 } } // namespace v8::internal |
3816 | 3832 |
3817 #endif // V8_TARGET_ARCH_IA32 | 3833 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |