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,
Object* key,
Object* value,
PropertyDetails details) {
ASSERT(!key->IsString() || details.index() > 0);
ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
int index = HashTable<Shape, Key>::EntryToIndex(entry);
WriteBarrierMode mode = FixedArray::GetWriteBarrierMode();
FixedArray::set(index, key, mode);
......
......@@ -436,8 +436,7 @@ Object* JSObject::SetNormalizedProperty(String* name,
store_value = Heap::AllocateJSGlobalPropertyCell(value);
if (store_value->IsFailure()) return store_value;
}
Object* dict =
property_dictionary()->Add(name, store_value, details);
Object* dict = property_dictionary()->Add(name, store_value, details);
if (dict->IsFailure()) return dict;
set_properties(StringDictionary::cast(dict));
return value;
......@@ -1712,30 +1711,24 @@ void JSObject::LocalLookupRealNamedProperty(String* name,
} else {
int entry = property_dictionary()->FindEntry(name);
if (entry != StringDictionary::kNotFound) {
// Make sure to disallow caching for uninitialized constants
// found in the dictionary-mode objects.
Object* value = property_dictionary()->ValueAt(entry);
if (IsGlobalObject()) {
PropertyDetails d = property_dictionary()->DetailsAt(entry);
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();
return;
}
value = JSGlobalPropertyCell::cast(value)->value();
ASSERT(result->IsLoaded());
}
if (value->IsTheHole()) {
result->DisallowCaching();
}
// Make sure to disallow caching for uninitialized constants
// found in the dictionary-mode objects.
if (value->IsTheHole()) result->DisallowCaching();
result->DictionaryResult(this, entry);
return;
}
// Slow case object skipped during lookup. Do not use inline caching.
result->DisallowCaching();
if (!IsGlobalObject()) result->DisallowCaching();
}
result->NotFound();
}
......@@ -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) {
SymbolKey key(string);
return LookupKey(&key, s);
......@@ -7200,7 +7213,7 @@ Object* Dictionary<Shape, Key>::AddEntry(Key key,
uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash);
// 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
// SetNextEnumerationIndex.
int index = NextEnumerationIndex();
......@@ -7273,7 +7286,9 @@ int Dictionary<Shape, Key>::NumberOfElementsFilterAttributes(
for (int i = 0; i < capacity; i++) {
Object* k = HashTable<Shape, Key>::KeyAt(i);
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++;
}
}
......@@ -7297,7 +7312,9 @@ void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage,
for (int i = 0; i < capacity; i++) {
Object* k = HashTable<Shape, Key>::KeyAt(i);
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);
}
}
......@@ -7315,13 +7332,12 @@ void StringDictionary::CopyEnumKeysTo(FixedArray* storage,
Object* k = KeyAt(i);
if (IsKey(k)) {
PropertyDetails details = DetailsAt(i);
if (!details.IsDontEnum()) {
storage->set(index, k);
sort_array->set(index,
Smi::FromInt(details.index()),
SKIP_WRITE_BARRIER);
index++;
}
if (details.IsDeleted() || details.IsDontEnum()) continue;
storage->set(index, k);
sort_array->set(index,
Smi::FromInt(details.index()),
SKIP_WRITE_BARRIER);
index++;
}
}
storage->SortPairs(sort_array, sort_array->length());
......@@ -7338,6 +7354,8 @@ void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage) {
for (int i = 0; i < capacity; i++) {
Object* k = HashTable<Shape, Key>::KeyAt(i);
if (HashTable<Shape, Key>::IsKey(k)) {
PropertyDetails details = DetailsAt(i);
if (details.IsDeleted()) continue;
storage->set(index++, k);
}
}
......
......@@ -3240,6 +3240,9 @@ class GlobalObject: public JSObject {
// Retrieve the property cell used to store a property.
Object* GetPropertyCell(LookupResult* result);
// Ensure that the global object has a cell for the given property name.
Object* EnsurePropertyCell(String* name);
// Casting.
static inline GlobalObject* cast(Object* obj);
......
......@@ -450,7 +450,7 @@ Object* StubCache::ComputeCallConstant(int argc,
if (!function->is_compiled()) return Failure::InternalError();
// Compile the stub - only create stubs for fully compiled functions.
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;
ASSERT_EQ(flags, Code::cast(code)->flags());
LOG(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name));
......@@ -957,6 +957,10 @@ Object* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
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;
masm_.GetCode(&desc);
Object* result = Heap::CreateCode(desc, NULL, flags, masm_.CodeObject());
......
......@@ -324,7 +324,7 @@ class StubCompiler BASE_EMBEDDED {
JSARRAY_HAS_FAST_ELEMENTS_CHECK
};
StubCompiler() : scope_(), masm_(NULL, 256) { }
StubCompiler() : scope_(), masm_(NULL, 256), failure_(NULL) { }
Object* CompileCallInitialize(Code::Flags flags);
Object* CompileCallPreMonomorphic(Code::Flags flags);
......@@ -344,40 +344,7 @@ class StubCompiler BASE_EMBEDDED {
static void GenerateFastPropertyLoad(MacroAssembler* masm,
Register dst, Register src,
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,
Register receiver,
Register scratch,
......@@ -412,10 +379,60 @@ class StubCompiler BASE_EMBEDDED {
Object* GetCodeWithFlags(Code::Flags flags, String* name);
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:
HandleScope scope_;
MacroAssembler masm_;
Failure* failure_;
};
......@@ -518,6 +535,7 @@ class CallStubCompiler: public StubCompiler {
Object* CompileCallConstant(Object* object,
JSObject* holder,
JSFunction* function,
String* name,
CheckType check);
Object* CompileCallInterceptor(Object* object,
JSObject* holder,
......
......@@ -42,7 +42,8 @@ namespace internal {
Object* CallStubCompiler::CompileCallConstant(Object* a,
JSObject* b,
JSFunction* c,
StubCompiler::CheckType d) {
String* d,
StubCompiler::CheckType e) {
UNIMPLEMENTED();
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