Commit 875dbe65 authored by kasperl@chromium.org's avatar kasperl@chromium.org

Re-enable ICs for loads and calls that skips a global object during

lookup through the prototype chain.
Review URL: http://codereview.chromium.org/155344

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2425 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 15754c6f
This diff is collapsed.
This diff is collapsed.
...@@ -2653,7 +2653,7 @@ void Dictionary<Shape, Key>::SetEntry(int entry, ...@@ -2653,7 +2653,7 @@ void Dictionary<Shape, Key>::SetEntry(int entry,
Object* key, Object* key,
Object* value, Object* value,
PropertyDetails details) { PropertyDetails details) {
ASSERT(!key->IsString() || details.index() > 0); ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
int index = HashTable<Shape, Key>::EntryToIndex(entry); int index = HashTable<Shape, Key>::EntryToIndex(entry);
WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(); WriteBarrierMode mode = FixedArray::GetWriteBarrierMode();
FixedArray::set(index, key, mode); FixedArray::set(index, key, mode);
......
...@@ -436,8 +436,7 @@ Object* JSObject::SetNormalizedProperty(String* name, ...@@ -436,8 +436,7 @@ Object* JSObject::SetNormalizedProperty(String* name,
store_value = Heap::AllocateJSGlobalPropertyCell(value); store_value = Heap::AllocateJSGlobalPropertyCell(value);
if (store_value->IsFailure()) return store_value; if (store_value->IsFailure()) return store_value;
} }
Object* dict = Object* dict = property_dictionary()->Add(name, store_value, details);
property_dictionary()->Add(name, store_value, details);
if (dict->IsFailure()) return dict; if (dict->IsFailure()) return dict;
set_properties(StringDictionary::cast(dict)); set_properties(StringDictionary::cast(dict));
return value; return value;
...@@ -1712,30 +1711,24 @@ void JSObject::LocalLookupRealNamedProperty(String* name, ...@@ -1712,30 +1711,24 @@ void JSObject::LocalLookupRealNamedProperty(String* name,
} else { } else {
int entry = property_dictionary()->FindEntry(name); int entry = property_dictionary()->FindEntry(name);
if (entry != StringDictionary::kNotFound) { if (entry != StringDictionary::kNotFound) {
// Make sure to disallow caching for uninitialized constants
// found in the dictionary-mode objects.
Object* value = property_dictionary()->ValueAt(entry); Object* value = property_dictionary()->ValueAt(entry);
if (IsGlobalObject()) { if (IsGlobalObject()) {
PropertyDetails d = property_dictionary()->DetailsAt(entry); PropertyDetails d = property_dictionary()->DetailsAt(entry);
if (d.IsDeleted()) { if (d.IsDeleted()) {
// We've skipped a global object during lookup, so we cannot
// use inline caching because the map of the global object
// doesn't change if the property should be re-added.
result->DisallowCaching();
result->NotFound(); result->NotFound();
return; return;
} }
value = JSGlobalPropertyCell::cast(value)->value(); value = JSGlobalPropertyCell::cast(value)->value();
ASSERT(result->IsLoaded()); ASSERT(result->IsLoaded());
} }
if (value->IsTheHole()) { // Make sure to disallow caching for uninitialized constants
result->DisallowCaching(); // found in the dictionary-mode objects.
} if (value->IsTheHole()) result->DisallowCaching();
result->DictionaryResult(this, entry); result->DictionaryResult(this, entry);
return; return;
} }
// Slow case object skipped during lookup. Do not use inline caching. // Slow case object skipped during lookup. Do not use inline caching.
result->DisallowCaching(); if (!IsGlobalObject()) result->DisallowCaching();
} }
result->NotFound(); result->NotFound();
} }
...@@ -6841,6 +6834,26 @@ Object* GlobalObject::GetPropertyCell(LookupResult* result) { ...@@ -6841,6 +6834,26 @@ Object* GlobalObject::GetPropertyCell(LookupResult* result) {
} }
Object* GlobalObject::EnsurePropertyCell(String* name) {
ASSERT(!HasFastProperties());
int entry = property_dictionary()->FindEntry(name);
if (entry == StringDictionary::kNotFound) {
Object* cell = Heap::AllocateJSGlobalPropertyCell(Heap::the_hole_value());
if (cell->IsFailure()) return cell;
PropertyDetails details(NONE, NORMAL);
details = details.AsDeleted();
Object* dictionary = property_dictionary()->Add(name, cell, details);
if (dictionary->IsFailure()) return dictionary;
set_properties(StringDictionary::cast(dictionary));
return cell;
} else {
Object* value = property_dictionary()->ValueAt(entry);
ASSERT(value->IsJSGlobalPropertyCell());
return value;
}
}
Object* SymbolTable::LookupString(String* string, Object** s) { Object* SymbolTable::LookupString(String* string, Object** s) {
SymbolKey key(string); SymbolKey key(string);
return LookupKey(&key, s); return LookupKey(&key, s);
...@@ -7200,7 +7213,7 @@ Object* Dictionary<Shape, Key>::AddEntry(Key key, ...@@ -7200,7 +7213,7 @@ Object* Dictionary<Shape, Key>::AddEntry(Key key,
uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash); uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash);
// Insert element at empty or deleted entry // Insert element at empty or deleted entry
if (details.index() == 0 && Shape::kIsEnumerable) { if (!details.IsDeleted() && details.index() == 0 && Shape::kIsEnumerable) {
// Assign an enumeration index to the property and update // Assign an enumeration index to the property and update
// SetNextEnumerationIndex. // SetNextEnumerationIndex.
int index = NextEnumerationIndex(); int index = NextEnumerationIndex();
...@@ -7273,7 +7286,9 @@ int Dictionary<Shape, Key>::NumberOfElementsFilterAttributes( ...@@ -7273,7 +7286,9 @@ int Dictionary<Shape, Key>::NumberOfElementsFilterAttributes(
for (int i = 0; i < capacity; i++) { for (int i = 0; i < capacity; i++) {
Object* k = HashTable<Shape, Key>::KeyAt(i); Object* k = HashTable<Shape, Key>::KeyAt(i);
if (HashTable<Shape, Key>::IsKey(k)) { if (HashTable<Shape, Key>::IsKey(k)) {
PropertyAttributes attr = DetailsAt(i).attributes(); PropertyDetails details = DetailsAt(i);
if (details.IsDeleted()) continue;
PropertyAttributes attr = details.attributes();
if ((attr & filter) == 0) result++; if ((attr & filter) == 0) result++;
} }
} }
...@@ -7297,7 +7312,9 @@ void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage, ...@@ -7297,7 +7312,9 @@ void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage,
for (int i = 0; i < capacity; i++) { for (int i = 0; i < capacity; i++) {
Object* k = HashTable<Shape, Key>::KeyAt(i); Object* k = HashTable<Shape, Key>::KeyAt(i);
if (HashTable<Shape, Key>::IsKey(k)) { if (HashTable<Shape, Key>::IsKey(k)) {
PropertyAttributes attr = DetailsAt(i).attributes(); PropertyDetails details = DetailsAt(i);
if (details.IsDeleted()) continue;
PropertyAttributes attr = details.attributes();
if ((attr & filter) == 0) storage->set(index++, k); if ((attr & filter) == 0) storage->set(index++, k);
} }
} }
...@@ -7315,13 +7332,12 @@ void StringDictionary::CopyEnumKeysTo(FixedArray* storage, ...@@ -7315,13 +7332,12 @@ void StringDictionary::CopyEnumKeysTo(FixedArray* storage,
Object* k = KeyAt(i); Object* k = KeyAt(i);
if (IsKey(k)) { if (IsKey(k)) {
PropertyDetails details = DetailsAt(i); PropertyDetails details = DetailsAt(i);
if (!details.IsDontEnum()) { if (details.IsDeleted() || details.IsDontEnum()) continue;
storage->set(index, k); storage->set(index, k);
sort_array->set(index, sort_array->set(index,
Smi::FromInt(details.index()), Smi::FromInt(details.index()),
SKIP_WRITE_BARRIER); SKIP_WRITE_BARRIER);
index++; index++;
}
} }
} }
storage->SortPairs(sort_array, sort_array->length()); storage->SortPairs(sort_array, sort_array->length());
...@@ -7338,6 +7354,8 @@ void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage) { ...@@ -7338,6 +7354,8 @@ void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage) {
for (int i = 0; i < capacity; i++) { for (int i = 0; i < capacity; i++) {
Object* k = HashTable<Shape, Key>::KeyAt(i); Object* k = HashTable<Shape, Key>::KeyAt(i);
if (HashTable<Shape, Key>::IsKey(k)) { if (HashTable<Shape, Key>::IsKey(k)) {
PropertyDetails details = DetailsAt(i);
if (details.IsDeleted()) continue;
storage->set(index++, k); storage->set(index++, k);
} }
} }
......
...@@ -3240,6 +3240,9 @@ class GlobalObject: public JSObject { ...@@ -3240,6 +3240,9 @@ class GlobalObject: public JSObject {
// Retrieve the property cell used to store a property. // Retrieve the property cell used to store a property.
Object* GetPropertyCell(LookupResult* result); Object* GetPropertyCell(LookupResult* result);
// Ensure that the global object has a cell for the given property name.
Object* EnsurePropertyCell(String* name);
// Casting. // Casting.
static inline GlobalObject* cast(Object* obj); static inline GlobalObject* cast(Object* obj);
......
...@@ -450,7 +450,7 @@ Object* StubCache::ComputeCallConstant(int argc, ...@@ -450,7 +450,7 @@ Object* StubCache::ComputeCallConstant(int argc,
if (!function->is_compiled()) return Failure::InternalError(); if (!function->is_compiled()) return Failure::InternalError();
// Compile the stub - only create stubs for fully compiled functions. // Compile the stub - only create stubs for fully compiled functions.
CallStubCompiler compiler(argc, in_loop); CallStubCompiler compiler(argc, in_loop);
code = compiler.CompileCallConstant(object, holder, function, check); code = compiler.CompileCallConstant(object, holder, function, name, check);
if (code->IsFailure()) return code; if (code->IsFailure()) return code;
ASSERT_EQ(flags, Code::cast(code)->flags()); ASSERT_EQ(flags, Code::cast(code)->flags());
LOG(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name)); LOG(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name));
...@@ -957,6 +957,10 @@ Object* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) { ...@@ -957,6 +957,10 @@ Object* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
Object* StubCompiler::GetCodeWithFlags(Code::Flags flags, const char* name) { Object* StubCompiler::GetCodeWithFlags(Code::Flags flags, const char* name) {
// Check for allocation failures during stub compilation.
if (failure_->IsFailure()) return failure_;
// Create code object in the heap.
CodeDesc desc; CodeDesc desc;
masm_.GetCode(&desc); masm_.GetCode(&desc);
Object* result = Heap::CreateCode(desc, NULL, flags, masm_.CodeObject()); Object* result = Heap::CreateCode(desc, NULL, flags, masm_.CodeObject());
......
...@@ -324,7 +324,7 @@ class StubCompiler BASE_EMBEDDED { ...@@ -324,7 +324,7 @@ class StubCompiler BASE_EMBEDDED {
JSARRAY_HAS_FAST_ELEMENTS_CHECK JSARRAY_HAS_FAST_ELEMENTS_CHECK
}; };
StubCompiler() : scope_(), masm_(NULL, 256) { } StubCompiler() : scope_(), masm_(NULL, 256), failure_(NULL) { }
Object* CompileCallInitialize(Code::Flags flags); Object* CompileCallInitialize(Code::Flags flags);
Object* CompileCallPreMonomorphic(Code::Flags flags); Object* CompileCallPreMonomorphic(Code::Flags flags);
...@@ -344,40 +344,7 @@ class StubCompiler BASE_EMBEDDED { ...@@ -344,40 +344,7 @@ class StubCompiler BASE_EMBEDDED {
static void GenerateFastPropertyLoad(MacroAssembler* masm, static void GenerateFastPropertyLoad(MacroAssembler* masm,
Register dst, Register src, Register dst, Register src,
JSObject* holder, int index); JSObject* holder, int index);
static void GenerateLoadField(MacroAssembler* masm,
JSObject* object,
JSObject* holder,
Register receiver,
Register scratch1,
Register scratch2,
int index,
Label* miss_label);
static void GenerateLoadCallback(MacroAssembler* masm,
JSObject* object,
JSObject* holder,
Register receiver,
Register name,
Register scratch1,
Register scratch2,
AccessorInfo* callback,
Label* miss_label);
static void GenerateLoadConstant(MacroAssembler* masm,
JSObject* object,
JSObject* holder,
Register receiver,
Register scratch1,
Register scratch2,
Object* value,
Label* miss_label);
static void GenerateLoadInterceptor(MacroAssembler* masm,
JSObject* object,
JSObject* holder,
Smi* lookup_hint,
Register receiver,
Register name,
Register scratch1,
Register scratch2,
Label* miss_label);
static void GenerateLoadArrayLength(MacroAssembler* masm, static void GenerateLoadArrayLength(MacroAssembler* masm,
Register receiver, Register receiver,
Register scratch, Register scratch,
...@@ -412,10 +379,60 @@ class StubCompiler BASE_EMBEDDED { ...@@ -412,10 +379,60 @@ class StubCompiler BASE_EMBEDDED {
Object* GetCodeWithFlags(Code::Flags flags, String* name); Object* GetCodeWithFlags(Code::Flags flags, String* name);
MacroAssembler* masm() { return &masm_; } MacroAssembler* masm() { return &masm_; }
void set_failure(Failure* failure) { failure_ = failure; }
// Check the integrity of the prototype chain to make sure that the
// current IC is still valid.
Register CheckPrototypes(JSObject* object,
Register object_reg,
JSObject* holder,
Register holder_reg,
Register scratch,
String* name,
Label* miss);
void GenerateLoadField(JSObject* object,
JSObject* holder,
Register receiver,
Register scratch1,
Register scratch2,
int index,
String* name,
Label* miss);
void GenerateLoadCallback(JSObject* object,
JSObject* holder,
Register receiver,
Register name_reg,
Register scratch1,
Register scratch2,
AccessorInfo* callback,
String* name,
Label* miss);
void GenerateLoadConstant(JSObject* object,
JSObject* holder,
Register receiver,
Register scratch1,
Register scratch2,
Object* value,
String* name,
Label* miss);
void GenerateLoadInterceptor(JSObject* object,
JSObject* holder,
Smi* lookup_hint,
Register receiver,
Register name_reg,
Register scratch1,
Register scratch2,
String* name,
Label* miss);
private: private:
HandleScope scope_; HandleScope scope_;
MacroAssembler masm_; MacroAssembler masm_;
Failure* failure_;
}; };
...@@ -518,6 +535,7 @@ class CallStubCompiler: public StubCompiler { ...@@ -518,6 +535,7 @@ class CallStubCompiler: public StubCompiler {
Object* CompileCallConstant(Object* object, Object* CompileCallConstant(Object* object,
JSObject* holder, JSObject* holder,
JSFunction* function, JSFunction* function,
String* name,
CheckType check); CheckType check);
Object* CompileCallInterceptor(Object* object, Object* CompileCallInterceptor(Object* object,
JSObject* holder, JSObject* holder,
......
...@@ -42,7 +42,8 @@ namespace internal { ...@@ -42,7 +42,8 @@ namespace internal {
Object* CallStubCompiler::CompileCallConstant(Object* a, Object* CallStubCompiler::CompileCallConstant(Object* a,
JSObject* b, JSObject* b,
JSFunction* c, JSFunction* c,
StubCompiler::CheckType d) { String* d,
StubCompiler::CheckType e) {
UNIMPLEMENTED(); UNIMPLEMENTED();
return NULL; return NULL;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment