[strong] create strong array literals
authorconradw <conradw@chromium.org>
Tue, 2 Jun 2015 11:46:04 +0000 (04:46 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 2 Jun 2015 11:46:15 +0000 (11:46 +0000)
Copied, with permission, from https://codereview.chromium.org/1151853003/

Initial patch set is an unmodified copy, rebased on top of related fixes from
https://codereview.chromium.org/1158933002/

Subsequent patch sets contain fixes for remaining bugs in the CL.

BUG=v8:3956
LOG=N

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

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

31 files changed:
src/arm/code-stubs-arm.cc
src/arm/full-codegen-arm.cc
src/arm64/code-stubs-arm64.cc
src/arm64/full-codegen-arm64.cc
src/builtins.cc
src/compiler/ast-graph-builder.cc
src/compiler/js-typed-lowering.cc
src/factory.cc
src/factory.h
src/full-codegen.cc
src/globals.h
src/ia32/code-stubs-ia32.cc
src/ia32/full-codegen-ia32.cc
src/isolate.cc
src/isolate.h
src/json-parser.h
src/mips/code-stubs-mips.cc
src/mips/full-codegen-mips.cc
src/mips64/code-stubs-mips64.cc
src/mips64/full-codegen-mips64.cc
src/ppc/code-stubs-ppc.cc
src/ppc/full-codegen-ppc.cc
src/runtime/runtime-scopes.cc
src/runtime/runtime.h
src/x64/code-stubs-x64.cc
src/x64/full-codegen-x64.cc
src/x87/code-stubs-x87.cc
src/x87/full-codegen-x87.cc
test/cctest/test-heap.cc
test/cctest/test-unboxed-doubles.cc
test/mjsunit/strong/literals.js

index e7ba1f3..da06b10 100644 (file)
@@ -1953,9 +1953,10 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
 
 void RestParamAccessStub::GenerateNew(MacroAssembler* masm) {
   // Stack layout on entry.
-  //  sp[0] : index of rest parameter
-  //  sp[4] : number of parameters
-  //  sp[8] : receiver displacement
+  //  sp[0] : language mode
+  //  sp[4] : index of rest parameter
+  //  sp[8] : number of parameters
+  //  sp[12] : receiver displacement
 
   Label runtime;
   __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
@@ -1965,13 +1966,13 @@ void RestParamAccessStub::GenerateNew(MacroAssembler* masm) {
 
   // Patch the arguments.length and the parameters pointer.
   __ ldr(r1, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset));
-  __ str(r1, MemOperand(sp, 1 * kPointerSize));
+  __ str(r1, MemOperand(sp, 2 * kPointerSize));
   __ add(r3, r2, Operand::PointerOffsetFromSmiKey(r1));
   __ add(r3, r3, Operand(StandardFrameConstants::kCallerSPOffset));
-  __ str(r3, MemOperand(sp, 2 * kPointerSize));
+  __ str(r3, MemOperand(sp, 3 * kPointerSize));
 
   __ bind(&runtime);
-  __ TailCallRuntime(Runtime::kNewRestParam, 3, 1);
+  __ TailCallRuntime(Runtime::kNewRestParam, 4, 1);
 }
 
 
index c945ce4..a792d9f 100644 (file)
@@ -268,7 +268,8 @@ void FullCodeGenerator::Generate() {
     __ add(r3, fp, Operand(StandardFrameConstants::kCallerSPOffset + offset));
     __ mov(r2, Operand(Smi::FromInt(num_parameters)));
     __ mov(r1, Operand(Smi::FromInt(rest_index)));
-    __ Push(r3, r2, r1);
+    __ mov(r0, Operand(Smi::FromInt(language_mode())));
+    __ Push(r3, r2, r1, r0);
 
     RestParamAccessStub stub(isolate());
     __ CallStub(&stub);
index 655f388..5e0778e 100644 (file)
@@ -2206,19 +2206,21 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
 
 void RestParamAccessStub::GenerateNew(MacroAssembler* masm) {
   // Stack layout on entry.
-  //  jssp[0]:  index of rest parameter (tagged)
-  //  jssp[8]:  number of parameters (tagged)
-  //  jssp[16]: address of receiver argument
+  //  jssp[0]:  language mode (tagged)
+  //  jssp[8]:  index of rest parameter (tagged)
+  //  jssp[16]: number of parameters (tagged)
+  //  jssp[24]: address of receiver argument
   //
   // Returns pointer to result object in x0.
 
   // Get the stub arguments from the frame, and make an untagged copy of the
   // parameter count.
-  Register rest_index_smi = x1;
-  Register param_count_smi = x2;
-  Register params = x3;
+  Register language_mode_smi = x1;
+  Register rest_index_smi = x2;
+  Register param_count_smi = x3;
+  Register params = x4;
   Register param_count = x13;
-  __ Pop(rest_index_smi, param_count_smi, params);
+  __ Pop(language_mode_smi, rest_index_smi, param_count_smi, params);
   __ SmiUntag(param_count, param_count_smi);
 
   // Test if arguments adaptor needed.
@@ -2231,11 +2233,12 @@ void RestParamAccessStub::GenerateNew(MacroAssembler* masm) {
   __ Cmp(caller_ctx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
   __ B(ne, &runtime);
 
-  //   x1   rest_index_smi    index of rest parameter
-  //   x2   param_count_smi   number of parameters passed to function (smi)
-  //   x3   params            pointer to parameters
-  //   x11  caller_fp         caller's frame pointer
-  //   x13  param_count       number of parameters passed to function
+  //   x1   language_mode_smi  language mode
+  //   x2   rest_index_smi     index of rest parameter
+  //   x3   param_count_smi    number of parameters passed to function (smi)
+  //   x4   params             pointer to parameters
+  //   x11  caller_fp          caller's frame pointer
+  //   x13  param_count        number of parameters passed to function
 
   // Patch the argument length and parameters pointer.
   __ Ldr(param_count_smi,
@@ -2246,8 +2249,8 @@ void RestParamAccessStub::GenerateNew(MacroAssembler* masm) {
   __ Add(params, x10, StandardFrameConstants::kCallerSPOffset);
 
   __ Bind(&runtime);
-  __ Push(params, param_count_smi, rest_index_smi);
-  __ TailCallRuntime(Runtime::kNewRestParam, 3, 1);
+  __ Push(params, param_count_smi, rest_index_smi, language_mode_smi);
+  __ TailCallRuntime(Runtime::kNewRestParam, 4, 1);
 }
 
 
index e1147b9..dfbae7d 100644 (file)
@@ -269,7 +269,8 @@ void FullCodeGenerator::Generate() {
     __ Add(x3, fp, StandardFrameConstants::kCallerSPOffset + offset);
     __ Mov(x2, Smi::FromInt(num_parameters));
     __ Mov(x1, Smi::FromInt(rest_index));
-    __ Push(x3, x2, x1);
+    __ Mov(x0, Smi::FromInt(language_mode()));
+    __ Push(x3, x2, x1, x0);
 
     RestParamAccessStub stub(isolate());
     __ CallStub(&stub);
index ee34cdc..7ac60da 100644 (file)
@@ -988,11 +988,8 @@ BUILTIN(ArrayConcat) {
   ArrayStorageAllocationMode mode =
       has_double && IsFastObjectElementsKind(elements_kind)
       ? INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE : DONT_INITIALIZE_ARRAY_ELEMENTS;
-  Handle<JSArray> result_array =
-      isolate->factory()->NewJSArray(elements_kind,
-                                     result_len,
-                                     result_len,
-                                     mode);
+  Handle<JSArray> result_array = isolate->factory()->NewJSArray(
+      elements_kind, result_len, result_len, WEAK, mode);
   if (result_len == 0) return *result_array;
 
   int j = 0;
index 94057f2..247f674 100644 (file)
@@ -2904,8 +2904,9 @@ Node* AstGraphBuilder::BuildRestArgumentsArray(Variable* rest, int index) {
   if (rest == NULL) return NULL;
 
   DCHECK(index >= 0);
-  const Operator* op = javascript()->CallRuntime(Runtime::kNewRestParamSlow, 1);
-  Node* object = NewNode(op, jsgraph()->SmiConstant(index));
+  const Operator* op = javascript()->CallRuntime(Runtime::kNewRestParamSlow, 2);
+  Node* object = NewNode(op, jsgraph()->SmiConstant(index),
+                         jsgraph()->SmiConstant(language_mode()));
 
   // Assign the object to the rest array
   DCHECK(rest->IsContextSlot() || rest->IsStackAllocated());
index 3a24ad7..fb59ce0 100644 (file)
@@ -1014,7 +1014,9 @@ Reduction JSTypedLowering::ReduceJSCreateLiteralArray(Node* node) {
 
   // Use the FastCloneShallowArrayStub only for shallow boilerplates up to the
   // initial length limit for arrays with "fast" elements kind.
+  // TODO(rossberg): Teach strong mode to FastCloneShallowArrayStub.
   if ((flags & ArrayLiteral::kShallowElements) != 0 &&
+      (flags & ArrayLiteral::kIsStrong) == 0 &&
       length < JSObject::kInitialMaxFastElementArray) {
     Isolate* isolate = jsgraph()->isolate();
     Callable callable = CodeFactory::FastCloneShallowArray(isolate);
index 6fc18eb..ed3afa5 100644 (file)
@@ -1637,22 +1637,24 @@ Handle<JSObject> Factory::NewJSObjectFromMap(
 
 
 Handle<JSArray> Factory::NewJSArray(ElementsKind elements_kind,
+                                    ObjectStrength strength,
                                     PretenureFlag pretenure) {
-  Context* native_context = isolate()->context()->native_context();
-  JSFunction* array_function = native_context->array_function();
-  Map* map = array_function->initial_map();
-  Map* transition_map = isolate()->get_initial_js_array_map(elements_kind);
-  if (transition_map != NULL) map = transition_map;
+  Map* map = isolate()->get_initial_js_array_map(elements_kind, strength);
+  if (map == nullptr) {
+    DCHECK(strength == WEAK);
+    Context* native_context = isolate()->context()->native_context();
+    JSFunction* array_function = native_context->array_function();
+    map = array_function->initial_map();
+  }
   return Handle<JSArray>::cast(NewJSObjectFromMap(handle(map), pretenure));
 }
 
 
-Handle<JSArray> Factory::NewJSArray(ElementsKind elements_kind,
-                                    int length,
-                                    int capacity,
+Handle<JSArray> Factory::NewJSArray(ElementsKind elements_kind, int length,
+                                    int capacity, ObjectStrength strength,
                                     ArrayStorageAllocationMode mode,
                                     PretenureFlag pretenure) {
-  Handle<JSArray> array = NewJSArray(elements_kind, pretenure);
+  Handle<JSArray> array = NewJSArray(elements_kind, strength, pretenure);
   NewJSArrayStorage(array, length, capacity, mode);
   return array;
 }
@@ -1661,9 +1663,10 @@ Handle<JSArray> Factory::NewJSArray(ElementsKind elements_kind,
 Handle<JSArray> Factory::NewJSArrayWithElements(Handle<FixedArrayBase> elements,
                                                 ElementsKind elements_kind,
                                                 int length,
+                                                ObjectStrength strength,
                                                 PretenureFlag pretenure) {
   DCHECK(length <= elements->length());
-  Handle<JSArray> array = NewJSArray(elements_kind, pretenure);
+  Handle<JSArray> array = NewJSArray(elements_kind, strength, pretenure);
 
   array->set_elements(*elements);
   array->set_length(Smi::FromInt(length));
index 076f81d..6552a67 100644 (file)
@@ -401,23 +401,26 @@ class Factory final {
   // Create a JSArray with no elements.
   Handle<JSArray> NewJSArray(
       ElementsKind elements_kind,
+      ObjectStrength strength = WEAK,
       PretenureFlag pretenure = NOT_TENURED);
 
   // Create a JSArray with a specified length and elements initialized
   // according to the specified mode.
   Handle<JSArray> NewJSArray(
       ElementsKind elements_kind, int length, int capacity,
+      ObjectStrength strength = WEAK,
       ArrayStorageAllocationMode mode = DONT_INITIALIZE_ARRAY_ELEMENTS,
       PretenureFlag pretenure = NOT_TENURED);
 
   Handle<JSArray> NewJSArray(
       int capacity,
       ElementsKind elements_kind = TERMINAL_FAST_ELEMENTS_KIND,
+      ObjectStrength strength = WEAK,
       PretenureFlag pretenure = NOT_TENURED) {
     if (capacity != 0) {
       elements_kind = GetHoleyElementsKind(elements_kind);
     }
-    return NewJSArray(elements_kind, 0, capacity,
+    return NewJSArray(elements_kind, 0, capacity, strength,
                       INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE, pretenure);
   }
 
@@ -426,14 +429,16 @@ class Factory final {
       Handle<FixedArrayBase> elements,
       ElementsKind elements_kind,
       int length,
+      ObjectStrength strength = WEAK,
       PretenureFlag pretenure = NOT_TENURED);
 
   Handle<JSArray> NewJSArrayWithElements(
       Handle<FixedArrayBase> elements,
       ElementsKind elements_kind = TERMINAL_FAST_ELEMENTS_KIND,
+      ObjectStrength strength = WEAK,
       PretenureFlag pretenure = NOT_TENURED) {
-    return NewJSArrayWithElements(
-        elements, elements_kind, elements->length(), pretenure);
+    return NewJSArrayWithElements(elements, elements_kind, elements->length(),
+                                  strength, pretenure);
   }
 
   void NewJSArrayStorage(
index 1ae52c8..c69f625 100644 (file)
@@ -412,7 +412,8 @@ bool FullCodeGenerator::MustCreateObjectLiteralWithRuntime(
 
 bool FullCodeGenerator::MustCreateArrayLiteralWithRuntime(
     ArrayLiteral* expr) const {
-  return expr->depth() > 1 ||
+  // TODO(rossberg): Teach strong mode to FastCloneShallowArrayStub.
+  return expr->depth() > 1 || expr->is_strong() ||
          expr->values()->length() > JSObject::kInitialMaxFastElementArray;
 }
 
index 23afbc2..7fdcc26 100644 (file)
@@ -225,6 +225,11 @@ template <typename T, class P = FreeStoreAllocationPolicy> class List;
 // -----------------------------------------------------------------------------
 // Declarations for use in both the preparser and the rest of V8.
 
+enum ObjectStrength {
+  WEAK,
+  FIRM  // strong object
+};
+
 // The Strict Mode (ECMA-262 5th edition, 4.2.2).
 
 enum LanguageMode {
@@ -284,6 +289,11 @@ inline LanguageMode construct_language_mode(bool strict_bit, bool strong_bit) {
 }
 
 
+inline ObjectStrength strength(LanguageMode language_mode) {
+  return is_strong(language_mode) ? FIRM : WEAK;
+}
+
+
 // Mask for the sign bit in a smi.
 const intptr_t kSmiSignMask = kIntptrSignBit;
 
index b1081ed..1165571 100644 (file)
@@ -1163,9 +1163,10 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
 
 void RestParamAccessStub::GenerateNew(MacroAssembler* masm) {
   // esp[0] : return address
-  // esp[4] : index of rest parameter
-  // esp[8] : number of parameters
-  // esp[12] : receiver displacement
+  // esp[4] : language mode
+  // esp[8] : index of rest parameter
+  // esp[12] : number of parameters
+  // esp[16] : receiver displacement
 
   // Check if the calling frame is an arguments adaptor frame.
   Label runtime;
@@ -1176,13 +1177,13 @@ void RestParamAccessStub::GenerateNew(MacroAssembler* masm) {
 
   // Patch the arguments.length and the parameters pointer.
   __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
-  __ mov(Operand(esp, 2 * kPointerSize), ecx);
+  __ mov(Operand(esp, 3 * kPointerSize), ecx);
   __ lea(edx, Operand(edx, ecx, times_2,
                       StandardFrameConstants::kCallerSPOffset));
-  __ mov(Operand(esp, 3 * kPointerSize), edx);
+  __ mov(Operand(esp, 4 * kPointerSize), edx);
 
   __ bind(&runtime);
-  __ TailCallRuntime(Runtime::kNewRestParam, 3, 1);
+  __ TailCallRuntime(Runtime::kNewRestParam, 4, 1);
 }
 
 
index 07910d7..cd8b22f 100644 (file)
@@ -266,6 +266,7 @@ void FullCodeGenerator::Generate() {
     __ push(edx);
     __ push(Immediate(Smi::FromInt(num_parameters)));
     __ push(Immediate(Smi::FromInt(rest_index)));
+    __ push(Immediate(Smi::FromInt(language_mode())));
 
     RestParamAccessStub stub(isolate());
     __ CallStub(&stub);
index 93005e3..efa0e28 100644 (file)
@@ -2373,9 +2373,11 @@ CodeTracer* Isolate::GetCodeTracer() {
 }
 
 
-Map* Isolate::get_initial_js_array_map(ElementsKind kind) {
+Map* Isolate::get_initial_js_array_map(ElementsKind kind,
+                                       ObjectStrength strength) {
   Context* native_context = context()->native_context();
-  Object* maybe_map_array = native_context->js_array_maps();
+  Object* maybe_map_array = strength ? native_context->js_array_strong_maps()
+                                     : native_context->js_array_maps();
   if (!maybe_map_array->IsUndefined()) {
     Object* maybe_transitioned_map =
         FixedArray::cast(maybe_map_array)->get(kind);
index bdc3210..4b242a3 100644 (file)
@@ -990,7 +990,8 @@ class Isolate {
     date_cache_ = date_cache;
   }
 
-  Map* get_initial_js_array_map(ElementsKind kind);
+  Map* get_initial_js_array_map(ElementsKind kind,
+                                ObjectStrength strength = WEAK);
 
   static const int kArrayProtectorValid = 1;
   static const int kArrayProtectorInvalid = 0;
index 973e9a0..76882dd 100644 (file)
@@ -525,7 +525,7 @@ Handle<Object> JsonParser<seq_one_byte>::ParseJsonArray() {
     fast_elements->set(i, *elements[i]);
   }
   Handle<Object> json_array = factory()->NewJSArrayWithElements(
-      fast_elements, FAST_ELEMENTS, pretenure_);
+      fast_elements, FAST_ELEMENTS, WEAK, pretenure_);
   return scope.CloseAndEscape(json_array);
 }
 
index e833ea0..5f87ae7 100644 (file)
@@ -2063,9 +2063,10 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
 
 
 void RestParamAccessStub::GenerateNew(MacroAssembler* masm) {
-  // sp[0] : index of rest parameter
-  // sp[4] : number of parameters
-  // sp[8] : receiver displacement
+  // sp[0] : language mode
+  // sp[4] : index of rest parameter
+  // sp[8] : number of parameters
+  // sp[12] : receiver displacement
   // Check if the calling frame is an arguments adaptor frame.
 
   Label runtime;
@@ -2076,16 +2077,16 @@ void RestParamAccessStub::GenerateNew(MacroAssembler* masm) {
 
   // Patch the arguments.length and the parameters pointer.
   __ lw(a1, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset));
-  __ sw(a1, MemOperand(sp, 1 * kPointerSize));
+  __ sw(a1, MemOperand(sp, 2 * kPointerSize));
   __ sll(at, a1, kPointerSizeLog2 - kSmiTagSize);
   __ Addu(a3, a2, Operand(at));
 
   __ Addu(a3, a3, Operand(StandardFrameConstants::kCallerSPOffset));
-  __ sw(a3, MemOperand(sp, 2 * kPointerSize));
+  __ sw(a3, MemOperand(sp, 3 * kPointerSize));
 
   // Do the runtime call to allocate the arguments object.
   __ bind(&runtime);
-  __ TailCallRuntime(Runtime::kNewRestParam, 3, 1);
+  __ TailCallRuntime(Runtime::kNewRestParam, 4, 1);
 }
 
 
index 8200096..fa295a4 100644 (file)
@@ -278,7 +278,8 @@ void FullCodeGenerator::Generate() {
             Operand(StandardFrameConstants::kCallerSPOffset + offset));
     __ li(a2, Operand(Smi::FromInt(num_parameters)));
     __ li(a1, Operand(Smi::FromInt(rest_index)));
-    __ Push(a3, a2, a1);
+    __ li(a0, Operand(Smi::FromInt(language_mode())));
+    __ Push(a3, a2, a1, a0);
 
     RestParamAccessStub stub(isolate());
     __ CallStub(&stub);
index fb8345b..d6a02fd 100644 (file)
@@ -2066,9 +2066,10 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
 
 
 void RestParamAccessStub::GenerateNew(MacroAssembler* masm) {
-  // sp[0] : index of rest parameter
-  // sp[4] : number of parameters
-  // sp[8] : receiver displacement
+  // sp[0] : language mode
+  // sp[4] : index of rest parameter
+  // sp[8] : number of parameters
+  // sp[12] : receiver displacement
   // Check if the calling frame is an arguments adaptor frame.
 
   Label runtime;
@@ -2079,17 +2080,17 @@ void RestParamAccessStub::GenerateNew(MacroAssembler* masm) {
 
   // Patch the arguments.length and the parameters pointer.
   __ ld(a1, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset));
-  __ sd(a1, MemOperand(sp, 1 * kPointerSize));
+  __ sd(a1, MemOperand(sp, 2 * kPointerSize));
   __ SmiScale(at, a1, kPointerSizeLog2);
 
   __ Daddu(a3, a2, Operand(at));
 
   __ Daddu(a3, a3, Operand(StandardFrameConstants::kCallerSPOffset));
-  __ sd(a3, MemOperand(sp, 2 * kPointerSize));
+  __ sd(a3, MemOperand(sp, 3 * kPointerSize));
 
   // Do the runtime call to allocate the arguments object.
   __ bind(&runtime);
-  __ TailCallRuntime(Runtime::kNewRestParam, 3, 1);
+  __ TailCallRuntime(Runtime::kNewRestParam, 4, 1);
 }
 
 
index e361862..9cd93ee 100644 (file)
@@ -275,7 +275,8 @@ void FullCodeGenerator::Generate() {
            Operand(StandardFrameConstants::kCallerSPOffset + offset));
     __ li(a2, Operand(Smi::FromInt(num_parameters)));
     __ li(a1, Operand(Smi::FromInt(rest_index)));
-    __ Push(a3, a2, a1);
+    __ li(a0, Operand(Smi::FromInt(language_mode())));
+    __ Push(a3, a2, a1, a0);
 
     RestParamAccessStub stub(isolate());
     __ CallStub(&stub);
index 08dd1e5..0e4b725 100644 (file)
@@ -2092,9 +2092,10 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
 
 void RestParamAccessStub::GenerateNew(MacroAssembler* masm) {
   // Stack layout on entry.
-  //  sp[0] : index of rest parameter
-  //  sp[4] : number of parameters
-  //  sp[8] : receiver displacement
+  //  sp[0] : language mode
+  //  sp[4] : index of rest parameter
+  //  sp[8] : number of parameters
+  //  sp[12] : receiver displacement
 
   Label runtime;
   __ LoadP(r5, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
@@ -2104,14 +2105,14 @@ void RestParamAccessStub::GenerateNew(MacroAssembler* masm) {
 
   // Patch the arguments.length and the parameters pointer.
   __ LoadP(r4, MemOperand(r5, ArgumentsAdaptorFrameConstants::kLengthOffset));
-  __ StoreP(r4, MemOperand(sp, 1 * kPointerSize));
+  __ StoreP(r4, MemOperand(sp, 2 * kPointerSize));
   __ SmiToPtrArrayOffset(r6, r4);
   __ add(r6, r5, r6);
   __ addi(r6, r6, Operand(StandardFrameConstants::kCallerSPOffset));
-  __ StoreP(r6, MemOperand(sp, 2 * kPointerSize));
+  __ StoreP(r6, MemOperand(sp, 3 * kPointerSize));
 
   __ bind(&runtime);
-  __ TailCallRuntime(Runtime::kNewRestParam, 3, 1);
+  __ TailCallRuntime(Runtime::kNewRestParam, 4, 1);
 }
 
 
index 845303f..8945b26 100644 (file)
@@ -273,7 +273,8 @@ void FullCodeGenerator::Generate() {
     __ addi(r6, fp, Operand(StandardFrameConstants::kCallerSPOffset + offset));
     __ mov(r5, Operand(Smi::FromInt(num_parameters)));
     __ mov(r4, Operand(Smi::FromInt(rest_index)));
-    __ Push(r6, r5, r4);
+    __ mov(r7, Operand(Smi::FromInt(language_mode())));
+    __ Push(r6, r5, r4, r7);
 
     RestParamAccessStub stub(isolate());
     __ CallStub(&stub);
index 9d35ffa..8dedcea 100644 (file)
@@ -522,10 +522,9 @@ RUNTIME_FUNCTION(Runtime_NewStrictArguments) {
 }
 
 
-static Handle<JSArray> NewRestParam(Isolate* isolate,
-                                    Object** parameters,
-                                    int num_params,
-                                    int rest_index) {
+static Handle<JSArray> NewRestParam(Isolate* isolate, Object** parameters,
+                                    int num_params, int rest_index,
+                                    LanguageMode language_mode) {
   parameters -= rest_index;
   int num_elements = std::max(0, num_params - rest_index);
   Handle<FixedArray> elements =
@@ -533,26 +532,29 @@ static Handle<JSArray> NewRestParam(Isolate* isolate,
   for (int i = 0; i < num_elements; ++i) {
     elements->set(i, *--parameters);
   }
-  return isolate->factory()->NewJSArrayWithElements(elements, FAST_ELEMENTS,
-                                                    num_elements);
+  return isolate->factory()->NewJSArrayWithElements(
+      elements, FAST_ELEMENTS, num_elements, strength(language_mode));
 }
 
 
 RUNTIME_FUNCTION(Runtime_NewRestParam) {
   HandleScope scope(isolate);
-  DCHECK(args.length() == 3);
+  DCHECK(args.length() == 4);
   Object** parameters = reinterpret_cast<Object**>(args[0]);
   CONVERT_SMI_ARG_CHECKED(num_params, 1);
   CONVERT_SMI_ARG_CHECKED(rest_index, 2);
+  CONVERT_SMI_ARG_CHECKED(language_mode, 3);
 
-  return *NewRestParam(isolate, parameters, num_params, rest_index);
+  return *NewRestParam(isolate, parameters, num_params, rest_index,
+                       static_cast<LanguageMode>(language_mode));
 }
 
 
 RUNTIME_FUNCTION(Runtime_NewRestParamSlow) {
   HandleScope scope(isolate);
-  DCHECK(args.length() == 1);
+  DCHECK(args.length() == 2);
   CONVERT_SMI_ARG_CHECKED(rest_index, 0);
+  CONVERT_SMI_ARG_CHECKED(language_mode, 1);
 
   JavaScriptFrameIterator it(isolate);
 
@@ -563,7 +565,8 @@ RUNTIME_FUNCTION(Runtime_NewRestParamSlow) {
   int argument_count = frame->GetArgumentsLength();
   Object** parameters = reinterpret_cast<Object**>(frame->GetParameterSlot(-1));
 
-  return *NewRestParam(isolate, parameters, argument_count, rest_index);
+  return *NewRestParam(isolate, parameters, argument_count, rest_index,
+                       static_cast<LanguageMode>(language_mode));
 }
 
 
index ea5570e..d8d63ce 100644 (file)
@@ -513,8 +513,8 @@ namespace internal {
   F(NewArguments, 1, 1) /* TODO(turbofan): Only temporary */ \
   F(NewSloppyArguments, 3, 1)                                \
   F(NewStrictArguments, 3, 1)                                \
-  F(NewRestParam, 3, 1)                                      \
-  F(NewRestParamSlow, 1, 1)                                  \
+  F(NewRestParam, 4, 1)                                      \
+  F(NewRestParamSlow, 2, 1)                                  \
   F(NewClosureFromStubFailure, 1, 1)                         \
   F(NewClosure, 3, 1)                                        \
   F(NewScriptContext, 2, 1)                                  \
index 9459474..f24ae4d 100644 (file)
@@ -847,9 +847,10 @@ void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) {
 
 void RestParamAccessStub::GenerateNew(MacroAssembler* masm) {
   // rsp[0]  : return address
-  // rsp[8]  : index of rest parameter
-  // rsp[16] : number of parameters
-  // rsp[24] : receiver displacement
+  // rsp[8]  : language mode
+  // rsp[16] : index of rest parameter
+  // rsp[24] : number of parameters
+  // rsp[32] : receiver displacement
 
   // Check if the calling frame is an arguments adaptor frame.
   Label runtime;
@@ -859,7 +860,7 @@ void RestParamAccessStub::GenerateNew(MacroAssembler* masm) {
   __ j(not_equal, &runtime);
 
   // Patch the arguments.length and the parameters pointer.
-  StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER);
+  StackArgumentsAccessor args(rsp, 4, ARGUMENTS_DONT_CONTAIN_RECEIVER);
   __ movp(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset));
   __ movp(args.GetArgumentOperand(1), rcx);
   __ SmiToInteger64(rcx, rcx);
@@ -868,7 +869,7 @@ void RestParamAccessStub::GenerateNew(MacroAssembler* masm) {
   __ movp(args.GetArgumentOperand(0), rdx);
 
   __ bind(&runtime);
-  __ TailCallRuntime(Runtime::kNewRestParam, 3, 1);
+  __ TailCallRuntime(Runtime::kNewRestParam, 4, 1);
 }
 
 
index 03b35c4..1306b23 100644 (file)
@@ -262,6 +262,7 @@ void FullCodeGenerator::Generate() {
     __ Push(rdx);
     __ Push(Smi::FromInt(num_parameters));
     __ Push(Smi::FromInt(rest_index));
+    __ Push(Smi::FromInt(language_mode()));
 
     RestParamAccessStub stub(isolate());
     __ CallStub(&stub);
index 7f8571f..2303779 100644 (file)
@@ -844,9 +844,10 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
 
 void RestParamAccessStub::GenerateNew(MacroAssembler* masm) {
   // esp[0] : return address
-  // esp[4] : index of rest parameter
-  // esp[8] : number of parameters
-  // esp[12] : receiver displacement
+  // esp[4] : language mode
+  // esp[8] : index of rest parameter
+  // esp[12] : number of parameters
+  // esp[16] : receiver displacement
 
   // Check if the calling frame is an arguments adaptor frame.
   Label runtime;
@@ -857,13 +858,13 @@ void RestParamAccessStub::GenerateNew(MacroAssembler* masm) {
 
   // Patch the arguments.length and the parameters pointer.
   __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset));
-  __ mov(Operand(esp, 2 * kPointerSize), ecx);
+  __ mov(Operand(esp, 3 * kPointerSize), ecx);
   __ lea(edx, Operand(edx, ecx, times_2,
                       StandardFrameConstants::kCallerSPOffset));
-  __ mov(Operand(esp, 3 * kPointerSize), edx);
+  __ mov(Operand(esp, 4 * kPointerSize), edx);
 
   __ bind(&runtime);
-  __ TailCallRuntime(Runtime::kNewRestParam, 3, 1);
+  __ TailCallRuntime(Runtime::kNewRestParam, 4, 1);
 }
 
 
index ba7a2d4..cb4173f 100644 (file)
@@ -263,6 +263,7 @@ void FullCodeGenerator::Generate() {
     __ push(edx);
     __ push(Immediate(Smi::FromInt(num_parameters)));
     __ push(Immediate(Smi::FromInt(rest_index)));
+    __ push(Immediate(Smi::FromInt(language_mode())));
 
     RestParamAccessStub stub(isolate());
     __ CallStub(&stub);
index da19f09..a9cb60e 100644 (file)
@@ -896,9 +896,8 @@ TEST(Iteration) {
 
   // Allocate a JS array to OLD_SPACE and NEW_SPACE
   objs[next_objs_index++] = factory->NewJSArray(10);
-  objs[next_objs_index++] = factory->NewJSArray(10,
-                                                FAST_HOLEY_ELEMENTS,
-                                                TENURED);
+  objs[next_objs_index++] =
+      factory->NewJSArray(10, FAST_HOLEY_ELEMENTS, WEAK, TENURED);
 
   // Allocate a small string to OLD_DATA_SPACE and NEW_SPACE
   objs[next_objs_index++] = factory->NewStringFromStaticChars("abcdefghij");
@@ -2366,7 +2365,8 @@ TEST(PrototypeTransitionClearing) {
   {
     AlwaysAllocateScope always_allocate(isolate);
     SimulateFullSpace(space);
-    prototype = factory->NewJSArray(32 * KB, FAST_HOLEY_ELEMENTS, TENURED);
+    prototype =
+        factory->NewJSArray(32 * KB, FAST_HOLEY_ELEMENTS, WEAK, TENURED);
   }
 
   // Add a prototype on an evacuation candidate and verify that transition
@@ -4067,9 +4067,8 @@ TEST(Regress169928) {
                        JSArray::kSize + AllocationMemento::kSize +
                        kPointerSize);
 
-  Handle<JSArray> array = factory->NewJSArrayWithElements(array_data,
-                                                          FAST_SMI_ELEMENTS,
-                                                          NOT_TENURED);
+  Handle<JSArray> array =
+      factory->NewJSArrayWithElements(array_data, FAST_SMI_ELEMENTS);
 
   CHECK_EQ(Smi::FromInt(2), array->length());
   CHECK(array->HasFastSmiOrObjectElements());
index 89f58a6..d3ba5c8 100644 (file)
@@ -1035,7 +1035,7 @@ TEST(DoScavenge) {
   CcTest::heap()->CollectGarbage(i::NEW_SPACE);
 
   // Create temp object in the new space.
-  Handle<JSArray> temp = factory->NewJSArray(FAST_ELEMENTS, NOT_TENURED);
+  Handle<JSArray> temp = factory->NewJSArray(FAST_ELEMENTS, WEAK, NOT_TENURED);
   CHECK(isolate->heap()->new_space()->Contains(*temp));
 
   // Construct a double value that looks like a pointer to the new space object
@@ -1088,7 +1088,8 @@ TEST(DoScavengeWithIncrementalWriteBarrier) {
     AlwaysAllocateScope always_allocate(isolate);
     // Make sure |obj_value| is placed on an old-space evacuation candidate.
     SimulateFullSpace(old_space);
-    obj_value = factory->NewJSArray(32 * KB, FAST_HOLEY_ELEMENTS, TENURED);
+    obj_value =
+        factory->NewJSArray(32 * KB, FAST_HOLEY_ELEMENTS, WEAK, TENURED);
     ec_page = Page::FromAddress(obj_value->address());
   }
 
@@ -1373,7 +1374,7 @@ TEST(StoreBufferScanOnScavenge) {
   CHECK(isolate->heap()->old_space()->Contains(*obj));
 
   // Create temp object in the new space.
-  Handle<JSArray> temp = factory->NewJSArray(FAST_ELEMENTS, NOT_TENURED);
+  Handle<JSArray> temp = factory->NewJSArray(FAST_ELEMENTS, WEAK, NOT_TENURED);
   CHECK(isolate->heap()->new_space()->Contains(*temp));
 
   // Construct a double value that looks like a pointer to the new space object
@@ -1572,7 +1573,8 @@ static void TestIncrementalWriteBarrier(Handle<Map> map, Handle<Map> new_map,
 
     // Make sure |obj_value| is placed on an old-space evacuation candidate.
     SimulateFullSpace(old_space);
-    obj_value = factory->NewJSArray(32 * KB, FAST_HOLEY_ELEMENTS, TENURED);
+    obj_value =
+        factory->NewJSArray(32 * KB, FAST_HOLEY_ELEMENTS, WEAK, TENURED);
     ec_page = Page::FromAddress(obj_value->address());
     CHECK_NE(ec_page, Page::FromAddress(obj->address()));
   }
index db608fc..73129e7 100644 (file)
@@ -4,52 +4,37 @@
 
 // Flags: --strong-mode --allow-natives-syntax
 // Flags: --harmony-arrow-functions --harmony-rest-parameters
-// Flags: --harmony-destructuring
+// Flags: --harmony-destructuring --harmony-spread-arrays
 
 'use strict';
 
-let GeneratorFunctionPrototype = (function*(){}).__proto__;
-
-function assertStrongObject(o) {
-  assertTrue(%IsStrong(o));
-  assertSame(Object.prototype, o.__proto__);
-}
-
-function assertStrongArray(a) {
-  assertTrue(%IsStrong(a));
-  assertSame(Array.prototype, a.__proto__);
-}
-
-function assertStrongFunction(f) {
-  assertTrue(%IsStrong(f));
-  assertSame(Function.prototype, f.__proto__);
-}
-
-function assertStrongGenerator(g) {
-  assertTrue(%IsStrong(g));
-  assertSame(GeneratorFunctionPrototype, g.__proto__);
-}
-
 (function WeakObjectLiterals() {
-  assertTrue(!%IsStrong({}));
-  assertTrue(!%IsStrong({a: 0, b: 0}));
-  assertTrue(!%IsStrong({a: [], b: {}}));
-  assertTrue(!%IsStrong({a: [], b: {}}.a));
-  assertTrue(!%IsStrong({a: [], b: {}}.b));
-  assertTrue(!%IsStrong({a: {b: {c: {}}}}.a));
-  assertTrue(!%IsStrong({a: {b: {c: {}}}}.a.b));
-  assertTrue(!%IsStrong({a: {b: {c: {}}}}.a.b.c));
-  assertTrue(!%IsStrong({f: function(){}}));
-  assertTrue(!%IsStrong(Realm.eval(Realm.current(),
-                                   "({f: function(){}})")));
+  function assertWeakObject(x) {
+    assertFalse(%IsStrong(x));
+    assertSame(Object.prototype, Object.getPrototypeOf(x));
+  }
+  assertWeakObject({});
+  assertWeakObject({a: 0, b: 0});
+  assertWeakObject({a: [], b: {}});
+  assertWeakObject({a: [], b: {}}.b);
+  assertWeakObject({a: {b: {c: {}}}}.a);
+  assertWeakObject({a: {b: {c: {}}}}.a.b);
+  assertWeakObject({a: {b: {c: {}}}}.a.b.c);
+  assertWeakObject([[1], {}, [[3]]][1]);
+  assertWeakObject({f: function(){}});
+  assertWeakObject(
+    Realm.eval(Realm.current(), "({f: function(){}})"));
 })();
 
 (function StrongObjectLiterals() {
   'use strong';
+  function assertStrongObject(x) {
+    assertTrue(%IsStrong(x));
+    assertSame(Object.prototype, Object.getPrototypeOf(x));
+  }
   assertStrongObject({});
   assertStrongObject({a: 0, b: 0});
   assertStrongObject({a: [], b: {}});
-  assertStrongArray({a: [], b: {}}.a);
   assertStrongObject({a: [], b: {}}.b);
   assertStrongObject({a: {b: {c: {}}}}.a);
   assertStrongObject({a: {b: {c: {}}}}.a.b);
@@ -97,73 +82,92 @@ function assertStrongGenerator(g) {
     x191: 0, x192: 0, x193: 0, x194: 0, x195: 0,
     x196: 0, x197: 0, x198: 0, x199: 0, x200: 0,
   });
+  assertStrongObject([[1], {}, [[3]]][1]);
   assertStrongObject({[Date() + ""]: 0, [Symbol()]: 0});
   assertStrongObject({m() { super.m() }});
+  assertTrue(%IsStrong({__proto__: {}, get a() {}, set b(x) {}}));
   // Object literals with constant functions are treated specially,
   // but currently only on the toplevel (using Realm.eval to emulate that).
   assertStrongObject({f: function(){}});
-  assertStrongObject(Realm.eval(Realm.current(),
-                       "'use strong'; ({f: function(){}})"));
-  assertTrue(%IsStrong({__proto__: {}, get a() {}, set b(x) {}}));
+  assertStrongObject(
+    Realm.eval(Realm.current(), "'use strong'; ({f: function(){}})"));
 })();
 
 (function WeakArrayLiterals(...args) {
+  function assertWeakArray(x) {
+    assertFalse(%IsStrong(x));
+    assertSame(Array.prototype, Object.getPrototypeOf(x));
+  }
   let [...r] = [];
-  assertTrue(!%IsStrong(args));
-  assertTrue(!%IsStrong(r));
-  assertTrue(!%IsStrong([]));
-  assertTrue(!%IsStrong([1, 2, 3]));
-  assertTrue(!%IsStrong([[[]]]));
-  assertTrue(!%IsStrong([[1], {}, [[3]]]));
-  assertTrue(!%IsStrong([[1], {}, [[3]]][0]));
-  assertTrue(!%IsStrong([[1], {}, [[3]]][1]));
-  assertTrue(!%IsStrong([[1], {}, [[3]]][2]));
-  assertTrue(!%IsStrong([[1], {}, [[3]]][2][0]));
+  assertWeakArray(args);
+  assertWeakArray(r);
+  assertWeakArray([]);
+  assertWeakArray([1, 2, 3]);
+  assertWeakArray([1, 2, ...[3, 4], 5]);
+  assertWeakArray([[[]]]);
+  assertWeakArray([[1], {}, [[3]]]);
+  assertWeakArray([[1], {}, [[3]]][0]);
+  assertWeakArray([[1], {}, [[3]]][2]);
+  assertWeakArray([[1], {}, [[3]]][2][0]);
+  assertWeakArray({a: [], b: {}}.a);
 })();
 
 (function StrongArrayLiterals(...args) {
   'use strong';
+  function assertStrongArray(x) {
+    assertTrue(%IsStrong(x));
+    assertSame(Array.prototype, Object.getPrototypeOf(x));
+  }
   let [...r] = [];
-  // TODO(rossberg): teach strongness to FastCloneShallowArrayStub
-  // assertTrue(%IsStrong(args));
-  // assertTrue(%IsStrong(r));
-  // assertTrue(%IsStrong([]));
-  // assertTrue(%IsStrong([1, 2, 3]));
-  // assertTrue(%IsStrong([1, 2, ...[3, 4], 5]));
+  assertStrongArray(args);
+  assertStrongArray(r);
+  assertStrongArray([]);
+  assertStrongArray([1, 2, 3]);
+  assertStrongArray([1, 2, ...[3, 4], 5]);
   assertStrongArray([[[]]]);
   assertStrongArray([[1], {}, [[3]]]);
   assertStrongArray([[1], {}, [[3]]][0]);
-  assertStrongObject([[1], {}, [[3]]][1]);
   assertStrongArray([[1], {}, [[3]]][2]);
   assertStrongArray([[1], {}, [[3]]][2][0]);
+  assertStrongArray({a: [], b: {}}.a);
 })();
 
 (function WeakFunctionLiterals() {
+  function assertWeakFunction(x) {
+    assertFalse(%IsStrong(x));
+    assertFalse(%IsStrong(x.prototype));
+    assertSame(Function.prototype, Object.getPrototypeOf(x));
+  }
   function f() {}
-  assertTrue(!%IsStrong(f));
-  assertTrue(!%IsStrong(function(){}));
-  assertTrue(!%IsStrong(function f(){}));
-  assertTrue(!%IsStrong(() => {}));
-  assertTrue(!%IsStrong(x => x));
-  assertTrue(!%IsStrong({m(){}}.m));
-  assertTrue(!%IsStrong(Object.getOwnPropertyDescriptor(
-      {get a(){}}, 'a').get));
-  assertTrue(!%IsStrong(Object.getOwnPropertyDescriptor(
-      {set a(x){}}, 'a').set));
-  assertTrue(!%IsStrong((class {static m(){}}).m));
-  assertTrue(!%IsStrong(Object.getOwnPropertyDescriptor(
-      class {static get a(){}}, 'a').get));
-  assertTrue(!%IsStrong(Object.getOwnPropertyDescriptor(
-      class {static set a(x){}}, 'a').set));
-  assertTrue(!%IsStrong((new class {m(){}}).m));
-  assertTrue(!%IsStrong(Object.getOwnPropertyDescriptor(
-      (class {get a(){}}).prototype, 'a').get));
-  assertTrue(!%IsStrong(Object.getOwnPropertyDescriptor(
-      (class {set a(x){}}).prototype, 'a').set));
+  assertWeakFunction(f);
+  assertWeakFunction(function(){});
+  assertWeakFunction(function f(){});
+  assertWeakFunction(() => {});
+  assertWeakFunction(x => x);
+  assertWeakFunction({m(){}}.m);
+  assertWeakFunction(Object.getOwnPropertyDescriptor(
+      {get a(){}}, 'a').get);
+  assertWeakFunction(Object.getOwnPropertyDescriptor(
+      {set a(x){}}, 'a').set);
+  assertWeakFunction((class {static m(){}}).m);
+  assertWeakFunction(Object.getOwnPropertyDescriptor(
+      class {static get a(){}}, 'a').get);
+  assertWeakFunction(Object.getOwnPropertyDescriptor(
+      class {static set a(x){}}, 'a').set);
+  assertWeakFunction((new class {m(){}}).m);
+  assertWeakFunction(Object.getOwnPropertyDescriptor(
+      (class {get a(){}}).prototype, 'a').get);
+  assertWeakFunction(Object.getOwnPropertyDescriptor(
+      (class {set a(x){}}).prototype, 'a').set);
 })();
 
 (function StrongFunctionLiterals() {
   'use strong';
+  function assertStrongFunction(x) {
+    assertTrue(%IsStrong(x));
+    assertFalse('prototype' in x);
+    assertSame(Function.prototype, Object.getPrototypeOf(x));
+  }
   function f() {}
   assertStrongFunction(f);
   assertStrongFunction(function(){});
@@ -188,6 +192,11 @@ function assertStrongGenerator(g) {
 })();
 
 (function SelfStrongFunctionLiterals() {
+  function assertStrongFunction(x) {
+    assertTrue(%IsStrong(x));
+    assertFalse('prototype' in x);
+    assertSame(Function.prototype, Object.getPrototypeOf(x));
+  }
   function f() {'use strong'}
   assertStrongFunction(f);
   assertStrongFunction(function(){'use strong'});
@@ -211,18 +220,34 @@ function assertStrongGenerator(g) {
       (class {set a(x){'use strong'}}).prototype, 'a').set);
 })();
 
+let GeneratorPrototype = (function*(){}).__proto__;
+
 (function WeakGeneratorLiterals() {
+  function assertWeakGenerator(x) {
+    assertFalse(%IsStrong(x));
+    assertFalse(%IsStrong(x.prototype));
+    assertSame(GeneratorPrototype, Object.getPrototypeOf(x));
+    assertFalse(%IsStrong(x()));
+  }
   function* g() {}
-  assertTrue(!%IsStrong(g));
-  assertTrue(!%IsStrong(function*(){}));
-  assertTrue(!%IsStrong(function* g(){}));
-  assertTrue(!%IsStrong({*m(){}}.m));
-  assertTrue(!%IsStrong((class {static *m(){}}).m));
-  assertTrue(!%IsStrong((new class {*m(){}}).m));
+  assertWeakGenerator(g);
+  assertWeakGenerator(function*(){});
+  assertWeakGenerator(function* g(){});
+  assertWeakGenerator({*m(){}}.m);
+  assertWeakGenerator((class {static *m(){}}).m);
+  assertWeakGenerator((new class {*m(){}}).m);
 })();
 
 (function StrongGeneratorLiterals() {
   'use strong';
+  function assertStrongGenerator(x) {
+    assertTrue(%IsStrong(x));
+    // TODO(rossberg): strongify generator prototypes
+    // assertTrue(%IsStrong(x.prototype));
+    assertSame(GeneratorPrototype, Object.getPrototypeOf(x));
+    // TODO(rossberg): strongify generator instances
+    // assertTrue(%IsStrong(x()));
+  }
   function* g() {}
   assertStrongGenerator(g);
   assertStrongGenerator(function*(){});
@@ -233,6 +258,14 @@ function assertStrongGenerator(g) {
 })();
 
 (function SelfStrongGeneratorLiterals() {
+  function assertStrongGenerator(x) {
+    assertTrue(%IsStrong(x));
+    // TODO(rossberg): strongify generator prototypes
+    // assertTrue(%IsStrong(x.prototype));
+    assertSame(GeneratorPrototype, Object.getPrototypeOf(x));
+    // TODO(rossberg): strongify generator instances
+    // assertTrue(%IsStrong(x()));
+  }
   function* g() {'use strong'}
   assertStrongGenerator(g);
   assertStrongGenerator(function*(){'use strong'});
@@ -243,30 +276,31 @@ function assertStrongGenerator(g) {
 })();
 
 (function WeakClassLiterals() {
-  function assertWeakClass(C) {
-    assertTrue(!%IsStrong(C));
-    assertTrue(!%IsStrong(C.prototype));
+  function assertWeakClass(x) {
+    assertFalse(%IsStrong(x));
+    assertFalse(%IsStrong(x.prototype));
+    assertFalse(%IsStrong(new x));
   }
   class C {};
   class D extends C {};
   class E extends Object {};
-  class F extends null {};
+  // class F extends null {};
   const S = (() => {'use strong'; return class {}})();
   class G extends S {};
   assertWeakClass(C);
   assertWeakClass(D);
   assertWeakClass(E);
-  assertWeakClass(F);
+  // assertWeakClass(F);
   assertWeakClass(G);
   assertWeakClass(class {});
   assertWeakClass(class extends Object {});
-  assertWeakClass(class extends null {});
+  // assertWeakClass(class extends null {});
   assertWeakClass(class extends C {});
   assertWeakClass(class extends S {});
   assertWeakClass(class extends class {} {});
   assertWeakClass(class C {});
   assertWeakClass(class D extends Object {});
-  assertWeakClass(class D extends null {});
+  // assertWeakClass(class D extends null {});
   assertWeakClass(class D extends C {});
   assertWeakClass(class D extends S {});
   assertWeakClass(class D extends class {} {});
@@ -274,42 +308,45 @@ function assertStrongGenerator(g) {
 
 (function StrongClassLiterals() {
   'use strong';
-  function assertStrongClass(C) {
-    assertTrue(%IsStrong(C));
-    // TODO(rossberg): prototype object is not yet strongified
-    // assertTrue(%IsStrong(C.prototype));
+  function assertStrongClass(x) {
+    assertTrue(%IsStrong(x));
+    // TODO(rossberg): strongify class prototype and instance
+    // assertTrue(%IsStrong(x.prototype));
+    // assertTrue(%IsStrong(new x));
   }
   class C {};
   class D extends C {};
   class E extends Object {};
-  class F extends null {};
   const W = (1, eval)(() => {'use strict'; return class {}})();
   class G extends W {};
   assertStrongClass(C);
   assertStrongClass(D);
   assertStrongClass(E);
-  assertStrongClass(F);
   assertStrongClass(G);
   assertStrongClass(class {});
   assertStrongClass(class extends Object {});
-  assertStrongClass(class extends null {});
   assertStrongClass(class extends C {});
   assertStrongClass(class extends W {});
   assertStrongClass(class extends class {} {});
   assertStrongClass(class C {});
   assertStrongClass(class D extends Object {});
-  assertStrongClass(class D extends null {});
   assertStrongClass(class D extends C {});
   assertStrongClass(class D extends W {});
   assertStrongClass(class D extends class {} {});
 })();
 
 (function WeakRegExpLiterals() {
-  assertTrue(!%IsStrong(/abc/));
+  function assertWeakRegExp(x) {
+    assertFalse(%IsStrong(x));
+  }
+  assertWeakRegExp(/abc/);
 })();
 
 (function StrongRegExpLiterals() {
   'use strong';
-  // TODO(rossberg): implement strong regexp literals
-  // assertTrue(%IsStrong(/abc/));
+  function assertStrongRegExp(x) {
+    // TODO(rossberg): strongify regexps
+    // assertTrue(%IsStrong(x));
+  }
+  assertStrongRegExp(/abc/);
 })();