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 2215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2226 __ Cmp(FieldOperand(result, HeapObject::kMapOffset), | 2226 __ Cmp(FieldOperand(result, HeapObject::kMapOffset), |
2227 Handle<Map>(JSObject::cast(current)->map())); | 2227 Handle<Map>(JSObject::cast(current)->map())); |
2228 DeoptimizeIf(not_equal, env); | 2228 DeoptimizeIf(not_equal, env); |
2229 current = HeapObject::cast(current->map()->prototype()); | 2229 current = HeapObject::cast(current->map()->prototype()); |
2230 } | 2230 } |
2231 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); | 2231 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); |
2232 } | 2232 } |
2233 } | 2233 } |
2234 | 2234 |
2235 | 2235 |
| 2236 // Check for cases where EmitLoadFieldOrConstantFunction needs to walk the |
| 2237 // prototype chain, which causes unbounded code generation. |
| 2238 static bool CompactEmit( |
| 2239 SmallMapList* list, Handle<String> name, int i, Isolate* isolate) { |
| 2240 LookupResult lookup(isolate); |
| 2241 Handle<Map> map = list->at(i); |
| 2242 map->LookupInDescriptors(NULL, *name, &lookup); |
| 2243 return lookup.IsFound() && |
| 2244 (lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION); |
| 2245 } |
| 2246 |
| 2247 |
2236 void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) { | 2248 void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) { |
2237 Register object = ToRegister(instr->object()); | 2249 Register object = ToRegister(instr->object()); |
2238 Register result = ToRegister(instr->result()); | 2250 Register result = ToRegister(instr->result()); |
2239 | 2251 |
2240 int map_count = instr->hydrogen()->types()->length(); | 2252 int map_count = instr->hydrogen()->types()->length(); |
2241 bool need_generic = instr->hydrogen()->need_generic(); | 2253 bool need_generic = instr->hydrogen()->need_generic(); |
2242 | 2254 |
2243 if (map_count == 0 && !need_generic) { | 2255 if (map_count == 0 && !need_generic) { |
2244 DeoptimizeIf(no_condition, instr->environment()); | 2256 DeoptimizeIf(no_condition, instr->environment()); |
2245 return; | 2257 return; |
2246 } | 2258 } |
2247 Handle<String> name = instr->hydrogen()->name(); | 2259 Handle<String> name = instr->hydrogen()->name(); |
2248 Label done; | 2260 Label done; |
2249 bool compact_code = true; | 2261 bool all_are_compact = true; |
2250 for (int i = 0; i < map_count; ++i) { | 2262 for (int i = 0; i < map_count; ++i) { |
2251 LookupResult lookup(isolate()); | 2263 if (!CompactEmit(instr->hydrogen()->types(), name, i, isolate())) { |
2252 Handle<Map> map = instr->hydrogen()->types()->at(i); | 2264 all_are_compact = false; |
2253 map->LookupInDescriptors(NULL, *name, &lookup); | |
2254 if (!lookup.IsFound() || | |
2255 (lookup.type() != FIELD && lookup.type() != CONSTANT_FUNCTION)) { | |
2256 // The two cases above cause a bounded amount of code to be emitted. This | |
2257 // is not necessarily the case for other lookup results. | |
2258 compact_code = false; | |
2259 break; | 2265 break; |
2260 } | 2266 } |
2261 } | 2267 } |
2262 for (int i = 0; i < map_count; ++i) { | 2268 for (int i = 0; i < map_count; ++i) { |
2263 bool last = (i == map_count - 1); | 2269 bool last = (i == map_count - 1); |
2264 Handle<Map> map = instr->hydrogen()->types()->at(i); | 2270 Handle<Map> map = instr->hydrogen()->types()->at(i); |
2265 Label check_passed; | 2271 Label check_passed; |
2266 __ CompareMap(object, map, &check_passed, ALLOW_ELEMENT_TRANSITION_MAPS); | 2272 __ CompareMap(object, map, &check_passed, ALLOW_ELEMENT_TRANSITION_MAPS); |
2267 if (last && !need_generic) { | 2273 if (last && !need_generic) { |
2268 DeoptimizeIf(not_equal, instr->environment()); | 2274 DeoptimizeIf(not_equal, instr->environment()); |
2269 __ bind(&check_passed); | 2275 __ bind(&check_passed); |
2270 EmitLoadFieldOrConstantFunction( | 2276 EmitLoadFieldOrConstantFunction( |
2271 result, object, map, name, instr->environment()); | 2277 result, object, map, name, instr->environment()); |
2272 } else { | 2278 } else { |
2273 Label next; | 2279 Label next; |
2274 __ j(not_equal, &next, Label::kNear); | 2280 bool compact = all_are_compact ? true : |
| 2281 CompactEmit(instr->hydrogen()->types(), name, i, isolate()); |
| 2282 __ j(not_equal, &next, compact ? Label::kNear : Label::kFar); |
2275 __ bind(&check_passed); | 2283 __ bind(&check_passed); |
2276 EmitLoadFieldOrConstantFunction( | 2284 EmitLoadFieldOrConstantFunction( |
2277 result, object, map, name, instr->environment()); | 2285 result, object, map, name, instr->environment()); |
2278 __ jmp(&done, compact_code ? Label::kNear: Label::kFar); | 2286 __ jmp(&done, all_are_compact ? Label::kNear : Label::kFar); |
2279 __ bind(&next); | 2287 __ bind(&next); |
2280 } | 2288 } |
2281 } | 2289 } |
2282 if (need_generic) { | 2290 if (need_generic) { |
2283 __ Move(rcx, name); | 2291 __ Move(rcx, name); |
2284 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2292 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
2285 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2293 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2286 } | 2294 } |
2287 __ bind(&done); | 2295 __ bind(&done); |
2288 } | 2296 } |
(...skipping 2648 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4937 FixedArray::kHeaderSize - kPointerSize)); | 4945 FixedArray::kHeaderSize - kPointerSize)); |
4938 __ bind(&done); | 4946 __ bind(&done); |
4939 } | 4947 } |
4940 | 4948 |
4941 | 4949 |
4942 #undef __ | 4950 #undef __ |
4943 | 4951 |
4944 } } // namespace v8::internal | 4952 } } // namespace v8::internal |
4945 | 4953 |
4946 #endif // V8_TARGET_ARCH_X64 | 4954 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |