Commit e05eba85 authored by bak@chromium.org's avatar bak@chromium.org

- Added a map cache for literal objects. This will

  canonicalize maps for object literals. JSON objects
  with the same set of properties names will then
  share the same map.
  This reduces the amount of generated code associated 
  with object literals.
- Added a flag canonicalize_object_literal_maps.
  (default true)
- Changed the format of a function's literal array.
  Only the global context is now stored in the literal prefix.

Review URL: http://codereview.chromium.org/4078

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@371 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent ff4e9ea1
...@@ -146,7 +146,6 @@ ObjectLiteral::Property::Property(bool is_getter, FunctionLiteral* value) { ...@@ -146,7 +146,6 @@ ObjectLiteral::Property::Property(bool is_getter, FunctionLiteral* value) {
} }
void LabelCollector::AddLabel(Label* label) { void LabelCollector::AddLabel(Label* label) {
// Add the label to the collector, but discard duplicates. // Add the label to the collector, but discard duplicates.
int length = labels_->length(); int length = labels_->length();
......
...@@ -3811,7 +3811,8 @@ void Ia32CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { ...@@ -3811,7 +3811,8 @@ void Ia32CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
// therefore context dependent. // therefore context dependent.
class ObjectLiteralDeferred: public DeferredCode { class ObjectLiteralDeferred: public DeferredCode {
public: public:
ObjectLiteralDeferred(CodeGenerator* generator, ObjectLiteral* node) ObjectLiteralDeferred(CodeGenerator* generator,
ObjectLiteral* node)
: DeferredCode(generator), node_(node) { : DeferredCode(generator), node_(node) {
set_comment("[ ObjectLiteralDeferred"); set_comment("[ ObjectLiteralDeferred");
} }
...@@ -3838,7 +3839,6 @@ void ObjectLiteralDeferred::Generate() { ...@@ -3838,7 +3839,6 @@ void ObjectLiteralDeferred::Generate() {
void Ia32CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { void Ia32CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
Comment cmnt(masm_, "[ ObjectLiteral"); Comment cmnt(masm_, "[ ObjectLiteral");
ObjectLiteralDeferred* deferred = new ObjectLiteralDeferred(this, node); ObjectLiteralDeferred* deferred = new ObjectLiteralDeferred(this, node);
// Retrieve the literal array and check the allocated entry. // Retrieve the literal array and check the allocated entry.
...@@ -3867,6 +3867,7 @@ void Ia32CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { ...@@ -3867,6 +3867,7 @@ void Ia32CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
// Push the new cloned literal object as the result. // Push the new cloned literal object as the result.
__ push(eax); __ push(eax);
for (int i = 0; i < node->properties()->length(); i++) { for (int i = 0; i < node->properties()->length(); i++) {
ObjectLiteral::Property* property = node->properties()->at(i); ObjectLiteral::Property* property = node->properties()->at(i);
switch (property->kind()) { switch (property->kind()) {
......
...@@ -91,7 +91,8 @@ enum ContextLookupFlags { ...@@ -91,7 +91,8 @@ enum ContextLookupFlags {
V(EMPTY_SCRIPT_INDEX, Script, empty_script) \ V(EMPTY_SCRIPT_INDEX, Script, empty_script) \
V(SCRIPT_FUNCTION_INDEX, JSFunction, script_function) \ V(SCRIPT_FUNCTION_INDEX, JSFunction, script_function) \
V(CONTEXT_EXTENSION_FUNCTION_INDEX, JSFunction, context_extension_function) \ V(CONTEXT_EXTENSION_FUNCTION_INDEX, JSFunction, context_extension_function) \
V(OUT_OF_MEMORY_INDEX, Object, out_of_memory) V(OUT_OF_MEMORY_INDEX, Object, out_of_memory) \
V(MAP_CACHE_INDEX, Object, map_cache)
// JSFunctions are pairs (context, function code), sometimes also called // JSFunctions are pairs (context, function code), sometimes also called
// closures. A Context object is used to represent function contexts and // closures. A Context object is used to represent function contexts and
...@@ -207,6 +208,7 @@ class Context: public FixedArray { ...@@ -207,6 +208,7 @@ class Context: public FixedArray {
SCRIPT_FUNCTION_INDEX, SCRIPT_FUNCTION_INDEX,
CONTEXT_EXTENSION_FUNCTION_INDEX, CONTEXT_EXTENSION_FUNCTION_INDEX,
OUT_OF_MEMORY_INDEX, OUT_OF_MEMORY_INDEX,
MAP_CACHE_INDEX,
GLOBAL_CONTEXT_SLOTS GLOBAL_CONTEXT_SLOTS
}; };
......
...@@ -211,12 +211,8 @@ Handle<JSFunction> Factory::NewFunctionFromBoilerplate( ...@@ -211,12 +211,8 @@ Handle<JSFunction> Factory::NewFunctionFromBoilerplate(
// Store the object, regexp and array functions in the literals // Store the object, regexp and array functions in the literals
// array prefix. These functions will be used when creating // array prefix. These functions will be used when creating
// object, regexp and array literals in this function. // object, regexp and array literals in this function.
literals->set(JSFunction::kLiteralObjectFunctionIndex, literals->set(JSFunction::kLiteralGlobalContextIndex,
context->global_context()->object_function()); context->global_context());
literals->set(JSFunction::kLiteralRegExpFunctionIndex,
context->global_context()->regexp_function());
literals->set(JSFunction::kLiteralArrayFunctionIndex,
context->global_context()->array_function());
} }
result->set_literals(*literals); result->set_literals(*literals);
ASSERT(!result->IsBoilerplate()); ASSERT(!result->IsBoilerplate());
...@@ -558,6 +554,12 @@ Handle<JSObject> Factory::NewJSObject(Handle<JSFunction> constructor, ...@@ -558,6 +554,12 @@ Handle<JSObject> Factory::NewJSObject(Handle<JSFunction> constructor,
} }
Handle<JSObject> Factory::NewJSObjectFromMap(Handle<Map> map) {
CALL_HEAP_FUNCTION(Heap::AllocateJSObjectFromMap(*map, NOT_TENURED),
JSObject);
}
Handle<JSObject> Factory::NewObjectLiteral(int expected_number_of_properties) { Handle<JSObject> Factory::NewObjectLiteral(int expected_number_of_properties) {
Handle<Map> map = Handle<Map>(Top::object_function()->initial_map()); Handle<Map> map = Handle<Map>(Top::object_function()->initial_map());
map = Factory::CopyMap(map); map = Factory::CopyMap(map);
...@@ -749,6 +751,47 @@ Handle<JSFunction> Factory::CreateApiFunction( ...@@ -749,6 +751,47 @@ Handle<JSFunction> Factory::CreateApiFunction(
} }
Handle<MapCache> Factory::NewMapCache(int at_least_space_for) {
CALL_HEAP_FUNCTION(MapCache::Allocate(at_least_space_for), MapCache);
}
static Object* UpdateMapCacheWith(Context* context,
FixedArray* keys,
Map* map) {
Object* result = MapCache::cast(context->map_cache())->Put(keys, map);
if (!result->IsFailure()) context->set_map_cache(MapCache::cast(result));
return result;
}
Handle<MapCache> Factory::AddToMapCache(Handle<Context> context,
Handle<FixedArray> keys,
Handle<Map> map) {
CALL_HEAP_FUNCTION(UpdateMapCacheWith(*context, *keys, *map), MapCache);
}
Handle<Map> Factory::ObjectLiteralMapFromCache(Handle<Context> context,
Handle<FixedArray> keys) {
if (context->map_cache()->IsUndefined()) {
// Allocate the new map cache for the global context.
Handle<MapCache> new_cache = NewMapCache(24);
context->set_map_cache(*new_cache);
}
// Check to see whether there is a maching element in the cache.
Handle<MapCache> cache =
Handle<MapCache>(MapCache::cast(context->map_cache()));
Handle<Object> result = Handle<Object>(cache->Lookup(*keys));
if (result->IsMap()) return Handle<Map>::cast(result);
// Create a new map and add it to the cache.
Handle<Map> map =
CopyMap(Handle<Map>(context->object_function()->initial_map()));
AddToMapCache(context, keys, map);
return Handle<Map>(map);
}
void Factory::ConfigureInstance(Handle<FunctionTemplateInfo> desc, void Factory::ConfigureInstance(Handle<FunctionTemplateInfo> desc,
Handle<JSObject> instance, Handle<JSObject> instance,
bool* pending_exception) { bool* pending_exception) {
......
...@@ -167,6 +167,10 @@ class Factory : public AllStatic { ...@@ -167,6 +167,10 @@ class Factory : public AllStatic {
static Handle<JSObject> NewJSObject(Handle<JSFunction> constructor, static Handle<JSObject> NewJSObject(Handle<JSFunction> constructor,
PretenureFlag pretenure = NOT_TENURED); PretenureFlag pretenure = NOT_TENURED);
// JS objects are pretenured when allocated by the bootstrapper and
// runtime.
static Handle<JSObject> NewJSObjectFromMap(Handle<Map> map);
// Allocate a JS object representing an object literal. The object is // Allocate a JS object representing an object literal. The object is
// pretenured (allocated directly in the old generation). // pretenured (allocated directly in the old generation).
static Handle<JSObject> NewObjectLiteral(int expected_number_of_properties); static Handle<JSObject> NewObjectLiteral(int expected_number_of_properties);
...@@ -291,6 +295,12 @@ class Factory : public AllStatic { ...@@ -291,6 +295,12 @@ class Factory : public AllStatic {
static Handle<DebugInfo> NewDebugInfo(Handle<SharedFunctionInfo> shared); static Handle<DebugInfo> NewDebugInfo(Handle<SharedFunctionInfo> shared);
// Return a map using the map cache in the global context.
// The key the an ordered set of property names.
static Handle<Map> ObjectLiteralMapFromCache(Handle<Context> context,
Handle<FixedArray> keys);
private: private:
static Handle<JSFunction> NewFunctionHelper(Handle<String> name, static Handle<JSFunction> NewFunctionHelper(Handle<String> name,
Handle<Object> prototype); Handle<Object> prototype);
...@@ -302,6 +312,14 @@ class Factory : public AllStatic { ...@@ -302,6 +312,14 @@ class Factory : public AllStatic {
static Handle<JSFunction> BaseNewFunctionFromBoilerplate( static Handle<JSFunction> BaseNewFunctionFromBoilerplate(
Handle<JSFunction> boilerplate, Handle<JSFunction> boilerplate,
Handle<Map> function_map); Handle<Map> function_map);
// Create a new map cache.
static Handle<MapCache> NewMapCache(int at_least_space_for);
// Update the map cache in the global context with (keys, map)
static Handle<MapCache> AddToMapCache(Handle<Context> context,
Handle<FixedArray> keys,
Handle<Map> map);
}; };
......
...@@ -154,6 +154,9 @@ DEFINE_bool(cleanup_ics_at_gc, true, ...@@ -154,6 +154,9 @@ DEFINE_bool(cleanup_ics_at_gc, true,
DEFINE_bool(cleanup_caches_in_maps_at_gc, true, DEFINE_bool(cleanup_caches_in_maps_at_gc, true,
"Flush code caches in maps during mark compact cycle.") "Flush code caches in maps during mark compact cycle.")
DEFINE_bool(canonicalize_object_literal_maps, true,
"Canonicalize maps for object literals.")
// mksnapshot.cc // mksnapshot.cc
DEFINE_bool(h, false, "print this message") DEFINE_bool(h, false, "print this message")
......
...@@ -325,6 +325,11 @@ bool Object::IsCompilationCacheTable() { ...@@ -325,6 +325,11 @@ bool Object::IsCompilationCacheTable() {
} }
bool Object::IsMapCache() {
return IsHashTable();
}
bool Object::IsPrimitive() { bool Object::IsPrimitive() {
return IsOddball() || IsNumber() || IsString(); return IsOddball() || IsNumber() || IsString();
} }
...@@ -1112,6 +1117,7 @@ CAST_ACCESSOR(DescriptorArray) ...@@ -1112,6 +1117,7 @@ CAST_ACCESSOR(DescriptorArray)
CAST_ACCESSOR(Dictionary) CAST_ACCESSOR(Dictionary)
CAST_ACCESSOR(SymbolTable) CAST_ACCESSOR(SymbolTable)
CAST_ACCESSOR(CompilationCacheTable) CAST_ACCESSOR(CompilationCacheTable)
CAST_ACCESSOR(MapCache)
CAST_ACCESSOR(String) CAST_ACCESSOR(String)
CAST_ACCESSOR(SeqString) CAST_ACCESSOR(SeqString)
CAST_ACCESSOR(AsciiString) CAST_ACCESSOR(AsciiString)
......
...@@ -3923,6 +3923,11 @@ Object* JSFunction::SetInstanceClassName(String* name) { ...@@ -3923,6 +3923,11 @@ Object* JSFunction::SetInstanceClassName(String* name) {
} }
Context* JSFunction::GlobalContextFromLiterals(FixedArray* literals) {
return Context::cast(literals->get(JSFunction::kLiteralGlobalContextIndex));
}
void Oddball::OddballIterateBody(ObjectVisitor* v) { void Oddball::OddballIterateBody(ObjectVisitor* v) {
// Assumes all Object* members are contiguously allocated! // Assumes all Object* members are contiguously allocated!
IteratePointers(v, kToStringOffset, kToNumberOffset + kPointerSize); IteratePointers(v, kToStringOffset, kToNumberOffset + kPointerSize);
...@@ -5533,12 +5538,12 @@ Object* HashTable<prefix_size, element_size>::EnsureCapacity( ...@@ -5533,12 +5538,12 @@ Object* HashTable<prefix_size, element_size>::EnsureCapacity(
Object* obj = Allocate(nof * 2); Object* obj = Allocate(nof * 2);
if (obj->IsFailure()) return obj; if (obj->IsFailure()) return obj;
HashTable* dict = HashTable::cast(obj); HashTable* table = HashTable::cast(obj);
WriteBarrierMode mode = dict->GetWriteBarrierMode(); WriteBarrierMode mode = table->GetWriteBarrierMode();
// Copy prefix to new array. // Copy prefix to new array.
for (int i = kPrefixStartIndex; i < kPrefixStartIndex + prefix_size; i++) { for (int i = kPrefixStartIndex; i < kPrefixStartIndex + prefix_size; i++) {
dict->set(i, get(i), mode); table->set(i, get(i), mode);
} }
// Rehash the elements. // Rehash the elements.
uint32_t (*Hash)(Object* key) = key->GetHashFunction(); uint32_t (*Hash)(Object* key) = key->GetHashFunction();
...@@ -5547,14 +5552,14 @@ Object* HashTable<prefix_size, element_size>::EnsureCapacity( ...@@ -5547,14 +5552,14 @@ Object* HashTable<prefix_size, element_size>::EnsureCapacity(
Object* key = get(from_index); Object* key = get(from_index);
if (IsKey(key)) { if (IsKey(key)) {
uint32_t insertion_index = uint32_t insertion_index =
EntryToIndex(dict->FindInsertionEntry(key, Hash(key))); EntryToIndex(table->FindInsertionEntry(key, Hash(key)));
for (int j = 0; j < element_size; j++) { for (int j = 0; j < element_size; j++) {
dict->set(insertion_index + j, get(from_index + j), mode); table->set(insertion_index + j, get(from_index + j), mode);
} }
} }
} }
dict->SetNumberOfElements(NumberOfElements()); table->SetNumberOfElements(NumberOfElements());
return dict; return table;
} }
...@@ -5656,6 +5661,70 @@ Object* CompilationCacheTable::Put(String* src, Object* value) { ...@@ -5656,6 +5661,70 @@ Object* CompilationCacheTable::Put(String* src, Object* value) {
} }
// SymbolsKey used for HashTable where key is array of symbols.
class SymbolsKey : public HashTableKey {
public:
explicit SymbolsKey(FixedArray* symbols) {
symbols_ = symbols;
}
bool IsMatch(Object* other) {
if (!other->IsFixedArray()) return false;
FixedArray* o = FixedArray::cast(other);
int len = symbols_->length();
if (o->length() != len) return false;
for (int i = 0; i < len; i++) {
if (o->get(i) != symbols_->get(i)) return false;
}
return true;
}
uint32_t Hash() { return SymbolsHash(symbols_); }
HashFunction GetHashFunction() { return SymbolsHash; }
Object* GetObject() { return symbols_; }
static uint32_t SymbolsHash(Object* obj) {
FixedArray* symbols_ = FixedArray::cast(obj);
int len = symbols_->length();
uint32_t hash = 0;
for (int i = 0; i < len; i++) {
hash ^= String::cast(symbols_->get(i))->Hash();
}
return hash;
}
bool IsStringKey() { return false; }
FixedArray* symbols_;
};
Object* MapCache::Lookup(FixedArray* array) {
SymbolsKey key(array);
int entry = FindEntry(&key);
if (entry != -1) {
return get(EntryToIndex(entry) + 1);
} else {
return Heap::undefined_value();
}
}
Object* MapCache::Put(FixedArray* array, Map* value) {
SymbolsKey key(array);
Object* obj = EnsureCapacity(1, &key);
if (obj->IsFailure()) return obj;
MapCache* cache = reinterpret_cast<MapCache*>(obj);
int entry = cache->FindInsertionEntry(array, key.Hash());
cache->set(EntryToIndex(entry), array);
cache->set(EntryToIndex(entry) + 1, value);
cache->ElementAdded();
return cache;
}
Object* Dictionary::Allocate(int at_least_space_for) { Object* Dictionary::Allocate(int at_least_space_for) {
Object* obj = DictionaryBase::Allocate(at_least_space_for); Object* obj = DictionaryBase::Allocate(at_least_space_for);
// Initialize the next enumeration index. // Initialize the next enumeration index.
......
...@@ -619,6 +619,7 @@ class Object BASE_EMBEDDED { ...@@ -619,6 +619,7 @@ class Object BASE_EMBEDDED {
inline bool IsDictionary(); inline bool IsDictionary();
inline bool IsSymbolTable(); inline bool IsSymbolTable();
inline bool IsCompilationCacheTable(); inline bool IsCompilationCacheTable();
inline bool IsMapCache();
inline bool IsPrimitive(); inline bool IsPrimitive();
inline bool IsGlobalObject(); inline bool IsGlobalObject();
inline bool IsJSGlobalObject(); inline bool IsJSGlobalObject();
...@@ -1836,6 +1837,22 @@ class CompilationCacheTable: public HashTable<0, 2> { ...@@ -1836,6 +1837,22 @@ class CompilationCacheTable: public HashTable<0, 2> {
}; };
// MapCache.
//
// Maps keys that are a fixed array of symbols to a map.
// Used for canonicalize maps for object literals.
class MapCache: public HashTable<0, 2> {
public:
// Find cached value for a string key, otherwise return null.
Object* Lookup(FixedArray* key);
Object* Put(FixedArray* key, Map* value);
static inline MapCache* cast(Object* obj);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(MapCache);
};
// Dictionary for keeping properties and elements in slow case. // Dictionary for keeping properties and elements in slow case.
// //
// One element in the prefix is used for storing non-element // One element in the prefix is used for storing non-element
...@@ -2671,6 +2688,9 @@ class JSFunction: public JSObject { ...@@ -2671,6 +2688,9 @@ class JSFunction: public JSObject {
// Returns the number of allocated literals. // Returns the number of allocated literals.
int NumberOfLiterals(); int NumberOfLiterals();
// Retrieve the global context from a function's literal array.
static Context* GlobalContextFromLiterals(FixedArray* literals);
// Layout descriptors. // Layout descriptors.
static const int kPrototypeOrInitialMapOffset = JSObject::kHeaderSize; static const int kPrototypeOrInitialMapOffset = JSObject::kHeaderSize;
static const int kSharedFunctionInfoOffset = static const int kSharedFunctionInfoOffset =
...@@ -2680,11 +2700,8 @@ class JSFunction: public JSObject { ...@@ -2680,11 +2700,8 @@ class JSFunction: public JSObject {
static const int kSize = kLiteralsOffset + kPointerSize; static const int kSize = kLiteralsOffset + kPointerSize;
// Layout of the literals array. // Layout of the literals array.
static const int kLiteralsPrefixSize = 3; static const int kLiteralsPrefixSize = 1;
static const int kLiteralObjectFunctionIndex = 0; static const int kLiteralGlobalContextIndex = 0;
static const int kLiteralRegExpFunctionIndex = 1;
static const int kLiteralArrayFunctionIndex = 2;
private: private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSFunction); DISALLOW_IMPLICIT_CONSTRUCTORS(JSFunction);
}; };
......
...@@ -2738,8 +2738,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) { ...@@ -2738,8 +2738,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
NEW(ObjectLiteral::Property(key, value)); NEW(ObjectLiteral::Property(key, value));
// Count CONSTANT or COMPUTED properties to maintain the enumeration order. // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
if (IsBoilerplateProperty(property)) if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++;
number_of_boilerplate_properties++;
properties.Add(property); properties.Add(property);
// TODO(1240767): Consider allowing trailing comma. // TODO(1240767): Consider allowing trailing comma.
......
...@@ -97,6 +97,37 @@ static Object* Runtime_CloneObjectLiteralBoilerplate(Arguments args) { ...@@ -97,6 +97,37 @@ static Object* Runtime_CloneObjectLiteralBoilerplate(Arguments args) {
} }
static Handle<Map> ComputeObjectLiteralMap(
Handle<Context> context,
Handle<FixedArray> constant_properties,
bool &is_result_from_cache) {
if (FLAG_canonicalize_object_literal_maps) {
// First find prefix of consecutive symbol keys.
int number_of_properties = constant_properties->length()/2;
int number_of_symbol_keys = 0;
while ((number_of_symbol_keys < number_of_properties) &&
(constant_properties->get(number_of_symbol_keys*2)->IsSymbol())) {
number_of_symbol_keys++;
}
// Based on the number of prefix symbols key we decide whether
// to use the map cache in the global context.
const int kMaxKeys = 10;
if ((number_of_symbol_keys == number_of_properties)
&& (number_of_symbol_keys < kMaxKeys)) {
// Create the fixed array with the key.
Handle<FixedArray> keys = Factory::NewFixedArray(number_of_symbol_keys);
for (int i = 0; i < number_of_symbol_keys; i++) {
keys->set(i, constant_properties->get(i*2));
}
is_result_from_cache = true;
return Factory::ObjectLiteralMapFromCache(context, keys);
}
}
is_result_from_cache = false;
return Handle<Map>(context->object_function()->initial_map());
}
static Object* Runtime_CreateObjectLiteralBoilerplate(Arguments args) { static Object* Runtime_CreateObjectLiteralBoilerplate(Arguments args) {
HandleScope scope; HandleScope scope;
ASSERT(args.length() == 3); ASSERT(args.length() == 3);
...@@ -104,21 +135,24 @@ static Object* Runtime_CreateObjectLiteralBoilerplate(Arguments args) { ...@@ -104,21 +135,24 @@ static Object* Runtime_CreateObjectLiteralBoilerplate(Arguments args) {
Handle<FixedArray> literals = args.at<FixedArray>(0); Handle<FixedArray> literals = args.at<FixedArray>(0);
int literals_index = Smi::cast(args[1])->value(); int literals_index = Smi::cast(args[1])->value();
Handle<FixedArray> constant_properties = args.at<FixedArray>(2); Handle<FixedArray> constant_properties = args.at<FixedArray>(2);
Handle<Context> context =
Handle<Context>(JSFunction::GlobalContextFromLiterals(*literals));
bool is_result_from_cache;
Handle<Map> map = ComputeObjectLiteralMap(context,
constant_properties,
is_result_from_cache);
// Get the object function from the literals array. This is the // Get the object function from the literals array. This is the
// object function from the context in which the function was // object function from the context in which the function was
// created. We do not use the object function from the current // created. We do not use the object function from the current
// global context because this might be the object function from // global context because this might be the object function from
// another context which we should not have access to. // another context which we should not have access to.
const int kObjectFunIndex = JSFunction::kLiteralObjectFunctionIndex; Handle<JSObject> boilerplate = Factory::NewJSObjectFromMap(map);
Handle<JSFunction> constructor =
Handle<JSFunction>(JSFunction::cast(literals->get(kObjectFunIndex)));
Handle<JSObject> boilerplate = Factory::NewJSObject(constructor, TENURED);
{ // Add the constant propeties to the boilerplate. { // Add the constant propeties to the boilerplate.
int length = constant_properties->length(); int length = constant_properties->length();
OptimizedObjectForAddingMultipleProperties opt(boilerplate, true); OptimizedObjectForAddingMultipleProperties opt(boilerplate,
!is_result_from_cache);
for (int index = 0; index < length; index +=2) { for (int index = 0; index < length; index +=2) {
Handle<Object> key(constant_properties->get(index+0)); Handle<Object> key(constant_properties->get(index+0));
Handle<Object> value(constant_properties->get(index+1)); Handle<Object> value(constant_properties->get(index+1));
...@@ -160,9 +194,8 @@ static Object* Runtime_CreateArrayLiteral(Arguments args) { ...@@ -160,9 +194,8 @@ static Object* Runtime_CreateArrayLiteral(Arguments args) {
ASSERT(args.length() == 2); ASSERT(args.length() == 2);
CONVERT_CHECKED(FixedArray, elements, args[0]); CONVERT_CHECKED(FixedArray, elements, args[0]);
CONVERT_CHECKED(FixedArray, literals, args[1]); CONVERT_CHECKED(FixedArray, literals, args[1]);
const int kArrayFunIndex = JSFunction::kLiteralArrayFunctionIndex; JSFunction* constructor =
JSFunction* constructor = JSFunction::cast(literals->get(kArrayFunIndex)); JSFunction::GlobalContextFromLiterals(literals)->array_function();
// Create the JSArray. // Create the JSArray.
Object* object = Heap::AllocateJSObject(constructor); Object* object = Heap::AllocateJSObject(constructor);
if (object->IsFailure()) return object; if (object->IsFailure()) return object;
...@@ -699,10 +732,9 @@ static Object* Runtime_MaterializeRegExpLiteral(Arguments args) { ...@@ -699,10 +732,9 @@ static Object* Runtime_MaterializeRegExpLiteral(Arguments args) {
// created. We do not use the RegExp function from the current // created. We do not use the RegExp function from the current
// global context because this might be the RegExp function from // global context because this might be the RegExp function from
// another context which we should not have access to. // another context which we should not have access to.
const int kRegexpFunIndex = JSFunction::kLiteralRegExpFunctionIndex;
Handle<JSFunction> constructor = Handle<JSFunction> constructor =
Handle<JSFunction>(JSFunction::cast(literals->get(kRegexpFunIndex))); Handle<JSFunction>(
JSFunction::GlobalContextFromLiterals(*literals)->regexp_function());
// Compute the regular expression literal. // Compute the regular expression literal.
bool has_pending_exception; bool has_pending_exception;
Handle<Object> regexp = Handle<Object> regexp =
...@@ -839,12 +871,8 @@ static Object* Runtime_SetCode(Arguments args) { ...@@ -839,12 +871,8 @@ static Object* Runtime_SetCode(Arguments args) {
// Insert the object, regexp and array functions in the literals // Insert the object, regexp and array functions in the literals
// array prefix. These are the functions that will be used when // array prefix. These are the functions that will be used when
// creating object, regexp and array literals. // creating object, regexp and array literals.
literals->set(JSFunction::kLiteralObjectFunctionIndex, literals->set(JSFunction::kLiteralGlobalContextIndex,
context->global_context()->object_function()); context->global_context());
literals->set(JSFunction::kLiteralRegExpFunctionIndex,
context->global_context()->regexp_function());
literals->set(JSFunction::kLiteralArrayFunctionIndex,
context->global_context()->array_function());
} }
target->set_literals(*literals); target->set_literals(*literals);
} }
......
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