- 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
This commit is contained in:
parent
ff4e9ea134
commit
e05eba857e
@ -146,7 +146,6 @@ ObjectLiteral::Property::Property(bool is_getter, FunctionLiteral* value) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LabelCollector::AddLabel(Label* label) {
|
||||
// Add the label to the collector, but discard duplicates.
|
||||
int length = labels_->length();
|
||||
|
@ -3811,7 +3811,8 @@ void Ia32CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
|
||||
// therefore context dependent.
|
||||
class ObjectLiteralDeferred: public DeferredCode {
|
||||
public:
|
||||
ObjectLiteralDeferred(CodeGenerator* generator, ObjectLiteral* node)
|
||||
ObjectLiteralDeferred(CodeGenerator* generator,
|
||||
ObjectLiteral* node)
|
||||
: DeferredCode(generator), node_(node) {
|
||||
set_comment("[ ObjectLiteralDeferred");
|
||||
}
|
||||
@ -3838,7 +3839,6 @@ void ObjectLiteralDeferred::Generate() {
|
||||
|
||||
void Ia32CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
|
||||
Comment cmnt(masm_, "[ ObjectLiteral");
|
||||
|
||||
ObjectLiteralDeferred* deferred = new ObjectLiteralDeferred(this, node);
|
||||
|
||||
// Retrieve the literal array and check the allocated entry.
|
||||
@ -3867,6 +3867,7 @@ void Ia32CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
|
||||
// Push the new cloned literal object as the result.
|
||||
__ push(eax);
|
||||
|
||||
|
||||
for (int i = 0; i < node->properties()->length(); i++) {
|
||||
ObjectLiteral::Property* property = node->properties()->at(i);
|
||||
switch (property->kind()) {
|
||||
|
@ -91,7 +91,8 @@ enum ContextLookupFlags {
|
||||
V(EMPTY_SCRIPT_INDEX, Script, empty_script) \
|
||||
V(SCRIPT_FUNCTION_INDEX, JSFunction, script_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
|
||||
// closures. A Context object is used to represent function contexts and
|
||||
@ -207,6 +208,7 @@ class Context: public FixedArray {
|
||||
SCRIPT_FUNCTION_INDEX,
|
||||
CONTEXT_EXTENSION_FUNCTION_INDEX,
|
||||
OUT_OF_MEMORY_INDEX,
|
||||
MAP_CACHE_INDEX,
|
||||
GLOBAL_CONTEXT_SLOTS
|
||||
};
|
||||
|
||||
|
@ -211,12 +211,8 @@ Handle<JSFunction> Factory::NewFunctionFromBoilerplate(
|
||||
// Store the object, regexp and array functions in the literals
|
||||
// array prefix. These functions will be used when creating
|
||||
// object, regexp and array literals in this function.
|
||||
literals->set(JSFunction::kLiteralObjectFunctionIndex,
|
||||
context->global_context()->object_function());
|
||||
literals->set(JSFunction::kLiteralRegExpFunctionIndex,
|
||||
context->global_context()->regexp_function());
|
||||
literals->set(JSFunction::kLiteralArrayFunctionIndex,
|
||||
context->global_context()->array_function());
|
||||
literals->set(JSFunction::kLiteralGlobalContextIndex,
|
||||
context->global_context());
|
||||
}
|
||||
result->set_literals(*literals);
|
||||
ASSERT(!result->IsBoilerplate());
|
||||
@ -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<Map> map = Handle<Map>(Top::object_function()->initial_map());
|
||||
map = Factory::CopyMap(map);
|
||||
@ -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,
|
||||
Handle<JSObject> instance,
|
||||
bool* pending_exception) {
|
||||
|
@ -167,6 +167,10 @@ class Factory : public AllStatic {
|
||||
static Handle<JSObject> NewJSObject(Handle<JSFunction> constructor,
|
||||
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
|
||||
// pretenured (allocated directly in the old generation).
|
||||
static Handle<JSObject> NewObjectLiteral(int expected_number_of_properties);
|
||||
@ -291,6 +295,12 @@ class Factory : public AllStatic {
|
||||
|
||||
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:
|
||||
static Handle<JSFunction> NewFunctionHelper(Handle<String> name,
|
||||
Handle<Object> prototype);
|
||||
@ -302,6 +312,14 @@ class Factory : public AllStatic {
|
||||
static Handle<JSFunction> BaseNewFunctionFromBoilerplate(
|
||||
Handle<JSFunction> boilerplate,
|
||||
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,
|
||||
DEFINE_bool(cleanup_caches_in_maps_at_gc, true,
|
||||
"Flush code caches in maps during mark compact cycle.")
|
||||
|
||||
DEFINE_bool(canonicalize_object_literal_maps, true,
|
||||
"Canonicalize maps for object literals.")
|
||||
|
||||
// mksnapshot.cc
|
||||
DEFINE_bool(h, false, "print this message")
|
||||
|
||||
|
@ -325,6 +325,11 @@ bool Object::IsCompilationCacheTable() {
|
||||
}
|
||||
|
||||
|
||||
bool Object::IsMapCache() {
|
||||
return IsHashTable();
|
||||
}
|
||||
|
||||
|
||||
bool Object::IsPrimitive() {
|
||||
return IsOddball() || IsNumber() || IsString();
|
||||
}
|
||||
@ -1112,6 +1117,7 @@ CAST_ACCESSOR(DescriptorArray)
|
||||
CAST_ACCESSOR(Dictionary)
|
||||
CAST_ACCESSOR(SymbolTable)
|
||||
CAST_ACCESSOR(CompilationCacheTable)
|
||||
CAST_ACCESSOR(MapCache)
|
||||
CAST_ACCESSOR(String)
|
||||
CAST_ACCESSOR(SeqString)
|
||||
CAST_ACCESSOR(AsciiString)
|
||||
|
@ -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) {
|
||||
// Assumes all Object* members are contiguously allocated!
|
||||
IteratePointers(v, kToStringOffset, kToNumberOffset + kPointerSize);
|
||||
@ -5533,12 +5538,12 @@ Object* HashTable<prefix_size, element_size>::EnsureCapacity(
|
||||
|
||||
Object* obj = Allocate(nof * 2);
|
||||
if (obj->IsFailure()) return obj;
|
||||
HashTable* dict = HashTable::cast(obj);
|
||||
WriteBarrierMode mode = dict->GetWriteBarrierMode();
|
||||
HashTable* table = HashTable::cast(obj);
|
||||
WriteBarrierMode mode = table->GetWriteBarrierMode();
|
||||
|
||||
// Copy prefix to new array.
|
||||
for (int i = kPrefixStartIndex; i < kPrefixStartIndex + prefix_size; i++) {
|
||||
dict->set(i, get(i), mode);
|
||||
table->set(i, get(i), mode);
|
||||
}
|
||||
// Rehash the elements.
|
||||
uint32_t (*Hash)(Object* key) = key->GetHashFunction();
|
||||
@ -5547,14 +5552,14 @@ Object* HashTable<prefix_size, element_size>::EnsureCapacity(
|
||||
Object* key = get(from_index);
|
||||
if (IsKey(key)) {
|
||||
uint32_t insertion_index =
|
||||
EntryToIndex(dict->FindInsertionEntry(key, Hash(key)));
|
||||
EntryToIndex(table->FindInsertionEntry(key, Hash(key)));
|
||||
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());
|
||||
return dict;
|
||||
table->SetNumberOfElements(NumberOfElements());
|
||||
return table;
|
||||
}
|
||||
|
||||
|
||||
@ -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* obj = DictionaryBase::Allocate(at_least_space_for);
|
||||
// Initialize the next enumeration index.
|
||||
|
@ -619,6 +619,7 @@ class Object BASE_EMBEDDED {
|
||||
inline bool IsDictionary();
|
||||
inline bool IsSymbolTable();
|
||||
inline bool IsCompilationCacheTable();
|
||||
inline bool IsMapCache();
|
||||
inline bool IsPrimitive();
|
||||
inline bool IsGlobalObject();
|
||||
inline bool IsJSGlobalObject();
|
||||
@ -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.
|
||||
//
|
||||
// One element in the prefix is used for storing non-element
|
||||
@ -2671,6 +2688,9 @@ class JSFunction: public JSObject {
|
||||
// Returns the number of allocated literals.
|
||||
int NumberOfLiterals();
|
||||
|
||||
// Retrieve the global context from a function's literal array.
|
||||
static Context* GlobalContextFromLiterals(FixedArray* literals);
|
||||
|
||||
// Layout descriptors.
|
||||
static const int kPrototypeOrInitialMapOffset = JSObject::kHeaderSize;
|
||||
static const int kSharedFunctionInfoOffset =
|
||||
@ -2680,11 +2700,8 @@ class JSFunction: public JSObject {
|
||||
static const int kSize = kLiteralsOffset + kPointerSize;
|
||||
|
||||
// Layout of the literals array.
|
||||
static const int kLiteralsPrefixSize = 3;
|
||||
static const int kLiteralObjectFunctionIndex = 0;
|
||||
static const int kLiteralRegExpFunctionIndex = 1;
|
||||
static const int kLiteralArrayFunctionIndex = 2;
|
||||
|
||||
static const int kLiteralsPrefixSize = 1;
|
||||
static const int kLiteralGlobalContextIndex = 0;
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(JSFunction);
|
||||
};
|
||||
|
@ -2738,8 +2738,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
|
||||
NEW(ObjectLiteral::Property(key, value));
|
||||
|
||||
// Count CONSTANT or COMPUTED properties to maintain the enumeration order.
|
||||
if (IsBoilerplateProperty(property))
|
||||
number_of_boilerplate_properties++;
|
||||
if (IsBoilerplateProperty(property)) number_of_boilerplate_properties++;
|
||||
properties.Add(property);
|
||||
|
||||
// TODO(1240767): Consider allowing trailing comma.
|
||||
|
@ -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) {
|
||||
HandleScope scope;
|
||||
ASSERT(args.length() == 3);
|
||||
@ -104,21 +135,24 @@ static Object* Runtime_CreateObjectLiteralBoilerplate(Arguments args) {
|
||||
Handle<FixedArray> literals = args.at<FixedArray>(0);
|
||||
int literals_index = Smi::cast(args[1])->value();
|
||||
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
|
||||
// object function from the context in which the function was
|
||||
// created. We do not use the object function from the current
|
||||
// global context because this might be the object function from
|
||||
// another context which we should not have access to.
|
||||
const int kObjectFunIndex = JSFunction::kLiteralObjectFunctionIndex;
|
||||
Handle<JSFunction> constructor =
|
||||
Handle<JSFunction>(JSFunction::cast(literals->get(kObjectFunIndex)));
|
||||
|
||||
Handle<JSObject> boilerplate = Factory::NewJSObject(constructor, TENURED);
|
||||
|
||||
Handle<JSObject> boilerplate = Factory::NewJSObjectFromMap(map);
|
||||
{ // Add the constant propeties to the boilerplate.
|
||||
int length = constant_properties->length();
|
||||
OptimizedObjectForAddingMultipleProperties opt(boilerplate, true);
|
||||
OptimizedObjectForAddingMultipleProperties opt(boilerplate,
|
||||
!is_result_from_cache);
|
||||
for (int index = 0; index < length; index +=2) {
|
||||
Handle<Object> key(constant_properties->get(index+0));
|
||||
Handle<Object> value(constant_properties->get(index+1));
|
||||
@ -160,9 +194,8 @@ static Object* Runtime_CreateArrayLiteral(Arguments args) {
|
||||
ASSERT(args.length() == 2);
|
||||
CONVERT_CHECKED(FixedArray, elements, args[0]);
|
||||
CONVERT_CHECKED(FixedArray, literals, args[1]);
|
||||
const int kArrayFunIndex = JSFunction::kLiteralArrayFunctionIndex;
|
||||
JSFunction* constructor = JSFunction::cast(literals->get(kArrayFunIndex));
|
||||
|
||||
JSFunction* constructor =
|
||||
JSFunction::GlobalContextFromLiterals(literals)->array_function();
|
||||
// Create the JSArray.
|
||||
Object* object = Heap::AllocateJSObject(constructor);
|
||||
if (object->IsFailure()) return object;
|
||||
@ -699,10 +732,9 @@ static Object* Runtime_MaterializeRegExpLiteral(Arguments args) {
|
||||
// created. We do not use the RegExp function from the current
|
||||
// global context because this might be the RegExp function from
|
||||
// another context which we should not have access to.
|
||||
const int kRegexpFunIndex = JSFunction::kLiteralRegExpFunctionIndex;
|
||||
Handle<JSFunction> constructor =
|
||||
Handle<JSFunction>(JSFunction::cast(literals->get(kRegexpFunIndex)));
|
||||
|
||||
Handle<JSFunction>(
|
||||
JSFunction::GlobalContextFromLiterals(*literals)->regexp_function());
|
||||
// Compute the regular expression literal.
|
||||
bool has_pending_exception;
|
||||
Handle<Object> regexp =
|
||||
@ -839,12 +871,8 @@ static Object* Runtime_SetCode(Arguments args) {
|
||||
// Insert the object, regexp and array functions in the literals
|
||||
// array prefix. These are the functions that will be used when
|
||||
// creating object, regexp and array literals.
|
||||
literals->set(JSFunction::kLiteralObjectFunctionIndex,
|
||||
context->global_context()->object_function());
|
||||
literals->set(JSFunction::kLiteralRegExpFunctionIndex,
|
||||
context->global_context()->regexp_function());
|
||||
literals->set(JSFunction::kLiteralArrayFunctionIndex,
|
||||
context->global_context()->array_function());
|
||||
literals->set(JSFunction::kLiteralGlobalContextIndex,
|
||||
context->global_context());
|
||||
}
|
||||
target->set_literals(*literals);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user