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 2177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2188 } else { | 2188 } else { |
2189 __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); | 2189 __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); |
2190 __ movq(result, FieldOperand(result, instr->hydrogen()->offset())); | 2190 __ movq(result, FieldOperand(result, instr->hydrogen()->offset())); |
2191 } | 2191 } |
2192 } | 2192 } |
2193 | 2193 |
2194 | 2194 |
2195 void LCodeGen::EmitLoadFieldOrConstantFunction(Register result, | 2195 void LCodeGen::EmitLoadFieldOrConstantFunction(Register result, |
2196 Register object, | 2196 Register object, |
2197 Handle<Map> type, | 2197 Handle<Map> type, |
2198 Handle<String> name) { | 2198 Handle<String> name, |
| 2199 LEnvironment* env) { |
2199 LookupResult lookup(isolate()); | 2200 LookupResult lookup(isolate()); |
2200 type->LookupInDescriptors(NULL, *name, &lookup); | 2201 type->LookupInDescriptors(NULL, *name, &lookup); |
2201 ASSERT(lookup.IsFound() && | 2202 ASSERT(lookup.IsFound() || lookup.IsCacheable()); |
2202 (lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION)); | 2203 if (lookup.IsFound() && lookup.type() == FIELD) { |
2203 if (lookup.type() == FIELD) { | |
2204 int index = lookup.GetLocalFieldIndexFromMap(*type); | 2204 int index = lookup.GetLocalFieldIndexFromMap(*type); |
2205 int offset = index * kPointerSize; | 2205 int offset = index * kPointerSize; |
2206 if (index < 0) { | 2206 if (index < 0) { |
2207 // Negative property indices are in-object properties, indexed | 2207 // Negative property indices are in-object properties, indexed |
2208 // from the end of the fixed part of the object. | 2208 // from the end of the fixed part of the object. |
2209 __ movq(result, FieldOperand(object, offset + type->instance_size())); | 2209 __ movq(result, FieldOperand(object, offset + type->instance_size())); |
2210 } else { | 2210 } else { |
2211 // Non-negative property indices are in the properties array. | 2211 // Non-negative property indices are in the properties array. |
2212 __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); | 2212 __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); |
2213 __ movq(result, FieldOperand(result, offset + FixedArray::kHeaderSize)); | 2213 __ movq(result, FieldOperand(result, offset + FixedArray::kHeaderSize)); |
2214 } | 2214 } |
2215 } else { | 2215 } else if (lookup.IsFound() && lookup.type() == CONSTANT_FUNCTION) { |
2216 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*type)); | 2216 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*type)); |
2217 __ LoadHeapObject(result, function); | 2217 __ LoadHeapObject(result, function); |
| 2218 } else { |
| 2219 // Negative lookup. |
| 2220 // Check prototypes. |
| 2221 HeapObject* current = HeapObject::cast((*type)->prototype()); |
| 2222 Heap* heap = type->GetHeap(); |
| 2223 while (current != heap->null_value()) { |
| 2224 Handle<HeapObject> link(current); |
| 2225 __ LoadHeapObject(result, link); |
| 2226 __ Cmp(FieldOperand(result, HeapObject::kMapOffset), |
| 2227 Handle<Map>(JSObject::cast(current)->map())); |
| 2228 DeoptimizeIf(not_equal, env); |
| 2229 current = HeapObject::cast(current->map()->prototype()); |
| 2230 } |
| 2231 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); |
2218 } | 2232 } |
2219 } | 2233 } |
2220 | 2234 |
2221 | 2235 |
2222 void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) { | 2236 void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) { |
2223 Register object = ToRegister(instr->object()); | 2237 Register object = ToRegister(instr->object()); |
2224 Register result = ToRegister(instr->result()); | 2238 Register result = ToRegister(instr->result()); |
2225 | 2239 |
2226 int map_count = instr->hydrogen()->types()->length(); | 2240 int map_count = instr->hydrogen()->types()->length(); |
2227 bool need_generic = instr->hydrogen()->need_generic(); | 2241 bool need_generic = instr->hydrogen()->need_generic(); |
2228 | 2242 |
2229 if (map_count == 0 && !need_generic) { | 2243 if (map_count == 0 && !need_generic) { |
2230 DeoptimizeIf(no_condition, instr->environment()); | 2244 DeoptimizeIf(no_condition, instr->environment()); |
2231 return; | 2245 return; |
2232 } | 2246 } |
2233 Handle<String> name = instr->hydrogen()->name(); | 2247 Handle<String> name = instr->hydrogen()->name(); |
2234 Label done; | 2248 Label done; |
| 2249 bool compact_code = true; |
| 2250 for (int i = 0; i < map_count; ++i) { |
| 2251 LookupResult lookup(isolate()); |
| 2252 Handle<Map> map = instr->hydrogen()->types()->at(i); |
| 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; |
| 2260 } |
| 2261 } |
2235 for (int i = 0; i < map_count; ++i) { | 2262 for (int i = 0; i < map_count; ++i) { |
2236 bool last = (i == map_count - 1); | 2263 bool last = (i == map_count - 1); |
2237 Handle<Map> map = instr->hydrogen()->types()->at(i); | 2264 Handle<Map> map = instr->hydrogen()->types()->at(i); |
2238 __ Cmp(FieldOperand(object, HeapObject::kMapOffset), map); | 2265 Label check_passed; |
| 2266 __ CompareMap(object, map, &check_passed, ALLOW_ELEMENT_TRANSITION_MAPS); |
2239 if (last && !need_generic) { | 2267 if (last && !need_generic) { |
2240 DeoptimizeIf(not_equal, instr->environment()); | 2268 DeoptimizeIf(not_equal, instr->environment()); |
2241 EmitLoadFieldOrConstantFunction(result, object, map, name); | 2269 __ bind(&check_passed); |
| 2270 EmitLoadFieldOrConstantFunction( |
| 2271 result, object, map, name, instr->environment()); |
2242 } else { | 2272 } else { |
2243 Label next; | 2273 Label next; |
2244 __ j(not_equal, &next, Label::kNear); | 2274 __ j(not_equal, &next, Label::kNear); |
2245 EmitLoadFieldOrConstantFunction(result, object, map, name); | 2275 __ bind(&check_passed); |
2246 __ jmp(&done, Label::kNear); | 2276 EmitLoadFieldOrConstantFunction( |
| 2277 result, object, map, name, instr->environment()); |
| 2278 __ jmp(&done, compact_code ? Label::kNear: Label::kFar); |
2247 __ bind(&next); | 2279 __ bind(&next); |
2248 } | 2280 } |
2249 } | 2281 } |
2250 if (need_generic) { | 2282 if (need_generic) { |
2251 __ Move(rcx, name); | 2283 __ Move(rcx, name); |
2252 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2284 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
2253 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2285 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2254 } | 2286 } |
2255 __ bind(&done); | 2287 __ bind(&done); |
2256 } | 2288 } |
(...skipping 2648 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4905 FixedArray::kHeaderSize - kPointerSize)); | 4937 FixedArray::kHeaderSize - kPointerSize)); |
4906 __ bind(&done); | 4938 __ bind(&done); |
4907 } | 4939 } |
4908 | 4940 |
4909 | 4941 |
4910 #undef __ | 4942 #undef __ |
4911 | 4943 |
4912 } } // namespace v8::internal | 4944 } } // namespace v8::internal |
4913 | 4945 |
4914 #endif // V8_TARGET_ARCH_X64 | 4946 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |