From 3f5cd321f14fa15e80b71b6f79022d736680ba5a Mon Sep 17 00:00:00 2001 From: conradw Date: Tue, 2 Jun 2015 04:46:04 -0700 Subject: [PATCH] [strong] create strong array literals 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} --- src/arm/code-stubs-arm.cc | 13 +- src/arm/full-codegen-arm.cc | 3 +- src/arm64/code-stubs-arm64.cc | 31 ++-- src/arm64/full-codegen-arm64.cc | 3 +- src/builtins.cc | 7 +- src/compiler/ast-graph-builder.cc | 5 +- src/compiler/js-typed-lowering.cc | 2 + src/factory.cc | 23 +-- src/factory.h | 11 +- src/full-codegen.cc | 3 +- src/globals.h | 10 ++ src/ia32/code-stubs-ia32.cc | 13 +- src/ia32/full-codegen-ia32.cc | 1 + src/isolate.cc | 6 +- src/isolate.h | 3 +- src/json-parser.h | 2 +- src/mips/code-stubs-mips.cc | 13 +- src/mips/full-codegen-mips.cc | 3 +- src/mips64/code-stubs-mips64.cc | 13 +- src/mips64/full-codegen-mips64.cc | 3 +- src/ppc/code-stubs-ppc.cc | 13 +- src/ppc/full-codegen-ppc.cc | 3 +- src/runtime/runtime-scopes.cc | 23 +-- src/runtime/runtime.h | 4 +- src/x64/code-stubs-x64.cc | 11 +- src/x64/full-codegen-x64.cc | 1 + src/x87/code-stubs-x87.cc | 13 +- src/x87/full-codegen-x87.cc | 1 + test/cctest/test-heap.cc | 13 +- test/cctest/test-unboxed-doubles.cc | 10 +- test/mjsunit/strong/literals.js | 235 ++++++++++++++++------------ 31 files changed, 288 insertions(+), 207 deletions(-) diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc index e7ba1f3b3..da06b1034 100644 --- a/src/arm/code-stubs-arm.cc +++ b/src/arm/code-stubs-arm.cc @@ -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); } diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc index c945ce452..a792d9f3d 100644 --- a/src/arm/full-codegen-arm.cc +++ b/src/arm/full-codegen-arm.cc @@ -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); diff --git a/src/arm64/code-stubs-arm64.cc b/src/arm64/code-stubs-arm64.cc index 655f388d8..5e0778eba 100644 --- a/src/arm64/code-stubs-arm64.cc +++ b/src/arm64/code-stubs-arm64.cc @@ -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); } diff --git a/src/arm64/full-codegen-arm64.cc b/src/arm64/full-codegen-arm64.cc index e1147b991..dfbae7d59 100644 --- a/src/arm64/full-codegen-arm64.cc +++ b/src/arm64/full-codegen-arm64.cc @@ -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); diff --git a/src/builtins.cc b/src/builtins.cc index ee34cdc36..7ac60da66 100644 --- a/src/builtins.cc +++ b/src/builtins.cc @@ -988,11 +988,8 @@ BUILTIN(ArrayConcat) { ArrayStorageAllocationMode mode = has_double && IsFastObjectElementsKind(elements_kind) ? INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE : DONT_INITIALIZE_ARRAY_ELEMENTS; - Handle result_array = - isolate->factory()->NewJSArray(elements_kind, - result_len, - result_len, - mode); + Handle result_array = isolate->factory()->NewJSArray( + elements_kind, result_len, result_len, WEAK, mode); if (result_len == 0) return *result_array; int j = 0; diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc index 94057f2f2..247f67498 100644 --- a/src/compiler/ast-graph-builder.cc +++ b/src/compiler/ast-graph-builder.cc @@ -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()); diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc index 3a24ad7c7..fb59ce061 100644 --- a/src/compiler/js-typed-lowering.cc +++ b/src/compiler/js-typed-lowering.cc @@ -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); diff --git a/src/factory.cc b/src/factory.cc index 6fc18eb59..ed3afa593 100644 --- a/src/factory.cc +++ b/src/factory.cc @@ -1637,22 +1637,24 @@ Handle Factory::NewJSObjectFromMap( Handle 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::cast(NewJSObjectFromMap(handle(map), pretenure)); } -Handle Factory::NewJSArray(ElementsKind elements_kind, - int length, - int capacity, +Handle Factory::NewJSArray(ElementsKind elements_kind, int length, + int capacity, ObjectStrength strength, ArrayStorageAllocationMode mode, PretenureFlag pretenure) { - Handle array = NewJSArray(elements_kind, pretenure); + Handle array = NewJSArray(elements_kind, strength, pretenure); NewJSArrayStorage(array, length, capacity, mode); return array; } @@ -1661,9 +1663,10 @@ Handle Factory::NewJSArray(ElementsKind elements_kind, Handle Factory::NewJSArrayWithElements(Handle elements, ElementsKind elements_kind, int length, + ObjectStrength strength, PretenureFlag pretenure) { DCHECK(length <= elements->length()); - Handle array = NewJSArray(elements_kind, pretenure); + Handle array = NewJSArray(elements_kind, strength, pretenure); array->set_elements(*elements); array->set_length(Smi::FromInt(length)); diff --git a/src/factory.h b/src/factory.h index 076f81d89..6552a6793 100644 --- a/src/factory.h +++ b/src/factory.h @@ -401,23 +401,26 @@ class Factory final { // Create a JSArray with no elements. Handle 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 NewJSArray( ElementsKind elements_kind, int length, int capacity, + ObjectStrength strength = WEAK, ArrayStorageAllocationMode mode = DONT_INITIALIZE_ARRAY_ELEMENTS, PretenureFlag pretenure = NOT_TENURED); Handle 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 elements, ElementsKind elements_kind, int length, + ObjectStrength strength = WEAK, PretenureFlag pretenure = NOT_TENURED); Handle NewJSArrayWithElements( Handle 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( diff --git a/src/full-codegen.cc b/src/full-codegen.cc index 1ae52c848..c69f6252b 100644 --- a/src/full-codegen.cc +++ b/src/full-codegen.cc @@ -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; } diff --git a/src/globals.h b/src/globals.h index 23afbc256..7fdcc26ce 100644 --- a/src/globals.h +++ b/src/globals.h @@ -225,6 +225,11 @@ template 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; diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc index b1081ed89..11655713b 100644 --- a/src/ia32/code-stubs-ia32.cc +++ b/src/ia32/code-stubs-ia32.cc @@ -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); } diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc index 07910d7a3..cd8b22fa5 100644 --- a/src/ia32/full-codegen-ia32.cc +++ b/src/ia32/full-codegen-ia32.cc @@ -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); diff --git a/src/isolate.cc b/src/isolate.cc index 93005e316..efa0e28ba 100644 --- a/src/isolate.cc +++ b/src/isolate.cc @@ -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); diff --git a/src/isolate.h b/src/isolate.h index bdc3210ca..4b242a3d5 100644 --- a/src/isolate.h +++ b/src/isolate.h @@ -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; diff --git a/src/json-parser.h b/src/json-parser.h index 973e9a0fe..76882dd54 100644 --- a/src/json-parser.h +++ b/src/json-parser.h @@ -525,7 +525,7 @@ Handle JsonParser::ParseJsonArray() { fast_elements->set(i, *elements[i]); } Handle json_array = factory()->NewJSArrayWithElements( - fast_elements, FAST_ELEMENTS, pretenure_); + fast_elements, FAST_ELEMENTS, WEAK, pretenure_); return scope.CloseAndEscape(json_array); } diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc index e833ea0e6..5f87ae7ec 100644 --- a/src/mips/code-stubs-mips.cc +++ b/src/mips/code-stubs-mips.cc @@ -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); } diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc index 820009622..fa295a476 100644 --- a/src/mips/full-codegen-mips.cc +++ b/src/mips/full-codegen-mips.cc @@ -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); diff --git a/src/mips64/code-stubs-mips64.cc b/src/mips64/code-stubs-mips64.cc index fb8345be6..d6a02fdcd 100644 --- a/src/mips64/code-stubs-mips64.cc +++ b/src/mips64/code-stubs-mips64.cc @@ -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); } diff --git a/src/mips64/full-codegen-mips64.cc b/src/mips64/full-codegen-mips64.cc index e36186281..9cd93eeaa 100644 --- a/src/mips64/full-codegen-mips64.cc +++ b/src/mips64/full-codegen-mips64.cc @@ -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); diff --git a/src/ppc/code-stubs-ppc.cc b/src/ppc/code-stubs-ppc.cc index 08dd1e5c1..0e4b725a1 100644 --- a/src/ppc/code-stubs-ppc.cc +++ b/src/ppc/code-stubs-ppc.cc @@ -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); } diff --git a/src/ppc/full-codegen-ppc.cc b/src/ppc/full-codegen-ppc.cc index 845303ff4..8945b2644 100644 --- a/src/ppc/full-codegen-ppc.cc +++ b/src/ppc/full-codegen-ppc.cc @@ -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); diff --git a/src/runtime/runtime-scopes.cc b/src/runtime/runtime-scopes.cc index 9d35ffaed..8dedcea6b 100644 --- a/src/runtime/runtime-scopes.cc +++ b/src/runtime/runtime-scopes.cc @@ -522,10 +522,9 @@ RUNTIME_FUNCTION(Runtime_NewStrictArguments) { } -static Handle NewRestParam(Isolate* isolate, - Object** parameters, - int num_params, - int rest_index) { +static Handle 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 elements = @@ -533,26 +532,29 @@ static Handle 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(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(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(frame->GetParameterSlot(-1)); - return *NewRestParam(isolate, parameters, argument_count, rest_index); + return *NewRestParam(isolate, parameters, argument_count, rest_index, + static_cast(language_mode)); } diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index ea5570ec5..d8d63ceb7 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -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) \ diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc index 9459474e9..f24ae4d72 100644 --- a/src/x64/code-stubs-x64.cc +++ b/src/x64/code-stubs-x64.cc @@ -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); } diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc index 03b35c413..1306b2353 100644 --- a/src/x64/full-codegen-x64.cc +++ b/src/x64/full-codegen-x64.cc @@ -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); diff --git a/src/x87/code-stubs-x87.cc b/src/x87/code-stubs-x87.cc index 7f8571f5d..230377963 100644 --- a/src/x87/code-stubs-x87.cc +++ b/src/x87/code-stubs-x87.cc @@ -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); } diff --git a/src/x87/full-codegen-x87.cc b/src/x87/full-codegen-x87.cc index ba7a2d476..cb4173f80 100644 --- a/src/x87/full-codegen-x87.cc +++ b/src/x87/full-codegen-x87.cc @@ -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); diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc index da19f09f7..a9cb60e98 100644 --- a/test/cctest/test-heap.cc +++ b/test/cctest/test-heap.cc @@ -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 array = factory->NewJSArrayWithElements(array_data, - FAST_SMI_ELEMENTS, - NOT_TENURED); + Handle array = + factory->NewJSArrayWithElements(array_data, FAST_SMI_ELEMENTS); CHECK_EQ(Smi::FromInt(2), array->length()); CHECK(array->HasFastSmiOrObjectElements()); diff --git a/test/cctest/test-unboxed-doubles.cc b/test/cctest/test-unboxed-doubles.cc index 89f58a62e..d3ba5c847 100644 --- a/test/cctest/test-unboxed-doubles.cc +++ b/test/cctest/test-unboxed-doubles.cc @@ -1035,7 +1035,7 @@ TEST(DoScavenge) { CcTest::heap()->CollectGarbage(i::NEW_SPACE); // Create temp object in the new space. - Handle temp = factory->NewJSArray(FAST_ELEMENTS, NOT_TENURED); + Handle 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 temp = factory->NewJSArray(FAST_ELEMENTS, NOT_TENURED); + Handle 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, Handle 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())); } diff --git a/test/mjsunit/strong/literals.js b/test/mjsunit/strong/literals.js index db608fc62..73129e7a0 100644 --- a/test/mjsunit/strong/literals.js +++ b/test/mjsunit/strong/literals.js @@ -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/); })(); -- 2.34.1