| 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 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 Code::StubType type) { | 122 Code::StubType type) { |
| 123 Code::Flags flags = Code::ComputeHandlerFlags(kind, type, cache_holder); | 123 Code::Flags flags = Code::ComputeHandlerFlags(kind, type, cache_holder); |
| 124 | 124 |
| 125 Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), | 125 Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), |
| 126 name->GetIsolate()); | 126 name->GetIsolate()); |
| 127 if (probe->IsCode()) return Handle<Code>::cast(probe); | 127 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 128 return Handle<Code>::null(); | 128 return Handle<Code>::null(); |
| 129 } | 129 } |
| 130 | 130 |
| 131 | 131 |
| 132 Handle<Code> PropertyICCompiler::ComputeMonomorphicIC( | 132 Handle<Code> PropertyICCompiler::ComputeMonomorphic( |
| 133 Code::Kind kind, Handle<Name> name, Handle<HeapType> type, | 133 Code::Kind kind, Handle<Name> name, Handle<HeapType> type, |
| 134 Handle<Code> handler, ExtraICState extra_ic_state) { | 134 Handle<Code> handler, ExtraICState extra_ic_state) { |
| 135 CacheHolderFlag flag; | 135 CacheHolderFlag flag; |
| 136 Isolate* isolate = name->GetIsolate(); | 136 Isolate* isolate = name->GetIsolate(); |
| 137 Handle<Map> stub_holder = IC::GetICCacheHolder(*type, isolate, &flag); | 137 Handle<Map> stub_holder = IC::GetICCacheHolder(*type, isolate, &flag); |
| 138 | 138 |
| 139 Handle<Code> ic; | 139 Handle<Code> ic; |
| 140 // There are multiple string maps that all use the same prototype. That | 140 // There are multiple string maps that all use the same prototype. That |
| 141 // prototype cannot hold multiple handlers, one for each of the string maps, | 141 // prototype cannot hold multiple handlers, one for each of the string maps, |
| 142 // for a single name. Hence, turn off caching of the IC. | 142 // for a single name. Hence, turn off caching of the IC. |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 cache_name, stub_holder_map, Code::LOAD_IC, flag, Code::FAST); | 198 cache_name, stub_holder_map, Code::LOAD_IC, flag, Code::FAST); |
| 199 if (!handler.is_null()) return handler; | 199 if (!handler.is_null()) return handler; |
| 200 | 200 |
| 201 NamedLoadHandlerCompiler compiler(isolate, flag); | 201 NamedLoadHandlerCompiler compiler(isolate, flag); |
| 202 handler = compiler.CompileLoadNonexistent(type, last, cache_name); | 202 handler = compiler.CompileLoadNonexistent(type, last, cache_name); |
| 203 Map::UpdateCodeCache(stub_holder_map, cache_name, handler); | 203 Map::UpdateCodeCache(stub_holder_map, cache_name, handler); |
| 204 return handler; | 204 return handler; |
| 205 } | 205 } |
| 206 | 206 |
| 207 | 207 |
| 208 Handle<Code> PropertyICCompiler::ComputeKeyedLoadElement( | 208 Handle<Code> PropertyICCompiler::ComputeKeyedLoadMonomorphic( |
| 209 Handle<Map> receiver_map) { | 209 Handle<Map> receiver_map) { |
| 210 Isolate* isolate = receiver_map->GetIsolate(); | 210 Isolate* isolate = receiver_map->GetIsolate(); |
| 211 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC); | 211 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC); |
| 212 Handle<Name> name = isolate->factory()->KeyedLoadElementMonomorphic_string(); | 212 Handle<Name> name = isolate->factory()->KeyedLoadMonomorphic_string(); |
| 213 | 213 |
| 214 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate); | 214 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate); |
| 215 if (probe->IsCode()) return Handle<Code>::cast(probe); | 215 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 216 | 216 |
| 217 ElementsKind elements_kind = receiver_map->elements_kind(); | 217 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 218 Handle<Code> stub; | 218 Handle<Code> stub; |
| 219 if (receiver_map->has_fast_elements() || | 219 if (receiver_map->has_fast_elements() || |
| 220 receiver_map->has_external_array_elements() || | 220 receiver_map->has_external_array_elements() || |
| 221 receiver_map->has_fixed_typed_array_elements()) { | 221 receiver_map->has_fixed_typed_array_elements()) { |
| 222 stub = KeyedLoadFastElementStub( | 222 stub = LoadFastElementStub(isolate, |
| 223 isolate, receiver_map->instance_type() == JS_ARRAY_TYPE, | 223 receiver_map->instance_type() == JS_ARRAY_TYPE, |
| 224 elements_kind).GetCode(); | 224 elements_kind).GetCode(); |
| 225 } else { | 225 } else { |
| 226 stub = FLAG_compiled_keyed_dictionary_loads | 226 stub = FLAG_compiled_keyed_dictionary_loads |
| 227 ? KeyedLoadDictionaryElementStub(isolate).GetCode() | 227 ? LoadDictionaryElementStub(isolate).GetCode() |
| 228 : KeyedLoadDictionaryElementPlatformStub(isolate).GetCode(); | 228 : LoadDictionaryElementPlatformStub(isolate).GetCode(); |
| 229 } | 229 } |
| 230 PropertyICCompiler compiler(isolate, Code::KEYED_LOAD_IC); | 230 PropertyICCompiler compiler(isolate, Code::KEYED_LOAD_IC); |
| 231 Handle<Code> code = | 231 Handle<Code> code = |
| 232 compiler.CompileMonomorphic(HeapType::Class(receiver_map, isolate), stub, | 232 compiler.CompileMonomorphic(HeapType::Class(receiver_map, isolate), stub, |
| 233 isolate->factory()->empty_string(), ELEMENT); | 233 isolate->factory()->empty_string(), ELEMENT); |
| 234 | 234 |
| 235 Map::UpdateCodeCache(receiver_map, name, code); | 235 Map::UpdateCodeCache(receiver_map, name, code); |
| 236 return code; | 236 return code; |
| 237 } | 237 } |
| 238 | 238 |
| 239 | 239 |
| 240 Handle<Code> PropertyICCompiler::ComputeKeyedStoreElement( | 240 Handle<Code> PropertyICCompiler::ComputeKeyedStoreMonomorphic( |
| 241 Handle<Map> receiver_map, StrictMode strict_mode, | 241 Handle<Map> receiver_map, StrictMode strict_mode, |
| 242 KeyedAccessStoreMode store_mode) { | 242 KeyedAccessStoreMode store_mode) { |
| 243 Isolate* isolate = receiver_map->GetIsolate(); | 243 Isolate* isolate = receiver_map->GetIsolate(); |
| 244 ExtraICState extra_state = | 244 ExtraICState extra_state = |
| 245 KeyedStoreIC::ComputeExtraICState(strict_mode, store_mode); | 245 KeyedStoreIC::ComputeExtraICState(strict_mode, store_mode); |
| 246 Code::Flags flags = | 246 Code::Flags flags = |
| 247 Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, extra_state); | 247 Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, extra_state); |
| 248 | 248 |
| 249 ASSERT(store_mode == STANDARD_STORE || | 249 ASSERT(store_mode == STANDARD_STORE || |
| 250 store_mode == STORE_AND_GROW_NO_TRANSITION || | 250 store_mode == STORE_AND_GROW_NO_TRANSITION || |
| 251 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || | 251 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || |
| 252 store_mode == STORE_NO_TRANSITION_HANDLE_COW); | 252 store_mode == STORE_NO_TRANSITION_HANDLE_COW); |
| 253 | 253 |
| 254 Handle<String> name = | 254 Handle<String> name = isolate->factory()->KeyedStoreMonomorphic_string(); |
| 255 isolate->factory()->KeyedStoreElementMonomorphic_string(); | |
| 256 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate); | 255 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate); |
| 257 if (probe->IsCode()) return Handle<Code>::cast(probe); | 256 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 258 | 257 |
| 259 PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state); | 258 PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state); |
| 260 Handle<Code> code = | 259 Handle<Code> code = |
| 261 compiler.CompileIndexedStoreMonomorphic(receiver_map, store_mode); | 260 compiler.CompileKeyedStoreMonomorphic(receiver_map, store_mode); |
| 262 | 261 |
| 263 Map::UpdateCodeCache(receiver_map, name, code); | 262 Map::UpdateCodeCache(receiver_map, name, code); |
| 264 ASSERT(KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state()) | 263 ASSERT(KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state()) |
| 265 == store_mode); | 264 == store_mode); |
| 266 return code; | 265 return code; |
| 267 } | 266 } |
| 268 | 267 |
| 269 | 268 |
| 270 #define CALL_LOGGER_TAG(kind, type) (Logger::KEYED_##type) | 269 #define CALL_LOGGER_TAG(kind, type) (Logger::KEYED_##type) |
| 271 | 270 |
| 272 static void FillCache(Isolate* isolate, Handle<Code> code) { | 271 static void FillCache(Isolate* isolate, Handle<Code> code) { |
| 273 Handle<UnseededNumberDictionary> dictionary = | 272 Handle<UnseededNumberDictionary> dictionary = |
| 274 UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(), | 273 UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(), |
| 275 code->flags(), | 274 code->flags(), |
| 276 code); | 275 code); |
| 277 isolate->heap()->public_set_non_monomorphic_cache(*dictionary); | 276 isolate->heap()->public_set_non_monomorphic_cache(*dictionary); |
| 278 } | 277 } |
| 279 | 278 |
| 280 | 279 |
| 281 Code* PropertyICCompiler::FindPreMonomorphicIC(Isolate* isolate, | 280 Code* PropertyICCompiler::FindPreMonomorphic(Isolate* isolate, Code::Kind kind, |
| 282 Code::Kind kind, | 281 ExtraICState state) { |
| 283 ExtraICState state) { | |
| 284 Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state); | 282 Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state); |
| 285 UnseededNumberDictionary* dictionary = | 283 UnseededNumberDictionary* dictionary = |
| 286 isolate->heap()->non_monomorphic_cache(); | 284 isolate->heap()->non_monomorphic_cache(); |
| 287 int entry = dictionary->FindEntry(isolate, flags); | 285 int entry = dictionary->FindEntry(isolate, flags); |
| 288 ASSERT(entry != -1); | 286 ASSERT(entry != -1); |
| 289 Object* code = dictionary->ValueAt(entry); | 287 Object* code = dictionary->ValueAt(entry); |
| 290 // This might be called during the marking phase of the collector | 288 // This might be called during the marking phase of the collector |
| 291 // hence the unchecked cast. | 289 // hence the unchecked cast. |
| 292 return reinterpret_cast<Code*>(code); | 290 return reinterpret_cast<Code*>(code); |
| 293 } | 291 } |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 362 | 360 |
| 363 if (!receiver_map->is_shared()) { | 361 if (!receiver_map->is_shared()) { |
| 364 Map::UpdateCodeCache(receiver_map, name, ic); | 362 Map::UpdateCodeCache(receiver_map, name, ic); |
| 365 } | 363 } |
| 366 | 364 |
| 367 return ic; | 365 return ic; |
| 368 } | 366 } |
| 369 | 367 |
| 370 | 368 |
| 371 // TODO(verwaest): Change this method so it takes in a TypeHandleList. | 369 // TODO(verwaest): Change this method so it takes in a TypeHandleList. |
| 372 Handle<Code> PropertyICCompiler::ComputeLoadElementPolymorphic( | 370 Handle<Code> PropertyICCompiler::ComputeKeyedLoadPolymorphic( |
| 373 MapHandleList* receiver_maps) { | 371 MapHandleList* receiver_maps) { |
| 374 Isolate* isolate = receiver_maps->at(0)->GetIsolate(); | 372 Isolate* isolate = receiver_maps->at(0)->GetIsolate(); |
| 375 Code::Flags flags = Code::ComputeFlags(Code::KEYED_LOAD_IC, POLYMORPHIC); | 373 Code::Flags flags = Code::ComputeFlags(Code::KEYED_LOAD_IC, POLYMORPHIC); |
| 376 Handle<PolymorphicCodeCache> cache = | 374 Handle<PolymorphicCodeCache> cache = |
| 377 isolate->factory()->polymorphic_code_cache(); | 375 isolate->factory()->polymorphic_code_cache(); |
| 378 Handle<Object> probe = cache->Lookup(receiver_maps, flags); | 376 Handle<Object> probe = cache->Lookup(receiver_maps, flags); |
| 379 if (probe->IsCode()) return Handle<Code>::cast(probe); | 377 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 380 | 378 |
| 381 TypeHandleList types(receiver_maps->length()); | 379 TypeHandleList types(receiver_maps->length()); |
| 382 for (int i = 0; i < receiver_maps->length(); i++) { | 380 for (int i = 0; i < receiver_maps->length(); i++) { |
| 383 types.Add(HeapType::Class(receiver_maps->at(i), isolate)); | 381 types.Add(HeapType::Class(receiver_maps->at(i), isolate)); |
| 384 } | 382 } |
| 385 CodeHandleList handlers(receiver_maps->length()); | 383 CodeHandleList handlers(receiver_maps->length()); |
| 386 IndexedHandlerCompiler compiler(isolate); | 384 ElementHandlerCompiler compiler(isolate); |
| 387 compiler.CompileElementHandlers(receiver_maps, &handlers); | 385 compiler.CompileElementHandlers(receiver_maps, &handlers); |
| 388 PropertyICCompiler ic_compiler(isolate, Code::KEYED_LOAD_IC); | 386 PropertyICCompiler ic_compiler(isolate, Code::KEYED_LOAD_IC); |
| 389 Handle<Code> code = ic_compiler.CompilePolymorphic( | 387 Handle<Code> code = ic_compiler.CompilePolymorphic( |
| 390 &types, &handlers, isolate->factory()->empty_string(), Code::NORMAL, | 388 &types, &handlers, isolate->factory()->empty_string(), Code::NORMAL, |
| 391 ELEMENT); | 389 ELEMENT); |
| 392 | 390 |
| 393 isolate->counters()->keyed_load_polymorphic_stubs()->Increment(); | 391 isolate->counters()->keyed_load_polymorphic_stubs()->Increment(); |
| 394 | 392 |
| 395 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); | 393 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); |
| 396 return code; | 394 return code; |
| 397 } | 395 } |
| 398 | 396 |
| 399 | 397 |
| 400 Handle<Code> PropertyICCompiler::ComputePolymorphicIC( | 398 Handle<Code> PropertyICCompiler::ComputePolymorphic( |
| 401 Code::Kind kind, TypeHandleList* types, CodeHandleList* handlers, | 399 Code::Kind kind, TypeHandleList* types, CodeHandleList* handlers, |
| 402 int valid_types, Handle<Name> name, ExtraICState extra_ic_state) { | 400 int valid_types, Handle<Name> name, ExtraICState extra_ic_state) { |
| 403 Handle<Code> handler = handlers->at(0); | 401 Handle<Code> handler = handlers->at(0); |
| 404 Code::StubType type = valid_types == 1 ? handler->type() : Code::NORMAL; | 402 Code::StubType type = valid_types == 1 ? handler->type() : Code::NORMAL; |
| 405 ASSERT(kind == Code::LOAD_IC || kind == Code::STORE_IC); | 403 ASSERT(kind == Code::LOAD_IC || kind == Code::STORE_IC); |
| 406 PropertyICCompiler ic_compiler(name->GetIsolate(), kind, extra_ic_state); | 404 PropertyICCompiler ic_compiler(name->GetIsolate(), kind, extra_ic_state); |
| 407 return ic_compiler.CompilePolymorphic(types, handlers, name, type, PROPERTY); | 405 return ic_compiler.CompilePolymorphic(types, handlers, name, type, PROPERTY); |
| 408 } | 406 } |
| 409 | 407 |
| 410 | 408 |
| 411 Handle<Code> PropertyICCompiler::ComputeStoreElementPolymorphic( | 409 Handle<Code> PropertyICCompiler::ComputeKeyedStorePolymorphic( |
| 412 MapHandleList* receiver_maps, KeyedAccessStoreMode store_mode, | 410 MapHandleList* receiver_maps, KeyedAccessStoreMode store_mode, |
| 413 StrictMode strict_mode) { | 411 StrictMode strict_mode) { |
| 414 Isolate* isolate = receiver_maps->at(0)->GetIsolate(); | 412 Isolate* isolate = receiver_maps->at(0)->GetIsolate(); |
| 415 ASSERT(store_mode == STANDARD_STORE || | 413 ASSERT(store_mode == STANDARD_STORE || |
| 416 store_mode == STORE_AND_GROW_NO_TRANSITION || | 414 store_mode == STORE_AND_GROW_NO_TRANSITION || |
| 417 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || | 415 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || |
| 418 store_mode == STORE_NO_TRANSITION_HANDLE_COW); | 416 store_mode == STORE_NO_TRANSITION_HANDLE_COW); |
| 419 Handle<PolymorphicCodeCache> cache = | 417 Handle<PolymorphicCodeCache> cache = |
| 420 isolate->factory()->polymorphic_code_cache(); | 418 isolate->factory()->polymorphic_code_cache(); |
| 421 ExtraICState extra_state = KeyedStoreIC::ComputeExtraICState( | 419 ExtraICState extra_state = KeyedStoreIC::ComputeExtraICState( |
| 422 strict_mode, store_mode); | 420 strict_mode, store_mode); |
| 423 Code::Flags flags = | 421 Code::Flags flags = |
| 424 Code::ComputeFlags(Code::KEYED_STORE_IC, POLYMORPHIC, extra_state); | 422 Code::ComputeFlags(Code::KEYED_STORE_IC, POLYMORPHIC, extra_state); |
| 425 Handle<Object> probe = cache->Lookup(receiver_maps, flags); | 423 Handle<Object> probe = cache->Lookup(receiver_maps, flags); |
| 426 if (probe->IsCode()) return Handle<Code>::cast(probe); | 424 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 427 | 425 |
| 428 PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state); | 426 PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state); |
| 429 Handle<Code> code = | 427 Handle<Code> code = |
| 430 compiler.CompileIndexedStorePolymorphic(receiver_maps, store_mode); | 428 compiler.CompileKeyedStorePolymorphic(receiver_maps, store_mode); |
| 431 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); | 429 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); |
| 432 return code; | 430 return code; |
| 433 } | 431 } |
| 434 | 432 |
| 435 | 433 |
| 436 void StubCache::Clear() { | 434 void StubCache::Clear() { |
| 437 Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal); | 435 Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal); |
| 438 for (int i = 0; i < kPrimaryTableSize; i++) { | 436 for (int i = 0; i < kPrimaryTableSize; i++) { |
| 439 primary_[i].key = isolate()->heap()->empty_string(); | 437 primary_[i].key = isolate()->heap()->empty_string(); |
| 440 primary_[i].map = NULL; | 438 primary_[i].map = NULL; |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 602 LookupIterator it(receiver, name, holder); | 600 LookupIterator it(receiver, name, holder); |
| 603 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 601 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 604 isolate, result, JSObject::GetProperty(&it)); | 602 isolate, result, JSObject::GetProperty(&it)); |
| 605 | 603 |
| 606 if (it.IsFound()) return *result; | 604 if (it.IsFound()) return *result; |
| 607 | 605 |
| 608 return ThrowReferenceError(isolate, Name::cast(args[0])); | 606 return ThrowReferenceError(isolate, Name::cast(args[0])); |
| 609 } | 607 } |
| 610 | 608 |
| 611 | 609 |
| 612 RUNTIME_FUNCTION(StoreInterceptorProperty) { | 610 RUNTIME_FUNCTION(StorePropertyWithInterceptor) { |
| 613 HandleScope scope(isolate); | 611 HandleScope scope(isolate); |
| 614 ASSERT(args.length() == 3); | 612 ASSERT(args.length() == 3); |
| 615 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 613 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
| 616 Handle<JSObject> receiver = args.at<JSObject>(0); | 614 Handle<JSObject> receiver = args.at<JSObject>(0); |
| 617 Handle<Name> name = args.at<Name>(1); | 615 Handle<Name> name = args.at<Name>(1); |
| 618 Handle<Object> value = args.at<Object>(2); | 616 Handle<Object> value = args.at<Object>(2); |
| 619 #ifdef DEBUG | 617 #ifdef DEBUG |
| 620 if (receiver->IsJSGlobalProxy()) { | 618 if (receiver->IsJSGlobalProxy()) { |
| 621 PrototypeIterator iter(isolate, receiver); | 619 PrototypeIterator iter(isolate, receiver); |
| 622 ASSERT(iter.IsAtEnd() || | 620 ASSERT(iter.IsAtEnd() || |
| 623 Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter)) | 621 Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter)) |
| 624 ->HasNamedInterceptor()); | 622 ->HasNamedInterceptor()); |
| 625 } else { | 623 } else { |
| 626 ASSERT(receiver->HasNamedInterceptor()); | 624 ASSERT(receiver->HasNamedInterceptor()); |
| 627 } | 625 } |
| 628 #endif | 626 #endif |
| 629 Handle<Object> result; | 627 Handle<Object> result; |
| 630 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 628 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 631 isolate, result, | 629 isolate, result, |
| 632 JSObject::SetProperty(receiver, name, value, ic.strict_mode())); | 630 JSObject::SetProperty(receiver, name, value, ic.strict_mode())); |
| 633 return *result; | 631 return *result; |
| 634 } | 632 } |
| 635 | 633 |
| 636 | 634 |
| 637 RUNTIME_FUNCTION(KeyedLoadPropertyWithInterceptor) { | 635 RUNTIME_FUNCTION(LoadElementWithInterceptor) { |
| 638 HandleScope scope(isolate); | 636 HandleScope scope(isolate); |
| 639 Handle<JSObject> receiver = args.at<JSObject>(0); | 637 Handle<JSObject> receiver = args.at<JSObject>(0); |
| 640 ASSERT(args.smi_at(1) >= 0); | 638 ASSERT(args.smi_at(1) >= 0); |
| 641 uint32_t index = args.smi_at(1); | 639 uint32_t index = args.smi_at(1); |
| 642 Handle<Object> result; | 640 Handle<Object> result; |
| 643 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 641 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 644 isolate, result, | 642 isolate, result, |
| 645 JSObject::GetElementWithInterceptor(receiver, receiver, index)); | 643 JSObject::GetElementWithInterceptor(receiver, receiver, index)); |
| 646 return *result; | 644 return *result; |
| 647 } | 645 } |
| (...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1081 const CallOptimization& call_optimization) { | 1079 const CallOptimization& call_optimization) { |
| 1082 Frontend(IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); | 1080 Frontend(IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); |
| 1083 Register values[] = { value() }; | 1081 Register values[] = { value() }; |
| 1084 GenerateFastApiCall( | 1082 GenerateFastApiCall( |
| 1085 masm(), call_optimization, handle(object->map()), | 1083 masm(), call_optimization, handle(object->map()), |
| 1086 receiver(), scratch1(), true, 1, values); | 1084 receiver(), scratch1(), true, 1, values); |
| 1087 return GetCode(kind(), Code::FAST, name); | 1085 return GetCode(kind(), Code::FAST, name); |
| 1088 } | 1086 } |
| 1089 | 1087 |
| 1090 | 1088 |
| 1091 Handle<Code> PropertyICCompiler::CompileIndexedStoreMonomorphic( | 1089 Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphic( |
| 1092 Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) { | 1090 Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) { |
| 1093 ElementsKind elements_kind = receiver_map->elements_kind(); | 1091 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 1094 bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE; | 1092 bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE; |
| 1095 Handle<Code> stub; | 1093 Handle<Code> stub; |
| 1096 if (receiver_map->has_fast_elements() || | 1094 if (receiver_map->has_fast_elements() || |
| 1097 receiver_map->has_external_array_elements() || | 1095 receiver_map->has_external_array_elements() || |
| 1098 receiver_map->has_fixed_typed_array_elements()) { | 1096 receiver_map->has_fixed_typed_array_elements()) { |
| 1099 stub = KeyedStoreFastElementStub(isolate(), is_jsarray, elements_kind, | 1097 stub = StoreFastElementStub(isolate(), is_jsarray, elements_kind, |
| 1100 store_mode).GetCode(); | 1098 store_mode).GetCode(); |
| 1101 } else { | 1099 } else { |
| 1102 stub = KeyedStoreElementStub(isolate(), is_jsarray, elements_kind, | 1100 stub = StoreElementStub(isolate(), is_jsarray, elements_kind, store_mode) |
| 1103 store_mode).GetCode(); | 1101 .GetCode(); |
| 1104 } | 1102 } |
| 1105 | 1103 |
| 1106 __ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK); | 1104 __ DispatchMap(receiver(), scratch1(), receiver_map, stub, DO_SMI_CHECK); |
| 1107 | 1105 |
| 1108 TailCallBuiltin(masm(), Builtins::kKeyedStoreIC_Miss); | 1106 TailCallBuiltin(masm(), Builtins::kKeyedStoreIC_Miss); |
| 1109 | 1107 |
| 1110 return GetCode(kind(), Code::NORMAL, factory()->empty_string()); | 1108 return GetCode(kind(), Code::NORMAL, factory()->empty_string()); |
| 1111 } | 1109 } |
| 1112 | 1110 |
| 1113 | 1111 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1148 Handle<Code> PropertyHandlerCompiler::GetCode(Code::Kind kind, | 1146 Handle<Code> PropertyHandlerCompiler::GetCode(Code::Kind kind, |
| 1149 Code::StubType type, | 1147 Code::StubType type, |
| 1150 Handle<Name> name) { | 1148 Handle<Name> name) { |
| 1151 Code::Flags flags = Code::ComputeHandlerFlags(kind, type, cache_holder()); | 1149 Code::Flags flags = Code::ComputeHandlerFlags(kind, type, cache_holder()); |
| 1152 Handle<Code> code = GetCodeWithFlags(flags, name); | 1150 Handle<Code> code = GetCodeWithFlags(flags, name); |
| 1153 PROFILE(isolate(), CodeCreateEvent(Logger::STUB_TAG, *code, *name)); | 1151 PROFILE(isolate(), CodeCreateEvent(Logger::STUB_TAG, *code, *name)); |
| 1154 return code; | 1152 return code; |
| 1155 } | 1153 } |
| 1156 | 1154 |
| 1157 | 1155 |
| 1158 void IndexedHandlerCompiler::CompileElementHandlers( | 1156 void ElementHandlerCompiler::CompileElementHandlers( |
| 1159 MapHandleList* receiver_maps, CodeHandleList* handlers) { | 1157 MapHandleList* receiver_maps, CodeHandleList* handlers) { |
| 1160 for (int i = 0; i < receiver_maps->length(); ++i) { | 1158 for (int i = 0; i < receiver_maps->length(); ++i) { |
| 1161 Handle<Map> receiver_map = receiver_maps->at(i); | 1159 Handle<Map> receiver_map = receiver_maps->at(i); |
| 1162 Handle<Code> cached_stub; | 1160 Handle<Code> cached_stub; |
| 1163 | 1161 |
| 1164 if ((receiver_map->instance_type() & kNotStringTag) == 0) { | 1162 if ((receiver_map->instance_type() & kNotStringTag) == 0) { |
| 1165 cached_stub = isolate()->builtins()->KeyedLoadIC_String(); | 1163 cached_stub = isolate()->builtins()->KeyedLoadIC_String(); |
| 1166 } else if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE) { | 1164 } else if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE) { |
| 1167 cached_stub = isolate()->builtins()->KeyedLoadIC_Slow(); | 1165 cached_stub = isolate()->builtins()->KeyedLoadIC_Slow(); |
| 1168 } else { | 1166 } else { |
| 1169 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; | 1167 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; |
| 1170 ElementsKind elements_kind = receiver_map->elements_kind(); | 1168 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 1171 | 1169 |
| 1172 if (IsFastElementsKind(elements_kind) || | 1170 if (IsFastElementsKind(elements_kind) || |
| 1173 IsExternalArrayElementsKind(elements_kind) || | 1171 IsExternalArrayElementsKind(elements_kind) || |
| 1174 IsFixedTypedArrayElementsKind(elements_kind)) { | 1172 IsFixedTypedArrayElementsKind(elements_kind)) { |
| 1175 cached_stub = | 1173 cached_stub = LoadFastElementStub(isolate(), is_js_array, elements_kind) |
| 1176 KeyedLoadFastElementStub(isolate(), | 1174 .GetCode(); |
| 1177 is_js_array, | |
| 1178 elements_kind).GetCode(); | |
| 1179 } else if (elements_kind == SLOPPY_ARGUMENTS_ELEMENTS) { | 1175 } else if (elements_kind == SLOPPY_ARGUMENTS_ELEMENTS) { |
| 1180 cached_stub = isolate()->builtins()->KeyedLoadIC_SloppyArguments(); | 1176 cached_stub = isolate()->builtins()->KeyedLoadIC_SloppyArguments(); |
| 1181 } else { | 1177 } else { |
| 1182 ASSERT(elements_kind == DICTIONARY_ELEMENTS); | 1178 ASSERT(elements_kind == DICTIONARY_ELEMENTS); |
| 1183 cached_stub = | 1179 cached_stub = LoadDictionaryElementStub(isolate()).GetCode(); |
| 1184 KeyedLoadDictionaryElementStub(isolate()).GetCode(); | |
| 1185 } | 1180 } |
| 1186 } | 1181 } |
| 1187 | 1182 |
| 1188 handlers->Add(cached_stub); | 1183 handlers->Add(cached_stub); |
| 1189 } | 1184 } |
| 1190 } | 1185 } |
| 1191 | 1186 |
| 1192 | 1187 |
| 1193 Handle<Code> PropertyICCompiler::CompileIndexedStorePolymorphic( | 1188 Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic( |
| 1194 MapHandleList* receiver_maps, KeyedAccessStoreMode store_mode) { | 1189 MapHandleList* receiver_maps, KeyedAccessStoreMode store_mode) { |
| 1195 // Collect MONOMORPHIC stubs for all |receiver_maps|. | 1190 // Collect MONOMORPHIC stubs for all |receiver_maps|. |
| 1196 CodeHandleList handlers(receiver_maps->length()); | 1191 CodeHandleList handlers(receiver_maps->length()); |
| 1197 MapHandleList transitioned_maps(receiver_maps->length()); | 1192 MapHandleList transitioned_maps(receiver_maps->length()); |
| 1198 for (int i = 0; i < receiver_maps->length(); ++i) { | 1193 for (int i = 0; i < receiver_maps->length(); ++i) { |
| 1199 Handle<Map> receiver_map(receiver_maps->at(i)); | 1194 Handle<Map> receiver_map(receiver_maps->at(i)); |
| 1200 Handle<Code> cached_stub; | 1195 Handle<Code> cached_stub; |
| 1201 Handle<Map> transitioned_map = | 1196 Handle<Map> transitioned_map = |
| 1202 receiver_map->FindTransitionedMap(receiver_maps); | 1197 receiver_map->FindTransitionedMap(receiver_maps); |
| 1203 | 1198 |
| 1204 // TODO(mvstanton): The code below is doing pessimistic elements | 1199 // TODO(mvstanton): The code below is doing pessimistic elements |
| 1205 // transitions. I would like to stop doing that and rely on Allocation Site | 1200 // transitions. I would like to stop doing that and rely on Allocation Site |
| 1206 // Tracking to do a better job of ensuring the data types are what they need | 1201 // Tracking to do a better job of ensuring the data types are what they need |
| 1207 // to be. Not all the elements are in place yet, pessimistic elements | 1202 // to be. Not all the elements are in place yet, pessimistic elements |
| 1208 // transitions are still important for performance. | 1203 // transitions are still important for performance. |
| 1209 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; | 1204 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; |
| 1210 ElementsKind elements_kind = receiver_map->elements_kind(); | 1205 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 1211 if (!transitioned_map.is_null()) { | 1206 if (!transitioned_map.is_null()) { |
| 1212 cached_stub = | 1207 cached_stub = |
| 1213 ElementsTransitionAndStoreStub(isolate(), elements_kind, | 1208 ElementsTransitionAndStoreStub(isolate(), elements_kind, |
| 1214 transitioned_map->elements_kind(), | 1209 transitioned_map->elements_kind(), |
| 1215 is_js_array, store_mode).GetCode(); | 1210 is_js_array, store_mode).GetCode(); |
| 1216 } else if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE) { | 1211 } else if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE) { |
| 1217 cached_stub = isolate()->builtins()->KeyedStoreIC_Slow(); | 1212 cached_stub = isolate()->builtins()->KeyedStoreIC_Slow(); |
| 1218 } else { | 1213 } else { |
| 1219 if (receiver_map->has_fast_elements() || | 1214 if (receiver_map->has_fast_elements() || |
| 1220 receiver_map->has_external_array_elements() || | 1215 receiver_map->has_external_array_elements() || |
| 1221 receiver_map->has_fixed_typed_array_elements()) { | 1216 receiver_map->has_fixed_typed_array_elements()) { |
| 1222 cached_stub = | 1217 cached_stub = StoreFastElementStub(isolate(), is_js_array, |
| 1223 KeyedStoreFastElementStub(isolate(), is_js_array, elements_kind, | 1218 elements_kind, store_mode).GetCode(); |
| 1224 store_mode).GetCode(); | |
| 1225 } else { | 1219 } else { |
| 1226 cached_stub = | 1220 cached_stub = StoreElementStub(isolate(), is_js_array, elements_kind, |
| 1227 KeyedStoreElementStub(isolate(), is_js_array, elements_kind, | 1221 store_mode).GetCode(); |
| 1228 store_mode).GetCode(); | |
| 1229 } | 1222 } |
| 1230 } | 1223 } |
| 1231 ASSERT(!cached_stub.is_null()); | 1224 ASSERT(!cached_stub.is_null()); |
| 1232 handlers.Add(cached_stub); | 1225 handlers.Add(cached_stub); |
| 1233 transitioned_maps.Add(transitioned_map); | 1226 transitioned_maps.Add(transitioned_map); |
| 1234 } | 1227 } |
| 1235 | 1228 |
| 1236 Handle<Code> code = CompileIndexedStorePolymorphic(receiver_maps, &handlers, | 1229 Handle<Code> code = CompileKeyedStorePolymorphic(receiver_maps, &handlers, |
| 1237 &transitioned_maps); | 1230 &transitioned_maps); |
| 1238 isolate()->counters()->keyed_store_polymorphic_stubs()->Increment(); | 1231 isolate()->counters()->keyed_store_polymorphic_stubs()->Increment(); |
| 1239 PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, 0)); | 1232 PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, 0)); |
| 1240 return code; | 1233 return code; |
| 1241 } | 1234 } |
| 1242 | 1235 |
| 1243 | 1236 |
| 1244 void IndexedHandlerCompiler::GenerateStoreDictionaryElement( | 1237 void ElementHandlerCompiler::GenerateStoreDictionaryElement( |
| 1245 MacroAssembler* masm) { | 1238 MacroAssembler* masm) { |
| 1246 KeyedStoreIC::GenerateSlow(masm); | 1239 KeyedStoreIC::GenerateSlow(masm); |
| 1247 } | 1240 } |
| 1248 | 1241 |
| 1249 | 1242 |
| 1250 CallOptimization::CallOptimization(LookupResult* lookup) { | 1243 CallOptimization::CallOptimization(LookupResult* lookup) { |
| 1251 if (lookup->IsFound() && | 1244 if (lookup->IsFound() && |
| 1252 lookup->IsCacheable() && | 1245 lookup->IsCacheable() && |
| 1253 lookup->IsConstantFunction()) { | 1246 lookup->IsConstantFunction()) { |
| 1254 // We only optimize constant function calls. | 1247 // We only optimize constant function calls. |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1357 Handle<FunctionTemplateInfo>( | 1350 Handle<FunctionTemplateInfo>( |
| 1358 FunctionTemplateInfo::cast(signature->receiver())); | 1351 FunctionTemplateInfo::cast(signature->receiver())); |
| 1359 } | 1352 } |
| 1360 } | 1353 } |
| 1361 | 1354 |
| 1362 is_simple_api_call_ = true; | 1355 is_simple_api_call_ = true; |
| 1363 } | 1356 } |
| 1364 | 1357 |
| 1365 | 1358 |
| 1366 } } // namespace v8::internal | 1359 } } // namespace v8::internal |
| OLD | NEW |