| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/api.h" | 7 #include "src/api.h" |
| 8 #include "src/arguments.h" | 8 #include "src/arguments.h" |
| 9 #include "src/ast.h" | 9 #include "src/ast.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 94 } | 94 } |
| 95 int secondary_offset = SecondaryOffset(name, flags, primary_offset); | 95 int secondary_offset = SecondaryOffset(name, flags, primary_offset); |
| 96 Entry* secondary = entry(secondary_, secondary_offset); | 96 Entry* secondary = entry(secondary_, secondary_offset); |
| 97 if (secondary->key == name && secondary->map == map) { | 97 if (secondary->key == name && secondary->map == map) { |
| 98 return secondary->value; | 98 return secondary->value; |
| 99 } | 99 } |
| 100 return NULL; | 100 return NULL; |
| 101 } | 101 } |
| 102 | 102 |
| 103 | 103 |
| 104 Handle<Code> StubCache::FindIC(Handle<Name> name, Handle<Map> stub_holder, | 104 Handle<Code> PropertyICCompiler::Find(Handle<Name> name, |
| 105 Code::Kind kind, ExtraICState extra_state, | 105 Handle<Map> stub_holder, Code::Kind kind, |
| 106 CacheHolderFlag cache_holder) { | 106 ExtraICState extra_state, |
| 107 CacheHolderFlag cache_holder) { |
| 107 Code::Flags flags = Code::ComputeMonomorphicFlags( | 108 Code::Flags flags = Code::ComputeMonomorphicFlags( |
| 108 kind, extra_state, cache_holder); | 109 kind, extra_state, cache_holder); |
| 109 Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), isolate_); | 110 Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), |
| 111 name->GetIsolate()); |
| 110 if (probe->IsCode()) return Handle<Code>::cast(probe); | 112 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 111 return Handle<Code>::null(); | 113 return Handle<Code>::null(); |
| 112 } | 114 } |
| 113 | 115 |
| 114 | 116 |
| 115 Handle<Code> StubCache::FindHandler(Handle<Name> name, Handle<Map> stub_holder, | 117 Handle<Code> PropertyHandlerCompiler::Find(Handle<Name> name, |
| 116 Code::Kind kind, | 118 Handle<Map> stub_holder, |
| 117 CacheHolderFlag cache_holder, | 119 Code::Kind kind, |
| 118 Code::StubType type) { | 120 CacheHolderFlag cache_holder, |
| 121 Code::StubType type) { |
| 119 Code::Flags flags = Code::ComputeHandlerFlags(kind, type, cache_holder); | 122 Code::Flags flags = Code::ComputeHandlerFlags(kind, type, cache_holder); |
| 120 | 123 |
| 121 Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), isolate_); | 124 Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), |
| 125 name->GetIsolate()); |
| 122 if (probe->IsCode()) return Handle<Code>::cast(probe); | 126 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 123 return Handle<Code>::null(); | 127 return Handle<Code>::null(); |
| 124 } | 128 } |
| 125 | 129 |
| 126 | 130 |
| 127 Handle<Code> StubCache::ComputeMonomorphicIC( | 131 Handle<Code> StubCache::ComputeMonomorphicIC( |
| 128 Code::Kind kind, | 132 Code::Kind kind, |
| 129 Handle<Name> name, | 133 Handle<Name> name, |
| 130 Handle<HeapType> type, | 134 Handle<HeapType> type, |
| 131 Handle<Code> handler, | 135 Handle<Code> handler, |
| 132 ExtraICState extra_ic_state) { | 136 ExtraICState extra_ic_state) { |
| 133 CacheHolderFlag flag; | 137 CacheHolderFlag flag; |
| 134 Handle<Map> stub_holder = IC::GetICCacheHolder(*type, isolate(), &flag); | 138 Handle<Map> stub_holder = IC::GetICCacheHolder(*type, isolate(), &flag); |
| 135 | 139 |
| 136 Handle<Code> ic; | 140 Handle<Code> ic; |
| 137 // There are multiple string maps that all use the same prototype. That | 141 // There are multiple string maps that all use the same prototype. That |
| 138 // prototype cannot hold multiple handlers, one for each of the string maps, | 142 // prototype cannot hold multiple handlers, one for each of the string maps, |
| 139 // for a single name. Hence, turn off caching of the IC. | 143 // for a single name. Hence, turn off caching of the IC. |
| 140 bool can_be_cached = !type->Is(HeapType::String()); | 144 bool can_be_cached = !type->Is(HeapType::String()); |
| 141 if (can_be_cached) { | 145 if (can_be_cached) { |
| 142 ic = FindIC(name, stub_holder, kind, extra_ic_state, flag); | 146 ic = |
| 147 PropertyICCompiler::Find(name, stub_holder, kind, extra_ic_state, flag); |
| 143 if (!ic.is_null()) return ic; | 148 if (!ic.is_null()) return ic; |
| 144 } | 149 } |
| 145 | 150 |
| 146 if (kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC) { | 151 #ifdef DEBUG |
| 147 LoadStubCompiler ic_compiler(isolate(), kind, extra_ic_state, flag); | 152 if (kind == Code::KEYED_STORE_IC) { |
| 148 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); | |
| 149 } else if (kind == Code::STORE_IC) { | |
| 150 StoreStubCompiler ic_compiler(isolate(), extra_ic_state); | |
| 151 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); | |
| 152 } else { | |
| 153 ASSERT(kind == Code::KEYED_STORE_IC); | |
| 154 ASSERT(STANDARD_STORE == | 153 ASSERT(STANDARD_STORE == |
| 155 KeyedStoreIC::GetKeyedAccessStoreMode(extra_ic_state)); | 154 KeyedStoreIC::GetKeyedAccessStoreMode(extra_ic_state)); |
| 156 KeyedStoreStubCompiler ic_compiler(isolate(), extra_ic_state); | |
| 157 ic = ic_compiler.CompileMonomorphicIC(type, handler, name); | |
| 158 } | 155 } |
| 156 #endif |
| 157 |
| 158 PropertyICCompiler ic_compiler(isolate(), kind, extra_ic_state, flag); |
| 159 ic = ic_compiler.CompileMonomorphic(type, handler, name, PROPERTY); |
| 159 | 160 |
| 160 if (can_be_cached) Map::UpdateCodeCache(stub_holder, name, ic); | 161 if (can_be_cached) Map::UpdateCodeCache(stub_holder, name, ic); |
| 161 return ic; | 162 return ic; |
| 162 } | 163 } |
| 163 | 164 |
| 164 | 165 |
| 165 Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name, | 166 Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name, |
| 166 Handle<HeapType> type) { | 167 Handle<HeapType> type) { |
| 167 Handle<Map> receiver_map = IC::TypeToMap(*type, isolate()); | 168 Handle<Map> receiver_map = IC::TypeToMap(*type, isolate()); |
| 168 if (receiver_map->prototype()->IsNull()) { | 169 if (receiver_map->prototype()->IsNull()) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 188 Handle<JSObject> last(JSObject::cast(receiver_map->prototype())); | 189 Handle<JSObject> last(JSObject::cast(receiver_map->prototype())); |
| 189 while (true) { | 190 while (true) { |
| 190 if (current_map->is_dictionary_map()) cache_name = name; | 191 if (current_map->is_dictionary_map()) cache_name = name; |
| 191 if (current_map->prototype()->IsNull()) break; | 192 if (current_map->prototype()->IsNull()) break; |
| 192 last = handle(JSObject::cast(current_map->prototype())); | 193 last = handle(JSObject::cast(current_map->prototype())); |
| 193 current_map = handle(last->map()); | 194 current_map = handle(last->map()); |
| 194 } | 195 } |
| 195 // Compile the stub that is either shared for all names or | 196 // Compile the stub that is either shared for all names or |
| 196 // name specific if there are global objects involved. | 197 // name specific if there are global objects involved. |
| 197 Code::Kind handler_kind = Code::LOAD_IC; | 198 Code::Kind handler_kind = Code::LOAD_IC; |
| 198 Handle<Code> handler = | 199 Handle<Code> handler = PropertyHandlerCompiler::Find( |
| 199 FindHandler(cache_name, stub_holder_map, handler_kind, flag, Code::FAST); | 200 cache_name, stub_holder_map, handler_kind, flag, Code::FAST); |
| 200 if (!handler.is_null()) { | 201 if (!handler.is_null()) return handler; |
| 201 return handler; | |
| 202 } | |
| 203 | 202 |
| 204 LoadStubCompiler compiler(isolate_, handler_kind, kNoExtraICState, flag); | 203 NamedLoadHandlerCompiler compiler(isolate_, handler_kind, kNoExtraICState, |
| 204 flag); |
| 205 handler = compiler.CompileLoadNonexistent(type, last, cache_name); | 205 handler = compiler.CompileLoadNonexistent(type, last, cache_name); |
| 206 Map::UpdateCodeCache(stub_holder_map, cache_name, handler); | 206 Map::UpdateCodeCache(stub_holder_map, cache_name, handler); |
| 207 return handler; | 207 return handler; |
| 208 } | 208 } |
| 209 | 209 |
| 210 | 210 |
| 211 Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) { | 211 Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) { |
| 212 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC); | 212 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC); |
| 213 Handle<Name> name = | 213 Handle<Name> name = |
| 214 isolate()->factory()->KeyedLoadElementMonomorphic_string(); | 214 isolate()->factory()->KeyedLoadElementMonomorphic_string(); |
| 215 | 215 |
| 216 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_); | 216 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_); |
| 217 if (probe->IsCode()) return Handle<Code>::cast(probe); | 217 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 218 | 218 |
| 219 KeyedLoadStubCompiler compiler(isolate()); | 219 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 220 Handle<Code> code = compiler.CompileLoadElement(receiver_map); | 220 Handle<Code> stub; |
| 221 if (receiver_map->has_fast_elements() || |
| 222 receiver_map->has_external_array_elements() || |
| 223 receiver_map->has_fixed_typed_array_elements()) { |
| 224 stub = KeyedLoadFastElementStub( |
| 225 isolate(), receiver_map->instance_type() == JS_ARRAY_TYPE, |
| 226 elements_kind).GetCode(); |
| 227 } else { |
| 228 stub = FLAG_compiled_keyed_dictionary_loads |
| 229 ? KeyedLoadDictionaryElementStub(isolate()).GetCode() |
| 230 : KeyedLoadDictionaryElementPlatformStub(isolate()).GetCode(); |
| 231 } |
| 232 PropertyICCompiler compiler(isolate(), Code::KEYED_LOAD_IC); |
| 233 Handle<Code> code = |
| 234 compiler.CompileMonomorphic(HeapType::Class(receiver_map, isolate()), |
| 235 stub, factory()->empty_string(), ELEMENT); |
| 221 | 236 |
| 222 Map::UpdateCodeCache(receiver_map, name, code); | 237 Map::UpdateCodeCache(receiver_map, name, code); |
| 223 return code; | 238 return code; |
| 224 } | 239 } |
| 225 | 240 |
| 226 | 241 |
| 227 Handle<Code> StubCache::ComputeKeyedStoreElement( | 242 Handle<Code> StubCache::ComputeKeyedStoreElement( |
| 228 Handle<Map> receiver_map, | 243 Handle<Map> receiver_map, |
| 229 StrictMode strict_mode, | 244 StrictMode strict_mode, |
| 230 KeyedAccessStoreMode store_mode) { | 245 KeyedAccessStoreMode store_mode) { |
| 231 ExtraICState extra_state = | 246 ExtraICState extra_state = |
| 232 KeyedStoreIC::ComputeExtraICState(strict_mode, store_mode); | 247 KeyedStoreIC::ComputeExtraICState(strict_mode, store_mode); |
| 233 Code::Flags flags = | 248 Code::Flags flags = |
| 234 Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, extra_state); | 249 Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, extra_state); |
| 235 | 250 |
| 236 ASSERT(store_mode == STANDARD_STORE || | 251 ASSERT(store_mode == STANDARD_STORE || |
| 237 store_mode == STORE_AND_GROW_NO_TRANSITION || | 252 store_mode == STORE_AND_GROW_NO_TRANSITION || |
| 238 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || | 253 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || |
| 239 store_mode == STORE_NO_TRANSITION_HANDLE_COW); | 254 store_mode == STORE_NO_TRANSITION_HANDLE_COW); |
| 240 | 255 |
| 241 Handle<String> name = | 256 Handle<String> name = |
| 242 isolate()->factory()->KeyedStoreElementMonomorphic_string(); | 257 isolate()->factory()->KeyedStoreElementMonomorphic_string(); |
| 243 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_); | 258 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_); |
| 244 if (probe->IsCode()) return Handle<Code>::cast(probe); | 259 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 245 | 260 |
| 246 KeyedStoreStubCompiler compiler(isolate(), extra_state); | 261 PropertyICCompiler compiler(isolate(), Code::KEYED_STORE_IC, extra_state); |
| 247 Handle<Code> code = compiler.CompileStoreElement(receiver_map); | 262 Handle<Code> code = |
| 263 compiler.CompileIndexedStoreMonomorphic(receiver_map, store_mode); |
| 248 | 264 |
| 249 Map::UpdateCodeCache(receiver_map, name, code); | 265 Map::UpdateCodeCache(receiver_map, name, code); |
| 250 ASSERT(KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state()) | 266 ASSERT(KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state()) |
| 251 == store_mode); | 267 == store_mode); |
| 252 return code; | 268 return code; |
| 253 } | 269 } |
| 254 | 270 |
| 255 | 271 |
| 256 #define CALL_LOGGER_TAG(kind, type) (Logger::KEYED_##type) | 272 #define CALL_LOGGER_TAG(kind, type) (Logger::KEYED_##type) |
| 257 | 273 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 278 | 294 |
| 279 | 295 |
| 280 Handle<Code> StubCache::ComputeLoad(InlineCacheState ic_state, | 296 Handle<Code> StubCache::ComputeLoad(InlineCacheState ic_state, |
| 281 ExtraICState extra_state) { | 297 ExtraICState extra_state) { |
| 282 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, ic_state, extra_state); | 298 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, ic_state, extra_state); |
| 283 Handle<UnseededNumberDictionary> cache = | 299 Handle<UnseededNumberDictionary> cache = |
| 284 isolate_->factory()->non_monomorphic_cache(); | 300 isolate_->factory()->non_monomorphic_cache(); |
| 285 int entry = cache->FindEntry(isolate_, flags); | 301 int entry = cache->FindEntry(isolate_, flags); |
| 286 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | 302 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); |
| 287 | 303 |
| 288 StubCompiler compiler(isolate_); | 304 PropertyICCompiler compiler(isolate_, Code::LOAD_IC); |
| 289 Handle<Code> code; | 305 Handle<Code> code; |
| 290 if (ic_state == UNINITIALIZED) { | 306 if (ic_state == UNINITIALIZED) { |
| 291 code = compiler.CompileLoadInitialize(flags); | 307 code = compiler.CompileLoadInitialize(flags); |
| 292 } else if (ic_state == PREMONOMORPHIC) { | 308 } else if (ic_state == PREMONOMORPHIC) { |
| 293 code = compiler.CompileLoadPreMonomorphic(flags); | 309 code = compiler.CompileLoadPreMonomorphic(flags); |
| 294 } else if (ic_state == MEGAMORPHIC) { | 310 } else if (ic_state == MEGAMORPHIC) { |
| 295 code = compiler.CompileLoadMegamorphic(flags); | 311 code = compiler.CompileLoadMegamorphic(flags); |
| 296 } else { | 312 } else { |
| 297 UNREACHABLE(); | 313 UNREACHABLE(); |
| 298 } | 314 } |
| 299 FillCache(isolate_, code); | 315 FillCache(isolate_, code); |
| 300 return code; | 316 return code; |
| 301 } | 317 } |
| 302 | 318 |
| 303 | 319 |
| 304 Handle<Code> StubCache::ComputeStore(InlineCacheState ic_state, | 320 Handle<Code> StubCache::ComputeStore(InlineCacheState ic_state, |
| 305 ExtraICState extra_state) { | 321 ExtraICState extra_state) { |
| 306 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, ic_state, extra_state); | 322 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, ic_state, extra_state); |
| 307 Handle<UnseededNumberDictionary> cache = | 323 Handle<UnseededNumberDictionary> cache = |
| 308 isolate_->factory()->non_monomorphic_cache(); | 324 isolate_->factory()->non_monomorphic_cache(); |
| 309 int entry = cache->FindEntry(isolate_, flags); | 325 int entry = cache->FindEntry(isolate_, flags); |
| 310 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | 326 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); |
| 311 | 327 |
| 312 StubCompiler compiler(isolate_); | 328 PropertyICCompiler compiler(isolate_, Code::STORE_IC); |
| 313 Handle<Code> code; | 329 Handle<Code> code; |
| 314 if (ic_state == UNINITIALIZED) { | 330 if (ic_state == UNINITIALIZED) { |
| 315 code = compiler.CompileStoreInitialize(flags); | 331 code = compiler.CompileStoreInitialize(flags); |
| 316 } else if (ic_state == PREMONOMORPHIC) { | 332 } else if (ic_state == PREMONOMORPHIC) { |
| 317 code = compiler.CompileStorePreMonomorphic(flags); | 333 code = compiler.CompileStorePreMonomorphic(flags); |
| 318 } else if (ic_state == GENERIC) { | 334 } else if (ic_state == GENERIC) { |
| 319 code = compiler.CompileStoreGeneric(flags); | 335 code = compiler.CompileStoreGeneric(flags); |
| 320 } else if (ic_state == MEGAMORPHIC) { | 336 } else if (ic_state == MEGAMORPHIC) { |
| 321 code = compiler.CompileStoreMegamorphic(flags); | 337 code = compiler.CompileStoreMegamorphic(flags); |
| 322 } else { | 338 } else { |
| 323 UNREACHABLE(); | 339 UNREACHABLE(); |
| 324 } | 340 } |
| 325 | 341 |
| 326 FillCache(isolate_, code); | 342 FillCache(isolate_, code); |
| 327 return code; | 343 return code; |
| 328 } | 344 } |
| 329 | 345 |
| 330 | 346 |
| 331 Handle<Code> StubCache::ComputeCompareNil(Handle<Map> receiver_map, | 347 Handle<Code> StubCache::ComputeCompareNil(Handle<Map> receiver_map, |
| 332 CompareNilICStub* stub) { | 348 CompareNilICStub* stub) { |
| 333 Handle<String> name(isolate_->heap()->empty_string()); | 349 Handle<String> name(isolate_->heap()->empty_string()); |
| 334 if (!receiver_map->is_shared()) { | 350 if (!receiver_map->is_shared()) { |
| 335 Handle<Code> cached_ic = FindIC(name, receiver_map, Code::COMPARE_NIL_IC, | 351 Handle<Code> cached_ic = PropertyICCompiler::Find( |
| 336 stub->GetExtraICState()); | 352 name, receiver_map, Code::COMPARE_NIL_IC, stub->GetExtraICState()); |
| 337 if (!cached_ic.is_null()) return cached_ic; | 353 if (!cached_ic.is_null()) return cached_ic; |
| 338 } | 354 } |
| 339 | 355 |
| 340 Code::FindAndReplacePattern pattern; | 356 Code::FindAndReplacePattern pattern; |
| 341 pattern.Add(isolate_->factory()->meta_map(), receiver_map); | 357 pattern.Add(isolate_->factory()->meta_map(), receiver_map); |
| 342 Handle<Code> ic = stub->GetCodeCopy(pattern); | 358 Handle<Code> ic = stub->GetCodeCopy(pattern); |
| 343 | 359 |
| 344 if (!receiver_map->is_shared()) { | 360 if (!receiver_map->is_shared()) { |
| 345 Map::UpdateCodeCache(receiver_map, name, ic); | 361 Map::UpdateCodeCache(receiver_map, name, ic); |
| 346 } | 362 } |
| 347 | 363 |
| 348 return ic; | 364 return ic; |
| 349 } | 365 } |
| 350 | 366 |
| 351 | 367 |
| 352 // TODO(verwaest): Change this method so it takes in a TypeHandleList. | 368 // TODO(verwaest): Change this method so it takes in a TypeHandleList. |
| 353 Handle<Code> StubCache::ComputeLoadElementPolymorphic( | 369 Handle<Code> StubCache::ComputeLoadElementPolymorphic( |
| 354 MapHandleList* receiver_maps) { | 370 MapHandleList* receiver_maps) { |
| 355 Code::Flags flags = Code::ComputeFlags(Code::KEYED_LOAD_IC, POLYMORPHIC); | 371 Code::Flags flags = Code::ComputeFlags(Code::KEYED_LOAD_IC, POLYMORPHIC); |
| 356 Handle<PolymorphicCodeCache> cache = | 372 Handle<PolymorphicCodeCache> cache = |
| 357 isolate_->factory()->polymorphic_code_cache(); | 373 isolate_->factory()->polymorphic_code_cache(); |
| 358 Handle<Object> probe = cache->Lookup(receiver_maps, flags); | 374 Handle<Object> probe = cache->Lookup(receiver_maps, flags); |
| 359 if (probe->IsCode()) return Handle<Code>::cast(probe); | 375 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 360 | 376 |
| 361 TypeHandleList types(receiver_maps->length()); | 377 TypeHandleList types(receiver_maps->length()); |
| 362 for (int i = 0; i < receiver_maps->length(); i++) { | 378 for (int i = 0; i < receiver_maps->length(); i++) { |
| 363 types.Add(HeapType::Class(receiver_maps->at(i), isolate())); | 379 types.Add(HeapType::Class(receiver_maps->at(i), isolate())); |
| 364 } | 380 } |
| 365 CodeHandleList handlers(receiver_maps->length()); | 381 CodeHandleList handlers(receiver_maps->length()); |
| 366 KeyedLoadStubCompiler compiler(isolate_); | 382 IndexedHandlerCompiler compiler(isolate_); |
| 367 compiler.CompileElementHandlers(receiver_maps, &handlers); | 383 compiler.CompileElementHandlers(receiver_maps, &handlers); |
| 368 LoadStubCompiler ic_compiler(isolate_, Code::KEYED_LOAD_IC); | 384 PropertyICCompiler ic_compiler(isolate_, Code::KEYED_LOAD_IC); |
| 369 Handle<Code> code = ic_compiler.CompilePolymorphicIC( | 385 Handle<Code> code = ic_compiler.CompilePolymorphic( |
| 370 &types, &handlers, factory()->empty_string(), Code::NORMAL, ELEMENT); | 386 &types, &handlers, factory()->empty_string(), Code::NORMAL, ELEMENT); |
| 371 | 387 |
| 372 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment(); | 388 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment(); |
| 373 | 389 |
| 374 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); | 390 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); |
| 375 return code; | 391 return code; |
| 376 } | 392 } |
| 377 | 393 |
| 378 | 394 |
| 379 Handle<Code> StubCache::ComputePolymorphicIC( | 395 Handle<Code> StubCache::ComputePolymorphicIC( |
| 380 Code::Kind kind, | 396 Code::Kind kind, |
| 381 TypeHandleList* types, | 397 TypeHandleList* types, |
| 382 CodeHandleList* handlers, | 398 CodeHandleList* handlers, |
| 383 int number_of_valid_types, | 399 int number_of_valid_types, |
| 384 Handle<Name> name, | 400 Handle<Name> name, |
| 385 ExtraICState extra_ic_state) { | 401 ExtraICState extra_ic_state) { |
| 386 Handle<Code> handler = handlers->at(0); | 402 Handle<Code> handler = handlers->at(0); |
| 387 Code::StubType type = number_of_valid_types == 1 ? handler->type() | 403 Code::StubType type = number_of_valid_types == 1 ? handler->type() |
| 388 : Code::NORMAL; | 404 : Code::NORMAL; |
| 389 if (kind == Code::LOAD_IC) { | 405 ASSERT(kind == Code::LOAD_IC || kind == Code::STORE_IC); |
| 390 LoadStubCompiler ic_compiler(isolate_, kind, extra_ic_state); | 406 PropertyICCompiler ic_compiler(isolate_, kind, extra_ic_state); |
| 391 return ic_compiler.CompilePolymorphicIC( | 407 return ic_compiler.CompilePolymorphic(types, handlers, name, type, PROPERTY); |
| 392 types, handlers, name, type, PROPERTY); | |
| 393 } else { | |
| 394 ASSERT(kind == Code::STORE_IC); | |
| 395 StoreStubCompiler ic_compiler(isolate_, extra_ic_state); | |
| 396 return ic_compiler.CompilePolymorphicIC( | |
| 397 types, handlers, name, type, PROPERTY); | |
| 398 } | |
| 399 } | 408 } |
| 400 | 409 |
| 401 | 410 |
| 402 Handle<Code> StubCache::ComputeStoreElementPolymorphic( | 411 Handle<Code> StubCache::ComputeStoreElementPolymorphic( |
| 403 MapHandleList* receiver_maps, | 412 MapHandleList* receiver_maps, |
| 404 KeyedAccessStoreMode store_mode, | 413 KeyedAccessStoreMode store_mode, |
| 405 StrictMode strict_mode) { | 414 StrictMode strict_mode) { |
| 406 ASSERT(store_mode == STANDARD_STORE || | 415 ASSERT(store_mode == STANDARD_STORE || |
| 407 store_mode == STORE_AND_GROW_NO_TRANSITION || | 416 store_mode == STORE_AND_GROW_NO_TRANSITION || |
| 408 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || | 417 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || |
| 409 store_mode == STORE_NO_TRANSITION_HANDLE_COW); | 418 store_mode == STORE_NO_TRANSITION_HANDLE_COW); |
| 410 Handle<PolymorphicCodeCache> cache = | 419 Handle<PolymorphicCodeCache> cache = |
| 411 isolate_->factory()->polymorphic_code_cache(); | 420 isolate_->factory()->polymorphic_code_cache(); |
| 412 ExtraICState extra_state = KeyedStoreIC::ComputeExtraICState( | 421 ExtraICState extra_state = KeyedStoreIC::ComputeExtraICState( |
| 413 strict_mode, store_mode); | 422 strict_mode, store_mode); |
| 414 Code::Flags flags = | 423 Code::Flags flags = |
| 415 Code::ComputeFlags(Code::KEYED_STORE_IC, POLYMORPHIC, extra_state); | 424 Code::ComputeFlags(Code::KEYED_STORE_IC, POLYMORPHIC, extra_state); |
| 416 Handle<Object> probe = cache->Lookup(receiver_maps, flags); | 425 Handle<Object> probe = cache->Lookup(receiver_maps, flags); |
| 417 if (probe->IsCode()) return Handle<Code>::cast(probe); | 426 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 418 | 427 |
| 419 KeyedStoreStubCompiler compiler(isolate_, extra_state); | 428 PropertyICCompiler compiler(isolate_, Code::KEYED_STORE_IC, extra_state); |
| 420 Handle<Code> code = compiler.CompileStoreElementPolymorphic(receiver_maps); | 429 Handle<Code> code = |
| 430 compiler.CompileIndexedStorePolymorphic(receiver_maps, store_mode); |
| 421 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); | 431 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); |
| 422 return code; | 432 return code; |
| 423 } | 433 } |
| 424 | 434 |
| 425 | 435 |
| 426 void StubCache::Clear() { | 436 void StubCache::Clear() { |
| 427 Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal); | 437 Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal); |
| 428 for (int i = 0; i < kPrimaryTableSize; i++) { | 438 for (int i = 0; i < kPrimaryTableSize; i++) { |
| 429 primary_[i].key = heap()->empty_string(); | 439 primary_[i].key = heap()->empty_string(); |
| 430 primary_[i].map = NULL; | 440 primary_[i].map = NULL; |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 621 ASSERT(args.smi_at(1) >= 0); | 631 ASSERT(args.smi_at(1) >= 0); |
| 622 uint32_t index = args.smi_at(1); | 632 uint32_t index = args.smi_at(1); |
| 623 Handle<Object> result; | 633 Handle<Object> result; |
| 624 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 634 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 625 isolate, result, | 635 isolate, result, |
| 626 JSObject::GetElementWithInterceptor(receiver, receiver, index)); | 636 JSObject::GetElementWithInterceptor(receiver, receiver, index)); |
| 627 return *result; | 637 return *result; |
| 628 } | 638 } |
| 629 | 639 |
| 630 | 640 |
| 631 Handle<Code> StubCompiler::CompileLoadInitialize(Code::Flags flags) { | 641 Handle<Code> PropertyICCompiler::CompileLoadInitialize(Code::Flags flags) { |
| 632 LoadIC::GenerateInitialize(masm()); | 642 LoadIC::GenerateInitialize(masm()); |
| 633 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadInitialize"); | 643 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadInitialize"); |
| 634 PROFILE(isolate(), | 644 PROFILE(isolate(), |
| 635 CodeCreateEvent(Logger::LOAD_INITIALIZE_TAG, *code, 0)); | 645 CodeCreateEvent(Logger::LOAD_INITIALIZE_TAG, *code, 0)); |
| 636 return code; | 646 return code; |
| 637 } | 647 } |
| 638 | 648 |
| 639 | 649 |
| 640 Handle<Code> StubCompiler::CompileLoadPreMonomorphic(Code::Flags flags) { | 650 Handle<Code> PropertyICCompiler::CompileLoadPreMonomorphic(Code::Flags flags) { |
| 641 LoadIC::GeneratePreMonomorphic(masm()); | 651 LoadIC::GeneratePreMonomorphic(masm()); |
| 642 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadPreMonomorphic"); | 652 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadPreMonomorphic"); |
| 643 PROFILE(isolate(), | 653 PROFILE(isolate(), |
| 644 CodeCreateEvent(Logger::LOAD_PREMONOMORPHIC_TAG, *code, 0)); | 654 CodeCreateEvent(Logger::LOAD_PREMONOMORPHIC_TAG, *code, 0)); |
| 645 return code; | 655 return code; |
| 646 } | 656 } |
| 647 | 657 |
| 648 | 658 |
| 649 Handle<Code> StubCompiler::CompileLoadMegamorphic(Code::Flags flags) { | 659 Handle<Code> PropertyICCompiler::CompileLoadMegamorphic(Code::Flags flags) { |
| 650 LoadIC::GenerateMegamorphic(masm()); | 660 LoadIC::GenerateMegamorphic(masm()); |
| 651 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadMegamorphic"); | 661 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadMegamorphic"); |
| 652 PROFILE(isolate(), | 662 PROFILE(isolate(), |
| 653 CodeCreateEvent(Logger::LOAD_MEGAMORPHIC_TAG, *code, 0)); | 663 CodeCreateEvent(Logger::LOAD_MEGAMORPHIC_TAG, *code, 0)); |
| 654 return code; | 664 return code; |
| 655 } | 665 } |
| 656 | 666 |
| 657 | 667 |
| 658 Handle<Code> StubCompiler::CompileStoreInitialize(Code::Flags flags) { | 668 Handle<Code> PropertyICCompiler::CompileStoreInitialize(Code::Flags flags) { |
| 659 StoreIC::GenerateInitialize(masm()); | 669 StoreIC::GenerateInitialize(masm()); |
| 660 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreInitialize"); | 670 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreInitialize"); |
| 661 PROFILE(isolate(), | 671 PROFILE(isolate(), |
| 662 CodeCreateEvent(Logger::STORE_INITIALIZE_TAG, *code, 0)); | 672 CodeCreateEvent(Logger::STORE_INITIALIZE_TAG, *code, 0)); |
| 663 return code; | 673 return code; |
| 664 } | 674 } |
| 665 | 675 |
| 666 | 676 |
| 667 Handle<Code> StubCompiler::CompileStorePreMonomorphic(Code::Flags flags) { | 677 Handle<Code> PropertyICCompiler::CompileStorePreMonomorphic(Code::Flags flags) { |
| 668 StoreIC::GeneratePreMonomorphic(masm()); | 678 StoreIC::GeneratePreMonomorphic(masm()); |
| 669 Handle<Code> code = GetCodeWithFlags(flags, "CompileStorePreMonomorphic"); | 679 Handle<Code> code = GetCodeWithFlags(flags, "CompileStorePreMonomorphic"); |
| 670 PROFILE(isolate(), | 680 PROFILE(isolate(), |
| 671 CodeCreateEvent(Logger::STORE_PREMONOMORPHIC_TAG, *code, 0)); | 681 CodeCreateEvent(Logger::STORE_PREMONOMORPHIC_TAG, *code, 0)); |
| 672 return code; | 682 return code; |
| 673 } | 683 } |
| 674 | 684 |
| 675 | 685 |
| 676 Handle<Code> StubCompiler::CompileStoreGeneric(Code::Flags flags) { | 686 Handle<Code> PropertyICCompiler::CompileStoreGeneric(Code::Flags flags) { |
| 677 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); | 687 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); |
| 678 StrictMode strict_mode = StoreIC::GetStrictMode(extra_state); | 688 StrictMode strict_mode = StoreIC::GetStrictMode(extra_state); |
| 679 StoreIC::GenerateRuntimeSetProperty(masm(), strict_mode); | 689 StoreIC::GenerateRuntimeSetProperty(masm(), strict_mode); |
| 680 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreGeneric"); | 690 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreGeneric"); |
| 681 PROFILE(isolate(), | 691 PROFILE(isolate(), |
| 682 CodeCreateEvent(Logger::STORE_GENERIC_TAG, *code, 0)); | 692 CodeCreateEvent(Logger::STORE_GENERIC_TAG, *code, 0)); |
| 683 return code; | 693 return code; |
| 684 } | 694 } |
| 685 | 695 |
| 686 | 696 |
| 687 Handle<Code> StubCompiler::CompileStoreMegamorphic(Code::Flags flags) { | 697 Handle<Code> PropertyICCompiler::CompileStoreMegamorphic(Code::Flags flags) { |
| 688 StoreIC::GenerateMegamorphic(masm()); | 698 StoreIC::GenerateMegamorphic(masm()); |
| 689 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreMegamorphic"); | 699 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreMegamorphic"); |
| 690 PROFILE(isolate(), | 700 PROFILE(isolate(), |
| 691 CodeCreateEvent(Logger::STORE_MEGAMORPHIC_TAG, *code, 0)); | 701 CodeCreateEvent(Logger::STORE_MEGAMORPHIC_TAG, *code, 0)); |
| 692 return code; | 702 return code; |
| 693 } | 703 } |
| 694 | 704 |
| 695 | 705 |
| 696 #undef CALL_LOGGER_TAG | 706 #undef CALL_LOGGER_TAG |
| 697 | 707 |
| 698 | 708 |
| 699 Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags, | 709 Handle<Code> PropertyAccessCompiler::GetCodeWithFlags(Code::Flags flags, |
| 700 const char* name) { | 710 const char* name) { |
| 701 // Create code object in the heap. | 711 // Create code object in the heap. |
| 702 CodeDesc desc; | 712 CodeDesc desc; |
| 703 masm_.GetCode(&desc); | 713 masm()->GetCode(&desc); |
| 704 Handle<Code> code = factory()->NewCode(desc, flags, masm_.CodeObject()); | 714 Handle<Code> code = factory()->NewCode(desc, flags, masm()->CodeObject()); |
| 705 if (code->IsCodeStubOrIC()) code->set_stub_key(CodeStub::NoCacheKey()); | 715 if (code->IsCodeStubOrIC()) code->set_stub_key(CodeStub::NoCacheKey()); |
| 706 #ifdef ENABLE_DISASSEMBLER | 716 #ifdef ENABLE_DISASSEMBLER |
| 707 if (FLAG_print_code_stubs) { | 717 if (FLAG_print_code_stubs) { |
| 708 OFStream os(stdout); | 718 OFStream os(stdout); |
| 709 code->Disassemble(name, os); | 719 code->Disassemble(name, os); |
| 710 } | 720 } |
| 711 #endif | 721 #endif |
| 712 return code; | 722 return code; |
| 713 } | 723 } |
| 714 | 724 |
| 715 | 725 |
| 716 Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags, | 726 Handle<Code> PropertyAccessCompiler::GetCodeWithFlags(Code::Flags flags, |
| 717 Handle<Name> name) { | 727 Handle<Name> name) { |
| 718 return (FLAG_print_code_stubs && !name.is_null() && name->IsString()) | 728 return (FLAG_print_code_stubs && !name.is_null() && name->IsString()) |
| 719 ? GetCodeWithFlags(flags, Handle<String>::cast(name)->ToCString().get()) | 729 ? GetCodeWithFlags(flags, Handle<String>::cast(name)->ToCString().get()) |
| 720 : GetCodeWithFlags(flags, NULL); | 730 : GetCodeWithFlags(flags, NULL); |
| 721 } | 731 } |
| 722 | 732 |
| 723 | 733 |
| 724 void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder, | |
| 725 Handle<Name> name, | |
| 726 LookupResult* lookup) { | |
| 727 holder->LookupOwnRealNamedProperty(name, lookup); | |
| 728 if (lookup->IsFound()) return; | |
| 729 PrototypeIterator iter(holder->GetIsolate(), holder); | |
| 730 if (iter.IsAtEnd()) return; | |
| 731 PrototypeIterator::GetCurrent(iter)->Lookup(name, lookup); | |
| 732 } | |
| 733 | |
| 734 | |
| 735 #define __ ACCESS_MASM(masm()) | 734 #define __ ACCESS_MASM(masm()) |
| 736 | 735 |
| 737 | 736 |
| 738 Register LoadStubCompiler::HandlerFrontendHeader( | 737 Register NamedLoadHandlerCompiler::FrontendHeader(Handle<HeapType> type, |
| 739 Handle<HeapType> type, | 738 Register object_reg, |
| 740 Register object_reg, | 739 Handle<JSObject> holder, |
| 741 Handle<JSObject> holder, | 740 Handle<Name> name, |
| 742 Handle<Name> name, | 741 Label* miss) { |
| 743 Label* miss) { | |
| 744 PrototypeCheckType check_type = CHECK_ALL_MAPS; | 742 PrototypeCheckType check_type = CHECK_ALL_MAPS; |
| 745 int function_index = -1; | 743 int function_index = -1; |
| 746 if (type->Is(HeapType::String())) { | 744 if (type->Is(HeapType::String())) { |
| 747 function_index = Context::STRING_FUNCTION_INDEX; | 745 function_index = Context::STRING_FUNCTION_INDEX; |
| 748 } else if (type->Is(HeapType::Symbol())) { | 746 } else if (type->Is(HeapType::Symbol())) { |
| 749 function_index = Context::SYMBOL_FUNCTION_INDEX; | 747 function_index = Context::SYMBOL_FUNCTION_INDEX; |
| 750 } else if (type->Is(HeapType::Number())) { | 748 } else if (type->Is(HeapType::Number())) { |
| 751 function_index = Context::NUMBER_FUNCTION_INDEX; | 749 function_index = Context::NUMBER_FUNCTION_INDEX; |
| 752 } else if (type->Is(HeapType::Boolean())) { | 750 } else if (type->Is(HeapType::Boolean())) { |
| 753 function_index = Context::BOOLEAN_FUNCTION_INDEX; | 751 function_index = Context::BOOLEAN_FUNCTION_INDEX; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 764 object_reg = scratch1(); | 762 object_reg = scratch1(); |
| 765 } | 763 } |
| 766 | 764 |
| 767 // Check that the maps starting from the prototype haven't changed. | 765 // Check that the maps starting from the prototype haven't changed. |
| 768 return CheckPrototypes( | 766 return CheckPrototypes( |
| 769 type, object_reg, holder, scratch1(), scratch2(), scratch3(), | 767 type, object_reg, holder, scratch1(), scratch2(), scratch3(), |
| 770 name, miss, check_type); | 768 name, miss, check_type); |
| 771 } | 769 } |
| 772 | 770 |
| 773 | 771 |
| 774 // HandlerFrontend for store uses the name register. It has to be restored | 772 // Frontend for store uses the name register. It has to be restored before a |
| 775 // before a miss. | 773 // miss. |
| 776 Register StoreStubCompiler::HandlerFrontendHeader( | 774 Register NamedStoreHandlerCompiler::FrontendHeader(Handle<HeapType> type, |
| 777 Handle<HeapType> type, | 775 Register object_reg, |
| 778 Register object_reg, | 776 Handle<JSObject> holder, |
| 779 Handle<JSObject> holder, | 777 Handle<Name> name, |
| 780 Handle<Name> name, | 778 Label* miss) { |
| 781 Label* miss) { | |
| 782 return CheckPrototypes(type, object_reg, holder, this->name(), | 779 return CheckPrototypes(type, object_reg, holder, this->name(), |
| 783 scratch1(), scratch2(), name, miss, SKIP_RECEIVER); | 780 scratch1(), scratch2(), name, miss, SKIP_RECEIVER); |
| 784 } | 781 } |
| 785 | 782 |
| 786 | 783 |
| 787 bool BaseLoadStoreStubCompiler::IncludesNumberType(TypeHandleList* types) { | 784 bool PropertyICCompiler::IncludesNumberType(TypeHandleList* types) { |
| 788 for (int i = 0; i < types->length(); ++i) { | 785 for (int i = 0; i < types->length(); ++i) { |
| 789 if (types->at(i)->Is(HeapType::Number())) return true; | 786 if (types->at(i)->Is(HeapType::Number())) return true; |
| 790 } | 787 } |
| 791 return false; | 788 return false; |
| 792 } | 789 } |
| 793 | 790 |
| 794 | 791 |
| 795 Register BaseLoadStoreStubCompiler::HandlerFrontend(Handle<HeapType> type, | 792 Register PropertyHandlerCompiler::Frontend(Handle<HeapType> type, |
| 796 Register object_reg, | 793 Register object_reg, |
| 797 Handle<JSObject> holder, | 794 Handle<JSObject> holder, |
| 798 Handle<Name> name) { | 795 Handle<Name> name) { |
| 799 Label miss; | 796 Label miss; |
| 800 | 797 Register reg = FrontendHeader(type, object_reg, holder, name, &miss); |
| 801 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss); | 798 FrontendFooter(name, &miss); |
| 802 | |
| 803 HandlerFrontendFooter(name, &miss); | |
| 804 | |
| 805 return reg; | 799 return reg; |
| 806 } | 800 } |
| 807 | 801 |
| 808 | 802 |
| 809 void LoadStubCompiler::NonexistentHandlerFrontend(Handle<HeapType> type, | 803 void NamedLoadHandlerCompiler::NonexistentFrontend(Handle<HeapType> type, |
| 810 Handle<JSObject> last, | 804 Handle<JSObject> last, |
| 811 Handle<Name> name) { | 805 Handle<Name> name) { |
| 812 Label miss; | 806 Label miss; |
| 813 | 807 |
| 814 Register holder; | 808 Register holder; |
| 815 Handle<Map> last_map; | 809 Handle<Map> last_map; |
| 816 if (last.is_null()) { | 810 if (last.is_null()) { |
| 817 holder = receiver(); | 811 holder = receiver(); |
| 818 last_map = IC::TypeToMap(*type, isolate()); | 812 last_map = IC::TypeToMap(*type, isolate()); |
| 819 // If |type| has null as its prototype, |last| is Handle<JSObject>::null(). | 813 // If |type| has null as its prototype, |last| is Handle<JSObject>::null(). |
| 820 ASSERT(last_map->prototype() == isolate()->heap()->null_value()); | 814 ASSERT(last_map->prototype() == isolate()->heap()->null_value()); |
| 821 } else { | 815 } else { |
| 822 holder = HandlerFrontendHeader(type, receiver(), last, name, &miss); | 816 holder = FrontendHeader(type, receiver(), last, name, &miss); |
| 823 last_map = handle(last->map()); | 817 last_map = handle(last->map()); |
| 824 } | 818 } |
| 825 | 819 |
| 826 if (last_map->is_dictionary_map() && | 820 if (last_map->is_dictionary_map() && |
| 827 !last_map->IsJSGlobalObjectMap() && | 821 !last_map->IsJSGlobalObjectMap() && |
| 828 !last_map->IsJSGlobalProxyMap()) { | 822 !last_map->IsJSGlobalProxyMap()) { |
| 829 if (!name->IsUniqueName()) { | 823 if (!name->IsUniqueName()) { |
| 830 ASSERT(name->IsString()); | 824 ASSERT(name->IsString()); |
| 831 name = factory()->InternalizeString(Handle<String>::cast(name)); | 825 name = factory()->InternalizeString(Handle<String>::cast(name)); |
| 832 } | 826 } |
| 833 ASSERT(last.is_null() || | 827 ASSERT(last.is_null() || |
| 834 last->property_dictionary()->FindEntry(name) == | 828 last->property_dictionary()->FindEntry(name) == |
| 835 NameDictionary::kNotFound); | 829 NameDictionary::kNotFound); |
| 836 GenerateDictionaryNegativeLookup(masm(), &miss, holder, name, | 830 GenerateDictionaryNegativeLookup(masm(), &miss, holder, name, |
| 837 scratch2(), scratch3()); | 831 scratch2(), scratch3()); |
| 838 } | 832 } |
| 839 | 833 |
| 840 // If the last object in the prototype chain is a global object, | 834 // If the last object in the prototype chain is a global object, |
| 841 // check that the global property cell is empty. | 835 // check that the global property cell is empty. |
| 842 if (last_map->IsJSGlobalObjectMap()) { | 836 if (last_map->IsJSGlobalObjectMap()) { |
| 843 Handle<JSGlobalObject> global = last.is_null() | 837 Handle<JSGlobalObject> global = last.is_null() |
| 844 ? Handle<JSGlobalObject>::cast(type->AsConstant()->Value()) | 838 ? Handle<JSGlobalObject>::cast(type->AsConstant()->Value()) |
| 845 : Handle<JSGlobalObject>::cast(last); | 839 : Handle<JSGlobalObject>::cast(last); |
| 846 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); | 840 GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); |
| 847 } | 841 } |
| 848 | 842 |
| 849 HandlerFrontendFooter(name, &miss); | 843 FrontendFooter(name, &miss); |
| 850 } | 844 } |
| 851 | 845 |
| 852 | 846 |
| 853 Handle<Code> LoadStubCompiler::CompileLoadField( | 847 Handle<Code> NamedLoadHandlerCompiler::CompileLoadField( |
| 854 Handle<HeapType> type, | 848 Handle<HeapType> type, Handle<JSObject> holder, Handle<Name> name, |
| 855 Handle<JSObject> holder, | 849 FieldIndex field, Representation representation) { |
| 856 Handle<Name> name, | 850 Register reg = Frontend(type, receiver(), holder, name); |
| 857 FieldIndex field, | |
| 858 Representation representation) { | |
| 859 Register reg = HandlerFrontend(type, receiver(), holder, name); | |
| 860 GenerateLoadField(reg, holder, field, representation); | 851 GenerateLoadField(reg, holder, field, representation); |
| 861 | |
| 862 // Return the generated code. | |
| 863 return GetCode(kind(), Code::FAST, name); | 852 return GetCode(kind(), Code::FAST, name); |
| 864 } | 853 } |
| 865 | 854 |
| 866 | 855 |
| 867 Handle<Code> LoadStubCompiler::CompileLoadConstant( | 856 Handle<Code> NamedLoadHandlerCompiler::CompileLoadConstant( |
| 868 Handle<HeapType> type, | 857 Handle<HeapType> type, Handle<JSObject> holder, Handle<Name> name, |
| 869 Handle<JSObject> holder, | |
| 870 Handle<Name> name, | |
| 871 Handle<Object> value) { | 858 Handle<Object> value) { |
| 872 HandlerFrontend(type, receiver(), holder, name); | 859 Frontend(type, receiver(), holder, name); |
| 873 GenerateLoadConstant(value); | 860 GenerateLoadConstant(value); |
| 874 | |
| 875 // Return the generated code. | |
| 876 return GetCode(kind(), Code::FAST, name); | 861 return GetCode(kind(), Code::FAST, name); |
| 877 } | 862 } |
| 878 | 863 |
| 879 | 864 |
| 880 Handle<Code> LoadStubCompiler::CompileLoadCallback( | 865 Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( |
| 881 Handle<HeapType> type, | 866 Handle<HeapType> type, Handle<JSObject> holder, Handle<Name> name, |
| 882 Handle<JSObject> holder, | |
| 883 Handle<Name> name, | |
| 884 Handle<ExecutableAccessorInfo> callback) { | 867 Handle<ExecutableAccessorInfo> callback) { |
| 885 Register reg = CallbackHandlerFrontend( | 868 Register reg = CallbackFrontend(type, receiver(), holder, name, callback); |
| 886 type, receiver(), holder, name, callback); | |
| 887 GenerateLoadCallback(reg, callback); | 869 GenerateLoadCallback(reg, callback); |
| 888 | |
| 889 // Return the generated code. | |
| 890 return GetCode(kind(), Code::FAST, name); | 870 return GetCode(kind(), Code::FAST, name); |
| 891 } | 871 } |
| 892 | 872 |
| 893 | 873 |
| 894 Handle<Code> LoadStubCompiler::CompileLoadCallback( | 874 Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( |
| 895 Handle<HeapType> type, | 875 Handle<HeapType> type, Handle<JSObject> holder, Handle<Name> name, |
| 896 Handle<JSObject> holder, | |
| 897 Handle<Name> name, | |
| 898 const CallOptimization& call_optimization) { | 876 const CallOptimization& call_optimization) { |
| 899 ASSERT(call_optimization.is_simple_api_call()); | 877 ASSERT(call_optimization.is_simple_api_call()); |
| 900 Handle<JSFunction> callback = call_optimization.constant_function(); | 878 Handle<JSFunction> callback = call_optimization.constant_function(); |
| 901 CallbackHandlerFrontend(type, receiver(), holder, name, callback); | 879 CallbackFrontend(type, receiver(), holder, name, callback); |
| 902 Handle<Map>receiver_map = IC::TypeToMap(*type, isolate()); | 880 Handle<Map>receiver_map = IC::TypeToMap(*type, isolate()); |
| 903 GenerateFastApiCall( | 881 GenerateFastApiCall( |
| 904 masm(), call_optimization, receiver_map, | 882 masm(), call_optimization, receiver_map, |
| 905 receiver(), scratch1(), false, 0, NULL); | 883 receiver(), scratch1(), false, 0, NULL); |
| 906 // Return the generated code. | |
| 907 return GetCode(kind(), Code::FAST, name); | 884 return GetCode(kind(), Code::FAST, name); |
| 908 } | 885 } |
| 909 | 886 |
| 910 | 887 |
| 911 Handle<Code> LoadStubCompiler::CompileLoadInterceptor( | 888 Handle<Code> NamedLoadHandlerCompiler::CompileLoadInterceptor( |
| 912 Handle<HeapType> type, | 889 Handle<HeapType> type, Handle<JSObject> holder, Handle<Name> name) { |
| 913 Handle<JSObject> holder, | 890 // Perform a lookup after the interceptor. |
| 914 Handle<Name> name) { | |
| 915 LookupResult lookup(isolate()); | 891 LookupResult lookup(isolate()); |
| 916 LookupPostInterceptor(holder, name, &lookup); | 892 holder->LookupOwnRealNamedProperty(name, &lookup); |
| 893 if (!lookup.IsFound()) { |
| 894 PrototypeIterator iter(holder->GetIsolate(), holder); |
| 895 if (!iter.IsAtEnd()) { |
| 896 PrototypeIterator::GetCurrent(iter)->Lookup(name, &lookup); |
| 897 } |
| 898 } |
| 917 | 899 |
| 918 Register reg = HandlerFrontend(type, receiver(), holder, name); | 900 Register reg = Frontend(type, receiver(), holder, name); |
| 919 // TODO(368): Compile in the whole chain: all the interceptors in | 901 // TODO(368): Compile in the whole chain: all the interceptors in |
| 920 // prototypes and ultimate answer. | 902 // prototypes and ultimate answer. |
| 921 GenerateLoadInterceptor(reg, type, holder, &lookup, name); | 903 GenerateLoadInterceptor(reg, type, holder, &lookup, name); |
| 922 | |
| 923 // Return the generated code. | |
| 924 return GetCode(kind(), Code::FAST, name); | 904 return GetCode(kind(), Code::FAST, name); |
| 925 } | 905 } |
| 926 | 906 |
| 927 | 907 |
| 928 void LoadStubCompiler::GenerateLoadPostInterceptor( | 908 void NamedLoadHandlerCompiler::GenerateLoadPostInterceptor( |
| 929 Register interceptor_reg, | 909 Register interceptor_reg, Handle<JSObject> interceptor_holder, |
| 930 Handle<JSObject> interceptor_holder, | 910 Handle<Name> name, LookupResult* lookup) { |
| 931 Handle<Name> name, | |
| 932 LookupResult* lookup) { | |
| 933 Handle<JSObject> holder(lookup->holder()); | 911 Handle<JSObject> holder(lookup->holder()); |
| 934 if (lookup->IsField()) { | 912 if (lookup->IsField()) { |
| 935 FieldIndex field = lookup->GetFieldIndex(); | 913 FieldIndex field = lookup->GetFieldIndex(); |
| 936 if (interceptor_holder.is_identical_to(holder)) { | 914 if (interceptor_holder.is_identical_to(holder)) { |
| 937 GenerateLoadField( | 915 GenerateLoadField( |
| 938 interceptor_reg, holder, field, lookup->representation()); | 916 interceptor_reg, holder, field, lookup->representation()); |
| 939 } else { | 917 } else { |
| 940 // We found FIELD property in prototype chain of interceptor's holder. | 918 // We found FIELD property in prototype chain of interceptor's holder. |
| 941 // Retrieve a field from field's holder. | 919 // Retrieve a field from field's holder. |
| 942 Register reg = HandlerFrontend( | 920 Register reg = Frontend(IC::CurrentTypeOf(interceptor_holder, isolate()), |
| 943 IC::CurrentTypeOf(interceptor_holder, isolate()), | 921 interceptor_reg, holder, name); |
| 944 interceptor_reg, holder, name); | |
| 945 GenerateLoadField( | 922 GenerateLoadField( |
| 946 reg, holder, field, lookup->representation()); | 923 reg, holder, field, lookup->representation()); |
| 947 } | 924 } |
| 948 } else { | 925 } else { |
| 949 // We found CALLBACKS property in prototype chain of interceptor's | 926 // We found CALLBACKS property in prototype chain of interceptor's |
| 950 // holder. | 927 // holder. |
| 951 ASSERT(lookup->type() == CALLBACKS); | 928 ASSERT(lookup->type() == CALLBACKS); |
| 952 Handle<ExecutableAccessorInfo> callback( | 929 Handle<ExecutableAccessorInfo> callback( |
| 953 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); | 930 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); |
| 954 ASSERT(callback->getter() != NULL); | 931 ASSERT(callback->getter() != NULL); |
| 955 | 932 |
| 956 Register reg = CallbackHandlerFrontend( | 933 Register reg = |
| 957 IC::CurrentTypeOf(interceptor_holder, isolate()), | 934 CallbackFrontend(IC::CurrentTypeOf(interceptor_holder, isolate()), |
| 958 interceptor_reg, holder, name, callback); | 935 interceptor_reg, holder, name, callback); |
| 959 GenerateLoadCallback(reg, callback); | 936 GenerateLoadCallback(reg, callback); |
| 960 } | 937 } |
| 961 } | 938 } |
| 962 | 939 |
| 963 | 940 |
| 964 Handle<Code> BaseLoadStoreStubCompiler::CompileMonomorphicIC( | 941 Handle<Code> PropertyICCompiler::CompileMonomorphic(Handle<HeapType> type, |
| 965 Handle<HeapType> type, | 942 Handle<Code> handler, |
| 966 Handle<Code> handler, | 943 Handle<Name> name, |
| 967 Handle<Name> name) { | 944 IcCheckType check) { |
| 968 TypeHandleList types(1); | 945 TypeHandleList types(1); |
| 969 CodeHandleList handlers(1); | 946 CodeHandleList handlers(1); |
| 970 types.Add(type); | 947 types.Add(type); |
| 971 handlers.Add(handler); | 948 handlers.Add(handler); |
| 972 Code::StubType stub_type = handler->type(); | 949 Code::StubType stub_type = handler->type(); |
| 973 return CompilePolymorphicIC(&types, &handlers, name, stub_type, PROPERTY); | 950 return CompilePolymorphic(&types, &handlers, name, stub_type, check); |
| 974 } | 951 } |
| 975 | 952 |
| 976 | 953 |
| 977 Handle<Code> LoadStubCompiler::CompileLoadViaGetter( | 954 Handle<Code> NamedLoadHandlerCompiler::CompileLoadViaGetter( |
| 978 Handle<HeapType> type, | 955 Handle<HeapType> type, Handle<JSObject> holder, Handle<Name> name, |
| 979 Handle<JSObject> holder, | |
| 980 Handle<Name> name, | |
| 981 Handle<JSFunction> getter) { | 956 Handle<JSFunction> getter) { |
| 982 HandlerFrontend(type, receiver(), holder, name); | 957 Frontend(type, receiver(), holder, name); |
| 983 GenerateLoadViaGetter(masm(), type, receiver(), getter); | 958 GenerateLoadViaGetter(masm(), type, receiver(), getter); |
| 984 | |
| 985 // Return the generated code. | |
| 986 return GetCode(kind(), Code::FAST, name); | 959 return GetCode(kind(), Code::FAST, name); |
| 987 } | 960 } |
| 988 | 961 |
| 989 | 962 |
| 990 Handle<Code> StoreStubCompiler::CompileStoreTransition( | 963 Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition( |
| 991 Handle<JSObject> object, | 964 Handle<JSObject> object, LookupResult* lookup, Handle<Map> transition, |
| 992 LookupResult* lookup, | |
| 993 Handle<Map> transition, | |
| 994 Handle<Name> name) { | 965 Handle<Name> name) { |
| 995 Label miss, slow; | 966 Label miss, slow; |
| 996 | 967 |
| 997 // Ensure no transitions to deprecated maps are followed. | 968 // Ensure no transitions to deprecated maps are followed. |
| 998 __ CheckMapDeprecated(transition, scratch1(), &miss); | 969 __ CheckMapDeprecated(transition, scratch1(), &miss); |
| 999 | 970 |
| 1000 // Check that we are allowed to write this. | 971 // Check that we are allowed to write this. |
| 1001 PrototypeIterator iter(object->GetIsolate(), object); | 972 PrototypeIterator iter(object->GetIsolate(), object); |
| 1002 if (!iter.IsAtEnd()) { | 973 if (!iter.IsAtEnd()) { |
| 1003 Handle<JSObject> holder; | 974 Handle<JSObject> holder; |
| 1004 // holder == object indicates that no property was found. | 975 // holder == object indicates that no property was found. |
| 1005 if (lookup->holder() != *object) { | 976 if (lookup->holder() != *object) { |
| 1006 holder = Handle<JSObject>(lookup->holder()); | 977 holder = Handle<JSObject>(lookup->holder()); |
| 1007 } else { | 978 } else { |
| 1008 // Find the top object. | 979 // Find the top object. |
| 1009 do { | 980 do { |
| 1010 holder = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); | 981 holder = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); |
| 1011 iter.Advance(); | 982 iter.Advance(); |
| 1012 } while (!iter.IsAtEnd()); | 983 } while (!iter.IsAtEnd()); |
| 1013 } | 984 } |
| 1014 | 985 |
| 1015 Register holder_reg = HandlerFrontendHeader( | 986 Register holder_reg = FrontendHeader(IC::CurrentTypeOf(object, isolate()), |
| 1016 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name, &miss); | 987 receiver(), holder, name, &miss); |
| 1017 | 988 |
| 1018 // If no property was found, and the holder (the last object in the | 989 // If no property was found, and the holder (the last object in the |
| 1019 // prototype chain) is in slow mode, we need to do a negative lookup on the | 990 // prototype chain) is in slow mode, we need to do a negative lookup on the |
| 1020 // holder. | 991 // holder. |
| 1021 if (lookup->holder() == *object) { | 992 if (lookup->holder() == *object) { |
| 1022 GenerateNegativeHolderLookup(masm(), holder, holder_reg, name, &miss); | 993 GenerateNegativeHolderLookup(masm(), holder, holder_reg, name, &miss); |
| 1023 } | 994 } |
| 1024 } | 995 } |
| 1025 | 996 |
| 1026 GenerateStoreTransition(masm(), | 997 GenerateStoreTransition(masm(), |
| 1027 object, | 998 object, |
| 1028 lookup, | 999 lookup, |
| 1029 transition, | 1000 transition, |
| 1030 name, | 1001 name, |
| 1031 receiver(), this->name(), value(), | 1002 receiver(), this->name(), value(), |
| 1032 scratch1(), scratch2(), scratch3(), | 1003 scratch1(), scratch2(), scratch3(), |
| 1033 &miss, | 1004 &miss, |
| 1034 &slow); | 1005 &slow); |
| 1035 | 1006 |
| 1036 // Handle store cache miss. | 1007 // Handle store cache miss. |
| 1037 GenerateRestoreName(masm(), &miss, name); | 1008 GenerateRestoreName(masm(), &miss, name); |
| 1038 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1009 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1039 | 1010 |
| 1040 GenerateRestoreName(masm(), &slow, name); | 1011 GenerateRestoreName(masm(), &slow, name); |
| 1041 TailCallBuiltin(masm(), SlowBuiltin(kind())); | 1012 TailCallBuiltin(masm(), SlowBuiltin(kind())); |
| 1042 | |
| 1043 // Return the generated code. | |
| 1044 return GetCode(kind(), Code::FAST, name); | 1013 return GetCode(kind(), Code::FAST, name); |
| 1045 } | 1014 } |
| 1046 | 1015 |
| 1047 | 1016 |
| 1048 Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, | 1017 Handle<Code> NamedStoreHandlerCompiler::CompileStoreField( |
| 1049 LookupResult* lookup, | 1018 Handle<JSObject> object, LookupResult* lookup, Handle<Name> name) { |
| 1050 Handle<Name> name) { | |
| 1051 Label miss; | 1019 Label miss; |
| 1052 | 1020 |
| 1053 HandlerFrontendHeader(IC::CurrentTypeOf(object, isolate()), | 1021 FrontendHeader(IC::CurrentTypeOf(object, isolate()), receiver(), object, name, |
| 1054 receiver(), object, name, &miss); | 1022 &miss); |
| 1055 | 1023 |
| 1056 // Generate store field code. | 1024 // Generate store field code. |
| 1057 GenerateStoreField(masm(), | 1025 GenerateStoreField(masm(), |
| 1058 object, | 1026 object, |
| 1059 lookup, | 1027 lookup, |
| 1060 receiver(), this->name(), value(), scratch1(), scratch2(), | 1028 receiver(), this->name(), value(), scratch1(), scratch2(), |
| 1061 &miss); | 1029 &miss); |
| 1062 | 1030 |
| 1063 // Handle store cache miss. | 1031 // Handle store cache miss. |
| 1064 __ bind(&miss); | 1032 __ bind(&miss); |
| 1065 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1033 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1066 | |
| 1067 // Return the generated code. | |
| 1068 return GetCode(kind(), Code::FAST, name); | 1034 return GetCode(kind(), Code::FAST, name); |
| 1069 } | 1035 } |
| 1070 | 1036 |
| 1071 | 1037 |
| 1072 Handle<Code> StoreStubCompiler::CompileStoreArrayLength(Handle<JSObject> object, | 1038 Handle<Code> NamedStoreHandlerCompiler::CompileStoreArrayLength( |
| 1073 LookupResult* lookup, | 1039 Handle<JSObject> object, LookupResult* lookup, Handle<Name> name) { |
| 1074 Handle<Name> name) { | |
| 1075 // This accepts as a receiver anything JSArray::SetElementsLength accepts | 1040 // This accepts as a receiver anything JSArray::SetElementsLength accepts |
| 1076 // (currently anything except for external arrays which means anything with | 1041 // (currently anything except for external arrays which means anything with |
| 1077 // elements of FixedArray type). Value must be a number, but only smis are | 1042 // elements of FixedArray type). Value must be a number, but only smis are |
| 1078 // accepted as the most common case. | 1043 // accepted as the most common case. |
| 1079 Label miss; | 1044 Label miss; |
| 1080 | 1045 |
| 1081 // Check that value is a smi. | 1046 // Check that value is a smi. |
| 1082 __ JumpIfNotSmi(value(), &miss); | 1047 __ JumpIfNotSmi(value(), &miss); |
| 1083 | 1048 |
| 1084 // Generate tail call to StoreIC_ArrayLength. | 1049 // Generate tail call to StoreIC_ArrayLength. |
| 1085 GenerateStoreArrayLength(); | 1050 GenerateStoreArrayLength(); |
| 1086 | 1051 |
| 1087 // Handle miss case. | 1052 // Handle miss case. |
| 1088 __ bind(&miss); | 1053 __ bind(&miss); |
| 1089 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1054 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 1090 | |
| 1091 // Return the generated code. | |
| 1092 return GetCode(kind(), Code::FAST, name); | 1055 return GetCode(kind(), Code::FAST, name); |
| 1093 } | 1056 } |
| 1094 | 1057 |
| 1095 | 1058 |
| 1096 Handle<Code> StoreStubCompiler::CompileStoreViaSetter( | 1059 Handle<Code> NamedStoreHandlerCompiler::CompileStoreViaSetter( |
| 1097 Handle<JSObject> object, | 1060 Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, |
| 1098 Handle<JSObject> holder, | |
| 1099 Handle<Name> name, | |
| 1100 Handle<JSFunction> setter) { | 1061 Handle<JSFunction> setter) { |
| 1101 Handle<HeapType> type = IC::CurrentTypeOf(object, isolate()); | 1062 Handle<HeapType> type = IC::CurrentTypeOf(object, isolate()); |
| 1102 HandlerFrontend(type, receiver(), holder, name); | 1063 Frontend(type, receiver(), holder, name); |
| 1103 GenerateStoreViaSetter(masm(), type, receiver(), setter); | 1064 GenerateStoreViaSetter(masm(), type, receiver(), setter); |
| 1104 | 1065 |
| 1105 return GetCode(kind(), Code::FAST, name); | 1066 return GetCode(kind(), Code::FAST, name); |
| 1106 } | 1067 } |
| 1107 | 1068 |
| 1108 | 1069 |
| 1109 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 1070 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
| 1110 Handle<JSObject> object, | 1071 Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, |
| 1111 Handle<JSObject> holder, | |
| 1112 Handle<Name> name, | |
| 1113 const CallOptimization& call_optimization) { | 1072 const CallOptimization& call_optimization) { |
| 1114 HandlerFrontend(IC::CurrentTypeOf(object, isolate()), | 1073 Frontend(IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); |
| 1115 receiver(), holder, name); | |
| 1116 Register values[] = { value() }; | 1074 Register values[] = { value() }; |
| 1117 GenerateFastApiCall( | 1075 GenerateFastApiCall( |
| 1118 masm(), call_optimization, handle(object->map()), | 1076 masm(), call_optimization, handle(object->map()), |
| 1119 receiver(), scratch1(), true, 1, values); | 1077 receiver(), scratch1(), true, 1, values); |
| 1120 // Return the generated code. | |
| 1121 return GetCode(kind(), Code::FAST, name); | 1078 return GetCode(kind(), Code::FAST, name); |
| 1122 } | 1079 } |
| 1123 | 1080 |
| 1124 | 1081 |
| 1125 Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( | 1082 Handle<Code> PropertyICCompiler::CompileIndexedStoreMonomorphic( |
| 1126 Handle<Map> receiver_map) { | 1083 Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) { |
| 1127 ElementsKind elements_kind = receiver_map->elements_kind(); | |
| 1128 if (receiver_map->has_fast_elements() || | |
| 1129 receiver_map->has_external_array_elements() || | |
| 1130 receiver_map->has_fixed_typed_array_elements()) { | |
| 1131 Handle<Code> stub = KeyedLoadFastElementStub( | |
| 1132 isolate(), | |
| 1133 receiver_map->instance_type() == JS_ARRAY_TYPE, | |
| 1134 elements_kind).GetCode(); | |
| 1135 __ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK); | |
| 1136 } else { | |
| 1137 Handle<Code> stub = FLAG_compiled_keyed_dictionary_loads | |
| 1138 ? KeyedLoadDictionaryElementStub(isolate()).GetCode() | |
| 1139 : KeyedLoadDictionaryElementPlatformStub(isolate()).GetCode(); | |
| 1140 __ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK); | |
| 1141 } | |
| 1142 | |
| 1143 TailCallBuiltin(masm(), Builtins::kKeyedLoadIC_Miss); | |
| 1144 | |
| 1145 // Return the generated code. | |
| 1146 Code::Flags flags = Code::ComputeFlags(Code::KEYED_LOAD_IC, MONOMORPHIC, | |
| 1147 extra_state(), Code::NORMAL); | |
| 1148 Handle<Code> code = GetCodeWithFlags(flags, factory()->empty_string()); | |
| 1149 IC::RegisterWeakMapDependency(code); | |
| 1150 PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, | |
| 1151 heap()->empty_string())); | |
| 1152 return code; | |
| 1153 } | |
| 1154 | |
| 1155 | |
| 1156 Handle<Code> KeyedStoreStubCompiler::CompileStoreElement( | |
| 1157 Handle<Map> receiver_map) { | |
| 1158 ElementsKind elements_kind = receiver_map->elements_kind(); | 1084 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 1159 bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE; | 1085 bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE; |
| 1160 Handle<Code> stub; | 1086 Handle<Code> stub; |
| 1161 if (receiver_map->has_fast_elements() || | 1087 if (receiver_map->has_fast_elements() || |
| 1162 receiver_map->has_external_array_elements() || | 1088 receiver_map->has_external_array_elements() || |
| 1163 receiver_map->has_fixed_typed_array_elements()) { | 1089 receiver_map->has_fixed_typed_array_elements()) { |
| 1164 stub = KeyedStoreFastElementStub( | 1090 stub = KeyedStoreFastElementStub(isolate(), is_jsarray, elements_kind, |
| 1165 isolate(), | 1091 store_mode).GetCode(); |
| 1166 is_jsarray, | |
| 1167 elements_kind, | |
| 1168 store_mode()).GetCode(); | |
| 1169 } else { | 1092 } else { |
| 1170 stub = KeyedStoreElementStub(isolate(), | 1093 stub = KeyedStoreElementStub(isolate(), is_jsarray, elements_kind, |
| 1171 is_jsarray, | 1094 store_mode).GetCode(); |
| 1172 elements_kind, | |
| 1173 store_mode()).GetCode(); | |
| 1174 } | 1095 } |
| 1175 | 1096 |
| 1176 __ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK); | 1097 __ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK); |
| 1177 | 1098 |
| 1178 TailCallBuiltin(masm(), Builtins::kKeyedStoreIC_Miss); | 1099 TailCallBuiltin(masm(), Builtins::kKeyedStoreIC_Miss); |
| 1179 | 1100 |
| 1180 // Return the generated code. | 1101 return GetCode(kind(), Code::NORMAL, factory()->empty_string()); |
| 1181 return GetICCode(kind(), Code::NORMAL, factory()->empty_string()); | |
| 1182 } | 1102 } |
| 1183 | 1103 |
| 1184 | 1104 |
| 1185 #undef __ | 1105 #undef __ |
| 1186 | 1106 |
| 1187 | 1107 |
| 1188 void StubCompiler::TailCallBuiltin(MacroAssembler* masm, Builtins::Name name) { | 1108 void PropertyAccessCompiler::TailCallBuiltin(MacroAssembler* masm, |
| 1109 Builtins::Name name) { |
| 1189 Handle<Code> code(masm->isolate()->builtins()->builtin(name)); | 1110 Handle<Code> code(masm->isolate()->builtins()->builtin(name)); |
| 1190 GenerateTailCall(masm, code); | 1111 GenerateTailCall(masm, code); |
| 1191 } | 1112 } |
| 1192 | 1113 |
| 1193 | 1114 |
| 1194 void BaseLoadStoreStubCompiler::InitializeRegisters() { | 1115 Register* PropertyAccessCompiler::GetCallingConvention(Code::Kind kind) { |
| 1195 if (kind_ == Code::LOAD_IC) { | 1116 if (kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC) { |
| 1196 registers_ = LoadStubCompiler::registers(); | 1117 return load_calling_convention(); |
| 1197 } else if (kind_ == Code::STORE_IC) { | 1118 } else if (kind == Code::STORE_IC) { |
| 1198 registers_ = StoreStubCompiler::registers(); | 1119 return store_calling_convention(); |
| 1199 } else { | 1120 } else { |
| 1200 registers_ = KeyedStoreStubCompiler::registers(); | 1121 ASSERT_EQ(Code::KEYED_STORE_IC, kind); |
| 1122 return keyed_store_calling_convention(); |
| 1201 } | 1123 } |
| 1202 } | 1124 } |
| 1203 | 1125 |
| 1204 | 1126 |
| 1205 Handle<Code> BaseLoadStoreStubCompiler::GetICCode(Code::Kind kind, | 1127 Handle<Code> PropertyICCompiler::GetCode(Code::Kind kind, Code::StubType type, |
| 1206 Code::StubType type, | 1128 Handle<Name> name, |
| 1207 Handle<Name> name, | 1129 InlineCacheState state) { |
| 1208 InlineCacheState state) { | 1130 Code::Flags flags = |
| 1209 Code::Flags flags = Code::ComputeFlags(kind, state, extra_state(), type); | 1131 Code::ComputeFlags(kind, state, extra_state(), type, cache_holder()); |
| 1210 Handle<Code> code = GetCodeWithFlags(flags, name); | 1132 Handle<Code> code = GetCodeWithFlags(flags, name); |
| 1211 IC::RegisterWeakMapDependency(code); | 1133 IC::RegisterWeakMapDependency(code); |
| 1212 PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name)); | 1134 PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name)); |
| 1213 return code; | 1135 return code; |
| 1214 } | 1136 } |
| 1215 | 1137 |
| 1216 | 1138 |
| 1217 Handle<Code> BaseLoadStoreStubCompiler::GetCode(Code::Kind kind, | 1139 Handle<Code> PropertyHandlerCompiler::GetCode(Code::Kind kind, |
| 1218 Code::StubType type, | 1140 Code::StubType type, |
| 1219 Handle<Name> name) { | 1141 Handle<Name> name) { |
| 1220 ASSERT_EQ(kNoExtraICState, extra_state()); | 1142 ASSERT_EQ(kNoExtraICState, extra_state()); |
| 1221 Code::Flags flags = Code::ComputeHandlerFlags(kind, type, cache_holder_); | 1143 Code::Flags flags = Code::ComputeHandlerFlags(kind, type, cache_holder()); |
| 1222 Handle<Code> code = GetCodeWithFlags(flags, name); | 1144 Handle<Code> code = GetCodeWithFlags(flags, name); |
| 1223 PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name)); | 1145 PROFILE(isolate(), CodeCreateEvent(Logger::STUB_TAG, *code, *name)); |
| 1224 return code; | 1146 return code; |
| 1225 } | 1147 } |
| 1226 | 1148 |
| 1227 | 1149 |
| 1228 void KeyedLoadStubCompiler::CompileElementHandlers(MapHandleList* receiver_maps, | 1150 void IndexedHandlerCompiler::CompileElementHandlers( |
| 1229 CodeHandleList* handlers) { | 1151 MapHandleList* receiver_maps, CodeHandleList* handlers) { |
| 1230 for (int i = 0; i < receiver_maps->length(); ++i) { | 1152 for (int i = 0; i < receiver_maps->length(); ++i) { |
| 1231 Handle<Map> receiver_map = receiver_maps->at(i); | 1153 Handle<Map> receiver_map = receiver_maps->at(i); |
| 1232 Handle<Code> cached_stub; | 1154 Handle<Code> cached_stub; |
| 1233 | 1155 |
| 1234 if ((receiver_map->instance_type() & kNotStringTag) == 0) { | 1156 if ((receiver_map->instance_type() & kNotStringTag) == 0) { |
| 1235 cached_stub = isolate()->builtins()->KeyedLoadIC_String(); | 1157 cached_stub = isolate()->builtins()->KeyedLoadIC_String(); |
| 1236 } else if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE) { | 1158 } else if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE) { |
| 1237 cached_stub = isolate()->builtins()->KeyedLoadIC_Slow(); | 1159 cached_stub = isolate()->builtins()->KeyedLoadIC_Slow(); |
| 1238 } else { | 1160 } else { |
| 1239 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; | 1161 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1253 cached_stub = | 1175 cached_stub = |
| 1254 KeyedLoadDictionaryElementStub(isolate()).GetCode(); | 1176 KeyedLoadDictionaryElementStub(isolate()).GetCode(); |
| 1255 } | 1177 } |
| 1256 } | 1178 } |
| 1257 | 1179 |
| 1258 handlers->Add(cached_stub); | 1180 handlers->Add(cached_stub); |
| 1259 } | 1181 } |
| 1260 } | 1182 } |
| 1261 | 1183 |
| 1262 | 1184 |
| 1263 Handle<Code> KeyedStoreStubCompiler::CompileStoreElementPolymorphic( | 1185 Handle<Code> PropertyICCompiler::CompileIndexedStorePolymorphic( |
| 1264 MapHandleList* receiver_maps) { | 1186 MapHandleList* receiver_maps, KeyedAccessStoreMode store_mode) { |
| 1265 // Collect MONOMORPHIC stubs for all |receiver_maps|. | 1187 // Collect MONOMORPHIC stubs for all |receiver_maps|. |
| 1266 CodeHandleList handlers(receiver_maps->length()); | 1188 CodeHandleList handlers(receiver_maps->length()); |
| 1267 MapHandleList transitioned_maps(receiver_maps->length()); | 1189 MapHandleList transitioned_maps(receiver_maps->length()); |
| 1268 for (int i = 0; i < receiver_maps->length(); ++i) { | 1190 for (int i = 0; i < receiver_maps->length(); ++i) { |
| 1269 Handle<Map> receiver_map(receiver_maps->at(i)); | 1191 Handle<Map> receiver_map(receiver_maps->at(i)); |
| 1270 Handle<Code> cached_stub; | 1192 Handle<Code> cached_stub; |
| 1271 Handle<Map> transitioned_map = | 1193 Handle<Map> transitioned_map = |
| 1272 receiver_map->FindTransitionedMap(receiver_maps); | 1194 receiver_map->FindTransitionedMap(receiver_maps); |
| 1273 | 1195 |
| 1274 // TODO(mvstanton): The code below is doing pessimistic elements | 1196 // TODO(mvstanton): The code below is doing pessimistic elements |
| 1275 // transitions. I would like to stop doing that and rely on Allocation Site | 1197 // transitions. I would like to stop doing that and rely on Allocation Site |
| 1276 // Tracking to do a better job of ensuring the data types are what they need | 1198 // Tracking to do a better job of ensuring the data types are what they need |
| 1277 // to be. Not all the elements are in place yet, pessimistic elements | 1199 // to be. Not all the elements are in place yet, pessimistic elements |
| 1278 // transitions are still important for performance. | 1200 // transitions are still important for performance. |
| 1279 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; | 1201 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; |
| 1280 ElementsKind elements_kind = receiver_map->elements_kind(); | 1202 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 1281 if (!transitioned_map.is_null()) { | 1203 if (!transitioned_map.is_null()) { |
| 1282 cached_stub = ElementsTransitionAndStoreStub( | 1204 cached_stub = |
| 1283 isolate(), | 1205 ElementsTransitionAndStoreStub(isolate(), elements_kind, |
| 1284 elements_kind, | 1206 transitioned_map->elements_kind(), |
| 1285 transitioned_map->elements_kind(), | 1207 is_js_array, store_mode).GetCode(); |
| 1286 is_js_array, | |
| 1287 store_mode()).GetCode(); | |
| 1288 } else if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE) { | 1208 } else if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE) { |
| 1289 cached_stub = isolate()->builtins()->KeyedStoreIC_Slow(); | 1209 cached_stub = isolate()->builtins()->KeyedStoreIC_Slow(); |
| 1290 } else { | 1210 } else { |
| 1291 if (receiver_map->has_fast_elements() || | 1211 if (receiver_map->has_fast_elements() || |
| 1292 receiver_map->has_external_array_elements() || | 1212 receiver_map->has_external_array_elements() || |
| 1293 receiver_map->has_fixed_typed_array_elements()) { | 1213 receiver_map->has_fixed_typed_array_elements()) { |
| 1294 cached_stub = KeyedStoreFastElementStub( | 1214 cached_stub = |
| 1295 isolate(), | 1215 KeyedStoreFastElementStub(isolate(), is_js_array, elements_kind, |
| 1296 is_js_array, | 1216 store_mode).GetCode(); |
| 1297 elements_kind, | |
| 1298 store_mode()).GetCode(); | |
| 1299 } else { | 1217 } else { |
| 1300 cached_stub = KeyedStoreElementStub( | 1218 cached_stub = |
| 1301 isolate(), | 1219 KeyedStoreElementStub(isolate(), is_js_array, elements_kind, |
| 1302 is_js_array, | 1220 store_mode).GetCode(); |
| 1303 elements_kind, | |
| 1304 store_mode()).GetCode(); | |
| 1305 } | 1221 } |
| 1306 } | 1222 } |
| 1307 ASSERT(!cached_stub.is_null()); | 1223 ASSERT(!cached_stub.is_null()); |
| 1308 handlers.Add(cached_stub); | 1224 handlers.Add(cached_stub); |
| 1309 transitioned_maps.Add(transitioned_map); | 1225 transitioned_maps.Add(transitioned_map); |
| 1310 } | 1226 } |
| 1311 Handle<Code> code = | 1227 |
| 1312 CompileStorePolymorphic(receiver_maps, &handlers, &transitioned_maps); | 1228 Handle<Code> code = CompileIndexedStorePolymorphic(receiver_maps, &handlers, |
| 1229 &transitioned_maps); |
| 1313 isolate()->counters()->keyed_store_polymorphic_stubs()->Increment(); | 1230 isolate()->counters()->keyed_store_polymorphic_stubs()->Increment(); |
| 1314 PROFILE(isolate(), | 1231 PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, 0)); |
| 1315 CodeCreateEvent(Logger::KEYED_STORE_POLYMORPHIC_IC_TAG, *code, 0)); | |
| 1316 return code; | 1232 return code; |
| 1317 } | 1233 } |
| 1318 | 1234 |
| 1319 | 1235 |
| 1320 void KeyedStoreStubCompiler::GenerateStoreDictionaryElement( | 1236 void IndexedHandlerCompiler::GenerateStoreDictionaryElement( |
| 1321 MacroAssembler* masm) { | 1237 MacroAssembler* masm) { |
| 1322 KeyedStoreIC::GenerateSlow(masm); | 1238 KeyedStoreIC::GenerateSlow(masm); |
| 1323 } | 1239 } |
| 1324 | 1240 |
| 1325 | 1241 |
| 1326 CallOptimization::CallOptimization(LookupResult* lookup) { | 1242 CallOptimization::CallOptimization(LookupResult* lookup) { |
| 1327 if (lookup->IsFound() && | 1243 if (lookup->IsFound() && |
| 1328 lookup->IsCacheable() && | 1244 lookup->IsCacheable() && |
| 1329 lookup->IsConstantFunction()) { | 1245 lookup->IsConstantFunction()) { |
| 1330 // We only optimize constant function calls. | 1246 // We only optimize constant function calls. |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1433 Handle<FunctionTemplateInfo>( | 1349 Handle<FunctionTemplateInfo>( |
| 1434 FunctionTemplateInfo::cast(signature->receiver())); | 1350 FunctionTemplateInfo::cast(signature->receiver())); |
| 1435 } | 1351 } |
| 1436 } | 1352 } |
| 1437 | 1353 |
| 1438 is_simple_api_call_ = true; | 1354 is_simple_api_call_ = true; |
| 1439 } | 1355 } |
| 1440 | 1356 |
| 1441 | 1357 |
| 1442 } } // namespace v8::internal | 1358 } } // namespace v8::internal |
| OLD | NEW |