static const int kJSObjectHeaderSize = 3 * kApiPointerSize;
static const int kFixedArrayHeaderSize = 2 * kApiPointerSize;
static const int kContextHeaderSize = 2 * kApiPointerSize;
- static const int kContextEmbedderDataIndex = 77;
+ static const int kContextEmbedderDataIndex = 78;
static const int kFullStringRepresentationMask = 0x07;
static const int kStringEncodingMask = 0x4;
static const int kExternalTwoByteRepresentationTag = 0x02;
return depth_;
}
+ bool is_strong() const { return is_strong_; }
+
protected:
- MaterializedLiteral(Zone* zone, int literal_index, int pos)
+ MaterializedLiteral(Zone* zone, int literal_index, bool is_strong, int pos)
: Expression(zone, pos),
literal_index_(literal_index),
is_simple_(false),
+ is_strong_(is_strong),
depth_(0) {}
// A materialized literal is simple if the values consist of only
private:
int literal_index_;
bool is_simple_;
+ bool is_strong_;
int depth_;
};
if (disable_mementos) {
flags |= kDisableMementos;
}
+ if (is_strong()) {
+ flags |= kIsStrong;
+ }
return flags;
}
kFastElements = 1,
kHasFunction = 1 << 1,
kShallowProperties = 1 << 2,
- kDisableMementos = 1 << 3
+ kDisableMementos = 1 << 3,
+ kIsStrong = 1 << 4
};
struct Accessors: public ZoneObject {
protected:
ObjectLiteral(Zone* zone, ZoneList<Property*>* properties, int literal_index,
- int boilerplate_properties, bool has_function, int pos)
- : MaterializedLiteral(zone, literal_index, pos),
+ int boilerplate_properties, bool has_function,
+ bool is_strong, int pos)
+ : MaterializedLiteral(zone, literal_index, is_strong, pos),
properties_(properties),
boilerplate_properties_(boilerplate_properties),
fast_elements_(false),
protected:
RegExpLiteral(Zone* zone, const AstRawString* pattern,
- const AstRawString* flags, int literal_index, int pos)
- : MaterializedLiteral(zone, literal_index, pos),
+ const AstRawString* flags, int literal_index, bool is_strong,
+ int pos)
+ : MaterializedLiteral(zone, literal_index, is_strong, pos),
pattern_(pattern),
flags_(flags) {
set_depth(1);
if (disable_mementos) {
flags |= kDisableMementos;
}
+ if (is_strong()) {
+ flags |= kIsStrong;
+ }
return flags;
}
enum Flags {
kNoFlags = 0,
kShallowElements = 1,
- kDisableMementos = 1 << 1
+ kDisableMementos = 1 << 1,
+ kIsStrong = 1 << 2
};
protected:
ArrayLiteral(Zone* zone, ZoneList<Expression*>* values, int literal_index,
- int pos)
- : MaterializedLiteral(zone, literal_index, pos), values_(values) {}
+ bool is_strong, int pos)
+ : MaterializedLiteral(zone, literal_index, is_strong, pos),
+ values_(values) {}
static int parent_num_ids() { return MaterializedLiteral::num_ids(); }
private:
int literal_index,
int boilerplate_properties,
bool has_function,
+ bool is_strong,
int pos) {
return new (zone_) ObjectLiteral(zone_, properties, literal_index,
- boilerplate_properties, has_function, pos);
+ boilerplate_properties, has_function,
+ is_strong, pos);
}
ObjectLiteral::Property* NewObjectLiteralProperty(
RegExpLiteral* NewRegExpLiteral(const AstRawString* pattern,
const AstRawString* flags,
int literal_index,
+ bool is_strong,
int pos) {
- return new (zone_) RegExpLiteral(zone_, pattern, flags, literal_index, pos);
+ return new (zone_) RegExpLiteral(zone_, pattern, flags, literal_index,
+ is_strong, pos);
}
ArrayLiteral* NewArrayLiteral(ZoneList<Expression*>* values,
int literal_index,
+ bool is_strong,
int pos) {
- return new (zone_) ArrayLiteral(zone_, values, literal_index, pos);
+ return new (zone_) ArrayLiteral(zone_, values, literal_index, is_strong,
+ pos);
}
VariableProxy* NewVariableProxy(Variable* var,
ArrayConstructorStub array_constructor_stub(isolate);
Handle<Code> code = array_constructor_stub.GetCode();
array_function->shared()->set_construct_stub(*code);
+
+ Handle<Map> initial_strong_map =
+ Map::Copy(initial_map, "SetInstancePrototype");
+ initial_strong_map->set_is_strong(true);
+ CacheInitialJSArrayMaps(native_context(), initial_strong_map);
}
{ // --- N u m b e r ---
V(INTERNAL_ARRAY_FUNCTION_INDEX, JSFunction, internal_array_function) \
V(ARRAY_FUNCTION_INDEX, JSFunction, array_function) \
V(JS_ARRAY_MAPS_INDEX, Object, js_array_maps) \
+ V(JS_ARRAY_STRONG_MAPS_INDEX, Object, js_array_strong_maps) \
V(DATE_FUNCTION_INDEX, JSFunction, date_function) \
V(JSON_OBJECT_INDEX, JSObject, json_object) \
V(REGEXP_FUNCTION_INDEX, JSFunction, regexp_function) \
INTERNAL_ARRAY_FUNCTION_INDEX,
ARRAY_FUNCTION_INDEX,
JS_ARRAY_MAPS_INDEX,
+ JS_ARRAY_STRONG_MAPS_INDEX,
DATE_FUNCTION_INDEX,
JSON_OBJECT_INDEX,
REGEXP_FUNCTION_INDEX,
Handle<Map> Factory::ObjectLiteralMapFromCache(Handle<Context> context,
int number_of_properties,
+ bool is_strong,
bool* is_result_from_cache) {
const int kMapCacheSize = 128;
// We do not cache maps for too many properties or when running builtin code.
- if (number_of_properties > kMapCacheSize ||
+ // TODO(rossberg): cache strong maps properly
+ if (number_of_properties > kMapCacheSize || is_strong ||
isolate()->bootstrapper()->IsActive()) {
*is_result_from_cache = false;
- return Map::Create(isolate(), number_of_properties);
+ Handle<Map> map = Map::Create(isolate(), number_of_properties);
+ if (is_strong) map->set_is_strong(true);
+ return map;
}
*is_result_from_cache = true;
if (number_of_properties == 0) {
// native context.
Handle<Map> ObjectLiteralMapFromCache(Handle<Context> context,
int number_of_properties,
+ bool is_strong,
bool* is_result_from_cache);
// Creates a new FixedArray that holds the data associated with the
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
isolate(), raw_boilerplate,
Runtime::CreateArrayLiteralBoilerplate(
- isolate(), literals, expr->constant_elements()),
+ isolate(), literals, expr->constant_elements(),
+ is_strong(function_language_mode())),
Bailout(kArrayBoilerplateCreationFailed));
boilerplate_object = Handle<JSObject>::cast(raw_boilerplate);
Isolate* isolate = map->GetIsolate();
Context* native_context = isolate->context()->native_context();
- Object* maybe_array_maps = native_context->js_array_maps();
+ Object* maybe_array_maps = map->is_strong()
+ ? native_context->js_array_strong_maps()
+ : native_context->js_array_maps();
if (maybe_array_maps->IsFixedArray()) {
DisallowHeapAllocation no_gc;
FixedArray* array_maps = FixedArray::cast(maybe_array_maps);
maps->set(next_kind, *new_map);
current_map = new_map;
}
- native_context->set_js_array_maps(*maps);
+ if (initial_map->is_strong())
+ native_context->set_js_array_strong_maps(*maps);
+ else
+ native_context->set_js_array_maps(*maps);
return initial_map;
}
JSFunction::SetInitialMap(function, new_map, value);
// If the function is used as the global Array function, cache the
- // initial map (and transitioned versions) in the native context.
- Context* native_context = function->context()->native_context();
- Object* array_function =
- native_context->get(Context::ARRAY_FUNCTION_INDEX);
+ // updated initial maps (and transitioned versions) in the native context.
+ Handle<Context> native_context(function->context()->native_context(),
+ isolate);
+ Handle<Object> array_function(
+ native_context->get(Context::ARRAY_FUNCTION_INDEX), isolate);
if (array_function->IsJSFunction() &&
- *function == JSFunction::cast(array_function)) {
- CacheInitialJSArrayMaps(handle(native_context, isolate), new_map);
+ *function == JSFunction::cast(*array_function)) {
+ CacheInitialJSArrayMaps(native_context, new_map);
+ Handle<Map> new_strong_map =
+ Map::Copy(initial_map, "SetInstancePrototype");
+ new_strong_map->set_is_strong(true);
+ CacheInitialJSArrayMaps(native_context, new_strong_map);
}
}
ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(4, zone());
args->Add(factory()->NewArrayLiteral(
const_cast<ZoneList<Expression*>*>(cooked_strings),
- cooked_idx, pos),
+ cooked_idx, is_strong(language_mode()), pos),
zone());
args->Add(
factory()->NewArrayLiteral(
- const_cast<ZoneList<Expression*>*>(raw_strings), raw_idx, pos),
+ const_cast<ZoneList<Expression*>*>(raw_strings), raw_idx,
+ is_strong(language_mode()), pos),
zone());
// Ensure hash is suitable as a Smi value
}
int literal_index = function_state_->NextMaterializedLiteralIndex();
args->Add(factory()->NewArrayLiteral(unspread, literal_index,
+ is_strong(language_mode()),
RelocInfo::kNoPosition),
zone());
PreParserExpression NewRegExpLiteral(PreParserIdentifier js_pattern,
PreParserIdentifier js_flags,
int literal_index,
+ bool is_strong,
int pos) {
return PreParserExpression::Default();
}
PreParserExpression NewArrayLiteral(PreParserExpressionList values,
int literal_index,
+ bool is_strong,
int pos) {
return PreParserExpression::Default();
}
int literal_index,
int boilerplate_properties,
bool has_function,
+ bool is_strong,
int pos) {
return PreParserExpression::Default();
}
}
IdentifierT js_flags = this->GetNextSymbol(scanner());
Next();
- return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index, pos);
+ return factory()->NewRegExpLiteral(js_pattern, js_flags, literal_index,
+ is_strong(language_mode()), pos);
}
// Update the scope information before the pre-parsing bailout.
int literal_index = function_state_->NextMaterializedLiteralIndex();
- return factory()->NewArrayLiteral(values, literal_index, pos);
+ return factory()->NewArrayLiteral(values, literal_index,
+ is_strong(language_mode()), pos);
}
literal_index,
number_of_boilerplate_properties,
has_function,
+ is_strong(language_mode()),
pos);
}
static Handle<Map> ComputeObjectLiteralMap(
Handle<Context> context, Handle<FixedArray> constant_properties,
- bool* is_result_from_cache) {
+ bool is_strong, bool* is_result_from_cache) {
int properties_length = constant_properties->length();
int number_of_properties = properties_length / 2;
}
Isolate* isolate = context->GetIsolate();
return isolate->factory()->ObjectLiteralMapFromCache(
- context, number_of_properties, is_result_from_cache);
+ context, number_of_properties, is_strong, is_result_from_cache);
}
MUST_USE_RESULT static MaybeHandle<Object> CreateLiteralBoilerplate(
Isolate* isolate, Handle<FixedArray> literals,
- Handle<FixedArray> constant_properties);
+ Handle<FixedArray> constant_properties, bool is_strong);
MUST_USE_RESULT static MaybeHandle<Object> CreateObjectLiteralBoilerplate(
Isolate* isolate, Handle<FixedArray> literals,
Handle<FixedArray> constant_properties, bool should_have_fast_elements,
- bool has_function_literal) {
+ bool has_function_literal, bool is_strong) {
Handle<Context> context = isolate->native_context();
// In case we have function literals, we want the object to be in
// slow properties mode for now. We don't go in the map cache because
// maps with constant functions can't be shared if the functions are
// not the same (which is the common case).
+ // TODO(rossberg): handle strong objects with function literals
bool is_result_from_cache = false;
Handle<Map> map = has_function_literal
? Handle<Map>(context->object_function()->initial_map())
: ComputeObjectLiteralMap(context, constant_properties,
+ is_strong,
&is_result_from_cache);
PretenureFlag pretenure_flag =
// simple object or array literal.
Handle<FixedArray> array = Handle<FixedArray>::cast(value);
ASSIGN_RETURN_ON_EXCEPTION(
- isolate, value, CreateLiteralBoilerplate(isolate, literals, array),
+ isolate, value,
+ CreateLiteralBoilerplate(isolate, literals, array, is_strong),
Object);
}
MaybeHandle<Object> maybe_result;
MaybeHandle<Object> Runtime::CreateArrayLiteralBoilerplate(
Isolate* isolate, Handle<FixedArray> literals,
- Handle<FixedArray> elements) {
+ Handle<FixedArray> elements, bool is_strong) {
// Create the JSArray.
Handle<JSFunction> constructor = isolate->array_function();
DisallowHeapAllocation no_gc;
DCHECK(IsFastElementsKind(constant_elements_kind));
Context* native_context = isolate->context()->native_context();
- Object* maps_array = native_context->js_array_maps();
+ Object* maps_array = is_strong
+ ? native_context->js_array_strong_maps()
+ : native_context->js_array_maps();
DCHECK(!maps_array->IsUndefined());
Object* map = FixedArray::cast(maps_array)->get(constant_elements_kind);
object->set_map(Map::cast(map));
Handle<FixedArray> fa(FixedArray::cast(fixed_array_values->get(i)));
Handle<Object> result;
ASSIGN_RETURN_ON_EXCEPTION(
- isolate, result, CreateLiteralBoilerplate(isolate, literals, fa),
+ isolate, result,
+ CreateLiteralBoilerplate(isolate, literals, fa, is_strong),
Object);
fixed_array_values_copy->set(i, *result);
}
MUST_USE_RESULT static MaybeHandle<Object> CreateLiteralBoilerplate(
- Isolate* isolate, Handle<FixedArray> literals, Handle<FixedArray> array) {
+ Isolate* isolate, Handle<FixedArray> literals, Handle<FixedArray> array,
+ bool is_strong) {
Handle<FixedArray> elements = CompileTimeValue::GetElements(array);
const bool kHasNoFunctionLiteral = false;
switch (CompileTimeValue::GetLiteralType(array)) {
case CompileTimeValue::OBJECT_LITERAL_FAST_ELEMENTS:
return CreateObjectLiteralBoilerplate(isolate, literals, elements, true,
- kHasNoFunctionLiteral);
+ kHasNoFunctionLiteral, is_strong);
case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS:
return CreateObjectLiteralBoilerplate(isolate, literals, elements, false,
- kHasNoFunctionLiteral);
+ kHasNoFunctionLiteral, is_strong);
case CompileTimeValue::ARRAY_LITERAL:
return Runtime::CreateArrayLiteralBoilerplate(isolate, literals,
- elements);
+ elements, is_strong);
default:
UNREACHABLE();
return MaybeHandle<Object>();
bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
bool enable_mementos = (flags & ObjectLiteral::kDisableMementos) == 0;
+ bool is_strong = (flags & ObjectLiteral::kIsStrong) != 0;
RUNTIME_ASSERT(literals_index >= 0 && literals_index < literals->length());
isolate, raw_boilerplate,
CreateObjectLiteralBoilerplate(isolate, literals, constant_properties,
should_have_fast_elements,
- has_function_literal));
+ has_function_literal, is_strong));
boilerplate = Handle<JSObject>::cast(raw_boilerplate);
AllocationSiteCreationContext creation_context(isolate);
MUST_USE_RESULT static MaybeHandle<AllocationSite> GetLiteralAllocationSite(
Isolate* isolate, Handle<FixedArray> literals, int literals_index,
- Handle<FixedArray> elements) {
+ Handle<FixedArray> elements, bool is_strong) {
// Check if boilerplate exists. If not, create it first.
Handle<Object> literal_site(literals->get(literals_index), isolate);
Handle<AllocationSite> site;
Handle<Object> boilerplate;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, boilerplate,
- Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements),
+ Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements,
+ is_strong),
AllocationSite);
AllocationSiteCreationContext creation_context(isolate);
RUNTIME_ASSERT_HANDLIFIED(
literals_index >= 0 && literals_index < literals->length(), JSObject);
Handle<AllocationSite> site;
+ bool is_strong = (flags & ArrayLiteral::kIsStrong) != 0;
ASSIGN_RETURN_ON_EXCEPTION(
isolate, site,
- GetLiteralAllocationSite(isolate, literals, literals_index, elements),
+ GetLiteralAllocationSite(isolate, literals, literals_index, elements,
+ is_strong),
JSObject);
bool enable_mementos = (flags & ArrayLiteral::kDisableMementos) == 0;
// Used in runtime.cc and hydrogen's VisitArrayLiteral.
MUST_USE_RESULT static MaybeHandle<Object> CreateArrayLiteralBoilerplate(
Isolate* isolate, Handle<FixedArray> literals,
- Handle<FixedArray> elements);
+ Handle<FixedArray> elements, bool is_strong);
static void WeakCollectionInitialize(
Isolate* isolate, Handle<JSWeakCollection> weak_collection);
--- /dev/null
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --strong-mode --allow-natives-syntax
+// Flags: --harmony-arrow-functions --harmony-rest-parameters
+
+
+(function WeakObjectLiterals() {
+ assertTrue(!%IsStrong({}));
+ assertTrue(!%IsStrong({a: 0, b: 0}));
+ assertTrue(!%IsStrong({f: function(){}}));
+ assertTrue(!%IsStrong(Realm.eval(Realm.current(),
+ "({f: function(){}})")));
+})();
+
+(function StrongObjectLiterals() {
+ 'use strong';
+ assertTrue(%IsStrong({}));
+ assertTrue(%IsStrong({a: 0, b: 0}));
+ assertTrue(%IsStrong({__proto__: {}, get a() {}, set b(x) {}}));
+ assertTrue(%IsStrong({[Date() + ""]: 0, [Symbol()]: 0}));
+ // TODO(rossberg): super does not work yet
+ // assertTrue(%IsStrong({m() { super.m() }}));
+ // Object literals with constant functions are treated specially,
+ // but currently only on the toplevel.
+ assertTrue(%IsStrong({f: function(){}}));
+ // TODO(rossberg): implement strong object literals with functions
+ // assertTrue(%IsStrong(Realm.eval(Realm.current(),
+ // "'use strong'; ({f: function(){}})")));
+})();
+
+(function WeakArrayLiterals(...args) {
+ assertTrue(!%IsStrong(args));
+ assertTrue(!%IsStrong([]));
+ assertTrue(!%IsStrong([1, 2, 3]));
+ Array.prototype = {}
+ assertTrue(!%IsStrong([]));
+ assertTrue(!%IsStrong([1, 2, 3]));
+})();
+
+(function StrongArrayLiterals(...args) {
+ 'use strong';
+ // TODO(rossberg): implement strong array literals
+ // assertTrue(%IsStrong(args));
+ // assertTrue(%IsStrong([]));
+ // assertTrue(%IsStrong([1, 2, 3]));
+ // Array.prototype = {}
+ // assertTrue(%IsStrong([]));
+ // assertTrue(%IsStrong([1, 2, 3]));
+})(0); // TODO(arv): drop dummy
+
+(function WeakFunctionLiterals() {
+ function f() {}
+ assertTrue(!%IsStrong(f));
+ assertTrue(!%IsStrong(function(){}));
+ assertTrue(!%IsStrong(() => {}));
+ assertTrue(!%IsStrong(x => x));
+})();
+
+(function StrongFunctionLiterals(g) {
+ 'use strong';
+ function f() {}
+ assertTrue(%IsStrong(f));
+ assertTrue(%IsStrong(g));
+ assertTrue(%IsStrong(function(){}));
+ assertTrue(%IsStrong(() => {}));
+ assertTrue(%IsStrong(x => x));
+})(function() { 'use strong' });
+
+(function WeakRegExpLiterals() {
+ assertTrue(!%IsStrong(/abc/));
+})();
+
+(function StrongRegExpLiterals() {
+ 'use strong';
+ // TODO(rossberg): implement strong regexp literals
+ // assertTrue(%IsStrong(/abc/));
+})();
+++ /dev/null
-// Copyright 2015 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Flags: --strong-mode --allow-natives-syntax
-
-'use strong';
-
-function f() {}
-assertTrue(%IsStrong(f));