| Index: src/stub-cache.cc
|
| diff --git a/src/stub-cache.cc b/src/stub-cache.cc
|
| index 2eb65d66659d9ef4a09ab5a19a008cb47bb6cb37..884eac24314328fbd62ddbe08cacd602a75d1204 100644
|
| --- a/src/stub-cache.cc
|
| +++ b/src/stub-cache.cc
|
| @@ -31,6 +31,7 @@
|
| #include "arguments.h"
|
| #include "ic-inl.h"
|
| #include "stub-cache.h"
|
| +#include "vm-state-inl.h"
|
|
|
| namespace v8 {
|
| namespace internal {
|
| @@ -429,6 +430,27 @@ MaybeObject* StubCache::ComputeKeyedLoadFunctionPrototype(
|
| }
|
|
|
|
|
| +MaybeObject* StubCache::ComputeKeyedLoadSpecialized(JSObject* receiver) {
|
| + Code::Flags flags =
|
| + Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, NORMAL);
|
| + String* name = isolate_->heap()->KeyedLoadSpecialized_symbol();
|
| + Object* code = receiver->map()->FindInCodeCache(name, flags);
|
| + if (code->IsUndefined()) {
|
| + KeyedLoadStubCompiler compiler;
|
| + { MaybeObject* maybe_code = compiler.CompileLoadSpecialized(receiver);
|
| + if (!maybe_code->ToObject(&code)) return maybe_code;
|
| + }
|
| + PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), 0));
|
| + Object* result;
|
| + { MaybeObject* maybe_result =
|
| + receiver->UpdateMapCodeCache(name, Code::cast(code));
|
| + if (!maybe_result->ToObject(&result)) return maybe_result;
|
| + }
|
| + }
|
| + return code;
|
| +}
|
| +
|
| +
|
| MaybeObject* StubCache::ComputeStoreField(String* name,
|
| JSObject* receiver,
|
| int field_index,
|
| @@ -453,6 +475,27 @@ MaybeObject* StubCache::ComputeStoreField(String* name,
|
| }
|
|
|
|
|
| +MaybeObject* StubCache::ComputeKeyedStoreSpecialized(JSObject* receiver) {
|
| + Code::Flags flags =
|
| + Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, NORMAL);
|
| + String* name = isolate_->heap()->KeyedStoreSpecialized_symbol();
|
| + Object* code = receiver->map()->FindInCodeCache(name, flags);
|
| + if (code->IsUndefined()) {
|
| + KeyedStoreStubCompiler compiler;
|
| + { MaybeObject* maybe_code = compiler.CompileStoreSpecialized(receiver);
|
| + if (!maybe_code->ToObject(&code)) return maybe_code;
|
| + }
|
| + PROFILE(CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, Code::cast(code), 0));
|
| + Object* result;
|
| + { MaybeObject* maybe_result =
|
| + receiver->UpdateMapCodeCache(name, Code::cast(code));
|
| + if (!maybe_result->ToObject(&result)) return maybe_result;
|
| + }
|
| + }
|
| + return code;
|
| +}
|
| +
|
| +
|
| MaybeObject* StubCache::ComputeStoreNormal() {
|
| return isolate_->builtins()->builtin(Builtins::StoreIC_Normal);
|
| }
|
| @@ -565,13 +608,13 @@ MaybeObject* StubCache::ComputeCallConstant(int argc,
|
| JSObject* map_holder = IC::GetCodeCacheHolder(object, cache_holder);
|
|
|
| // Compute check type based on receiver/holder.
|
| - StubCompiler::CheckType check = StubCompiler::RECEIVER_MAP_CHECK;
|
| + CheckType check = RECEIVER_MAP_CHECK;
|
| if (object->IsString()) {
|
| - check = StubCompiler::STRING_CHECK;
|
| + check = STRING_CHECK;
|
| } else if (object->IsNumber()) {
|
| - check = StubCompiler::NUMBER_CHECK;
|
| + check = NUMBER_CHECK;
|
| } else if (object->IsBoolean()) {
|
| - check = StubCompiler::BOOLEAN_CHECK;
|
| + check = BOOLEAN_CHECK;
|
| }
|
|
|
| Code::Flags flags =
|
| @@ -593,6 +636,7 @@ MaybeObject* StubCache::ComputeCallConstant(int argc,
|
| compiler.CompileCallConstant(object, holder, function, name, check);
|
| if (!maybe_code->ToObject(&code)) return maybe_code;
|
| }
|
| + Code::cast(code)->set_check_type(check);
|
| ASSERT_EQ(flags, Code::cast(code)->flags());
|
| PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG),
|
| Code::cast(code), name));
|
| @@ -964,6 +1008,48 @@ void StubCache::Clear() {
|
| }
|
|
|
|
|
| +void StubCache::CollectMatchingMaps(ZoneMapList* types,
|
| + String* name,
|
| + Code::Flags flags) {
|
| + for (int i = 0; i < kPrimaryTableSize; i++) {
|
| + if (primary_[i].key == name) {
|
| + Map* map = primary_[i].value->FindFirstMap();
|
| + // Map can be NULL, if the stub is constant function call
|
| + // with a primitive receiver.
|
| + if (map == NULL) continue;
|
| +
|
| + int offset = PrimaryOffset(name, flags, map);
|
| + if (entry(primary_, offset) == &primary_[i]) {
|
| + types->Add(Handle<Map>(map));
|
| + }
|
| + }
|
| + }
|
| +
|
| + for (int i = 0; i < kSecondaryTableSize; i++) {
|
| + if (secondary_[i].key == name) {
|
| + Map* map = secondary_[i].value->FindFirstMap();
|
| + // Map can be NULL, if the stub is constant function call
|
| + // with a primitive receiver.
|
| + if (map == NULL) continue;
|
| +
|
| + // Lookup in primary table and skip duplicates.
|
| + int primary_offset = PrimaryOffset(name, flags, map);
|
| + Entry* primary_entry = entry(primary_, primary_offset);
|
| + if (primary_entry->key == name) {
|
| + Map* primary_map = primary_entry->value->FindFirstMap();
|
| + if (map == primary_map) continue;
|
| + }
|
| +
|
| + // Lookup in secondary table and add matches.
|
| + int offset = SecondaryOffset(name, flags, primary_offset);
|
| + if (entry(secondary_, offset) == &secondary_[i]) {
|
| + types->Add(Handle<Map>(map));
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| // ------------------------------------------------------------------------
|
| // StubCompiler implementation.
|
|
|
| @@ -982,9 +1068,7 @@ MaybeObject* LoadCallbackProperty(RUNTIME_CALLING_CONVENTION) {
|
| {
|
| // Leaving JavaScript.
|
| VMState state(isolate, EXTERNAL);
|
| -#ifdef ENABLE_LOGGING_AND_PROFILING
|
| - state.set_external_callback(getter_address);
|
| -#endif
|
| + ExternalCallbackScope call_scope(isolate, getter_address);
|
| result = fun(v8::Utils::ToLocal(args.at<String>(4)), info);
|
| }
|
| RETURN_IF_SCHEDULED_EXCEPTION(isolate);
|
| @@ -1009,9 +1093,7 @@ MaybeObject* StoreCallbackProperty(RUNTIME_CALLING_CONVENTION) {
|
| {
|
| // Leaving JavaScript.
|
| VMState state(isolate, EXTERNAL);
|
| -#ifdef ENABLE_LOGGING_AND_PROFILING
|
| - state.set_external_callback(setter_address);
|
| -#endif
|
| + ExternalCallbackScope call_scope(isolate, setter_address);
|
| fun(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
|
| }
|
| RETURN_IF_SCHEDULED_EXCEPTION(isolate);
|
|
|