Reland "[strong] Object literals create strong objects"
authorrossberg <rossberg@chromium.org>
Wed, 20 May 2015 07:07:54 +0000 (00:07 -0700)
committerCommit bot <commit-bot@chromium.org>
Wed, 20 May 2015 07:07:42 +0000 (07:07 +0000)
(patchset #4 id:60001 of https://codereview.chromium.org/1134333005/)"

This reverts commit 81c080ef8e7c1a38622b870b351bb1e11b6c8a62.
Patchset #1 is the original CL.
Patchset #2 fixes a handlification bug that caused the crash.

R=dslomov@chromium.org
BUG=v8:3956
LOG=N

Review URL: https://codereview.chromium.org/1143813002

Cr-Commit-Position: refs/heads/master@{#28497}

14 files changed:
include/v8.h
src/ast.h
src/bootstrapper.cc
src/contexts.h
src/factory.cc
src/factory.h
src/hydrogen.cc
src/objects.cc
src/parser.cc
src/preparser.h
src/runtime/runtime-literals.cc
src/runtime/runtime.h
test/mjsunit/strong/literals.js [new file with mode: 0644]
test/mjsunit/strong/objects.js [deleted file]

index 74e4c53190e4221c09ff732891fc6441a7e5070d..2946ad2d82f2aeb32eeebd7443d7d15415e535f4 100644 (file)
@@ -6732,7 +6732,7 @@ class Internals {
   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;
index 26950b4c9ae95ca003e177422e45e41130e63691..60f0068d37aebe855c31c352469af4d9ca058bf5 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -1295,11 +1295,14 @@ class MaterializedLiteral : public Expression {
     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
@@ -1328,6 +1331,7 @@ class MaterializedLiteral : public Expression {
  private:
   int literal_index_;
   bool is_simple_;
+  bool is_strong_;
   int depth_;
 };
 
@@ -1422,6 +1426,9 @@ class ObjectLiteral final : public MaterializedLiteral {
     if (disable_mementos) {
       flags |= kDisableMementos;
     }
+    if (is_strong()) {
+      flags |= kIsStrong;
+    }
     return flags;
   }
 
@@ -1430,7 +1437,8 @@ class ObjectLiteral final : public MaterializedLiteral {
     kFastElements = 1,
     kHasFunction = 1 << 1,
     kShallowProperties = 1 << 2,
-    kDisableMementos = 1 << 3
+    kDisableMementos = 1 << 3,
+    kIsStrong = 1 << 4
   };
 
   struct Accessors: public ZoneObject {
@@ -1450,8 +1458,9 @@ class ObjectLiteral final : public MaterializedLiteral {
 
  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),
@@ -1482,8 +1491,9 @@ class RegExpLiteral final : public MaterializedLiteral {
 
  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);
@@ -1528,19 +1538,24 @@ class ArrayLiteral final : public MaterializedLiteral {
     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:
@@ -3305,9 +3320,11 @@ class AstNodeFactory final BASE_EMBEDDED {
       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(
@@ -3328,14 +3345,18 @@ class AstNodeFactory final BASE_EMBEDDED {
   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,
index a0e7b7af629a6ea6df1187fa31a75d73937a642a..6969edea108eac8c4fbaa4f9c08ebfc4f35ea0d4 100644 (file)
@@ -1016,6 +1016,11 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> global_object,
     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 ---
index f120788609f2d748ed0015684cc0f91f0900d899..d06e4e81855814a571d905d429897defebd162f1 100644 (file)
@@ -85,6 +85,7 @@ enum BindingFlags {
   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)                        \
@@ -341,6 +342,7 @@ class Context: public FixedArray {
     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,
index e966e5ca949324294a70e7b4f3acc568790e0754..06373d2d8a39f62c0f98db6fd4978270f486f350 100644 (file)
@@ -2339,14 +2339,18 @@ Handle<JSWeakMap> Factory::NewJSWeakMap() {
 
 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) {
index 4aba6eeb766c689a791d1ab9271d0bd79b1f2fd2..8eaa216ee84646ba9f3d0d42c8c6d2188be5d69f 100644 (file)
@@ -670,6 +670,7 @@ class Factory final {
   // 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
index 4f04580376789ec692104af8d6f914bc62b53634..86bf7634296dcbf71b8a2debf27262464a1a1e3c 100644 (file)
@@ -5790,7 +5790,8 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
     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);
index 645ea57e344d2727209c68fa90b4a98843108d0e..28670a94f758aa7d00054ee3514101cf65a04ef3 100644 (file)
@@ -3804,7 +3804,9 @@ Handle<Map> Map::TransitionElementsTo(Handle<Map> map,
 
   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);
@@ -10318,7 +10320,10 @@ Handle<Object> CacheInitialJSArrayMaps(
     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;
 }
 
@@ -10353,13 +10358,18 @@ void JSFunction::SetInstancePrototype(Handle<JSFunction> function,
       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);
       }
     }
 
index 374b59c7a7e9b4e78707bd57d0ce94ad266e6bdf..d70e386564c576d1e9c107cb725f0be78dde2b60 100644 (file)
@@ -5621,11 +5621,12 @@ Expression* Parser::CloseTemplateLiteral(TemplateLiteralState* state, int start,
     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
@@ -5716,6 +5717,7 @@ ZoneList<v8::internal::Expression*>* Parser::PrepareSpreadArguments(
         }
         int literal_index = function_state_->NextMaterializedLiteralIndex();
         args->Add(factory()->NewArrayLiteral(unspread, literal_index,
+                                             is_strong(language_mode()),
                                              RelocInfo::kNoPosition),
                   zone());
 
index e5bb8916802f4eb732626c06f602ce315b870599..116a8eac9b891721e208bea92d9f3b7e4ad30528 100644 (file)
@@ -1372,11 +1372,13 @@ class PreParserFactory {
   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();
   }
@@ -1397,6 +1399,7 @@ class PreParserFactory {
                                        int literal_index,
                                        int boilerplate_properties,
                                        bool has_function,
+                                       bool is_strong,
                                        int pos) {
     return PreParserExpression::Default();
   }
@@ -2250,7 +2253,8 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseRegExpLiteral(
   }
   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);
 }
 
 
@@ -2515,7 +2519,8 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral(
   // 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);
 }
 
 
@@ -2786,6 +2791,7 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseObjectLiteral(
                                      literal_index,
                                      number_of_boilerplate_properties,
                                      has_function,
+                                     is_strong(language_mode()),
                                      pos);
 }
 
index 76226d68f596facea57862488c6a71de1d3e705b..8fe6e3f2fd3922bbb40ac7d7385c6fc4eafa98aa 100644 (file)
@@ -16,7 +16,7 @@ namespace internal {
 
 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;
 
@@ -30,28 +30,30 @@ static Handle<Map> ComputeObjectLiteralMap(
   }
   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 =
@@ -82,7 +84,8 @@ MUST_USE_RESULT static MaybeHandle<Object> CreateObjectLiteralBoilerplate(
       // 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;
@@ -137,7 +140,7 @@ MUST_USE_RESULT static MaybeHandle<Object> CreateObjectLiteralBoilerplate(
 
 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();
 
@@ -156,7 +159,9 @@ MaybeHandle<Object> Runtime::CreateArrayLiteralBoilerplate(
     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));
@@ -192,7 +197,8 @@ MaybeHandle<Object> Runtime::CreateArrayLiteralBoilerplate(
           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);
         }
@@ -208,19 +214,20 @@ MaybeHandle<Object> Runtime::CreateArrayLiteralBoilerplate(
 
 
 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>();
@@ -238,6 +245,7 @@ RUNTIME_FUNCTION(Runtime_CreateObjectLiteral) {
   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());
 
@@ -251,7 +259,7 @@ RUNTIME_FUNCTION(Runtime_CreateObjectLiteral) {
         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);
@@ -281,7 +289,7 @@ RUNTIME_FUNCTION(Runtime_CreateObjectLiteral) {
 
 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;
@@ -290,7 +298,8 @@ MUST_USE_RESULT static MaybeHandle<AllocationSite> GetLiteralAllocationSite(
     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);
@@ -318,9 +327,11 @@ static MaybeHandle<JSObject> CreateArrayLiteralImpl(Isolate* 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;
index bd37a68a753aa8182469f5d8eb3f10ae6d064b7d..b4de53539e938ff0c34b0e62e0612f148356f22a 100644 (file)
@@ -848,7 +848,7 @@ class Runtime : public AllStatic {
   // 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);
diff --git a/test/mjsunit/strong/literals.js b/test/mjsunit/strong/literals.js
new file mode 100644 (file)
index 0000000..b9368e1
--- /dev/null
@@ -0,0 +1,79 @@
+// 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/));
+})();
diff --git a/test/mjsunit/strong/objects.js b/test/mjsunit/strong/objects.js
deleted file mode 100644 (file)
index 4654606..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// 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));