Selaa lähdekoodia

Fix class extension statements so BailOnNoProfile doesn't crash

rhuanjl 5 vuotta sitten
vanhempi
sitoutus
49d69a0a7e

+ 9 - 76
lib/Backend/IRBuilder.cpp

@@ -1639,6 +1639,15 @@ IRBuilder::BuildReg1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0)
             break;
         }
 
+    case Js::OpCode::LdBaseFncProto:
+        {
+            // reuseLoc set to true as this is only used when that is wanted - during class extension
+            reuseLoc = true;
+            srcOpnd = IR::AddrOpnd::New(m_func->GetScriptContextInfo()->GetFunctionPrototypeAddr(), IR::AddrOpndKindDynamicVar, m_func, true);
+            newOpcode = Js::OpCode::Ld_A;
+            break;
+        }
+
     case Js::OpCode::LdFalse_ReuseLoc:
         reuseLoc = true;
         // fall through
@@ -6900,24 +6909,6 @@ IRBuilder::BuildBrReg2(Js::OpCode newOpcode, uint32 offset)
     BuildBrReg2(newOpcode, offset, m_jnReader.GetCurrentOffset() + layout->RelativeJumpOffset, layout->R1, layout->R2);
 }
 
-template <typename SizePolicy>
-void
-IRBuilder::BuildBrReg3(Js::OpCode newOpcode, uint32 offset)
-{
-    Assert(!OpCodeAttr::IsProfiledOp(newOpcode));
-    Assert(OpCodeAttr::HasMultiSizeLayout(newOpcode));
-    auto layout = m_jnReader.GetLayout<Js::OpLayoutT_BrReg3<SizePolicy>>();
-
-    if (!PHASE_OFF(Js::ClosureRegCheckPhase, m_func))
-    {
-        this->DoClosureRegCheck(layout->R0);
-        this->DoClosureRegCheck(layout->R1);
-        this->DoClosureRegCheck(layout->R2);
-    }
-
-    BuildBrReg3(newOpcode, offset, m_jnReader.GetCurrentOffset() + layout->RelativeJumpOffset, layout->R0, layout->R1, layout->R2);
-}
-
 template <typename SizePolicy>
 void
 IRBuilder::BuildBrReg1Unsigned1(Js::OpCode newOpcode, uint32 offset)
@@ -7004,64 +6995,6 @@ IRBuilder::BuildBrReg2(Js::OpCode newOpcode, uint32 offset, uint targetOffset, J
     }
 }
 
-
-void
-IRBuilder::BuildBrReg3(Js::OpCode newOpcode, uint32 offset, uint targetOffset, Js::RegSlot R0, Js::RegSlot R1, Js::RegSlot R2)
-{
-    switch (newOpcode)
-    {
-        case Js::OpCode::CheckExtends:
-        {
-            IR::RegOpnd * opndExtends = BuildSrcOpnd(R2);
-            // If extends is Null, assign appropriate values to ctorParent and protoParent and jump to target offset.
-            IR::LabelInstr * labelNotNull = IR::LabelInstr::New(Js::OpCode::Label, m_func);
-            IR::BranchInstr * branchInstr = IR::BranchInstr::New(Js::OpCode::BrOnNotNullObj_A, labelNotNull, opndExtends, m_func);
-            this->AddInstr(branchInstr, offset);
-
-            IR::AddrOpnd * opndNullAddr = IR::AddrOpnd::New(m_func->GetScriptContextInfo()->GetNullAddr(), IR::AddrOpndKindDynamicVar, m_func, true);
-            IR::RegOpnd * opndProtoParent = BuildDstOpnd(R1);
-            IR::Instr * instr = IR::Instr::New(Js::OpCode::Ld_A, opndProtoParent, opndNullAddr, m_func);
-            opndNullAddr->SetValueType(ValueType::Null);
-            this->AddInstr(instr, offset);
-
-            IR::AddrOpnd * opndFuncProto = IR::AddrOpnd::New(m_func->GetScriptContextInfo()->GetFunctionPrototypeAddr(), IR::AddrOpndKindDynamicVar, m_func, true);
-            IR::RegOpnd * opndCtorParent = BuildDstOpnd(R0);
-            instr = IR::Instr::New(Js::OpCode::Ld_A, opndCtorParent, opndFuncProto, m_func);
-            this->AddInstr(instr, offset);
-
-            branchInstr = IR::BranchInstr::New(Js::OpCode::Br, nullptr, m_func);
-            this->AddBranchInstr(branchInstr, offset, targetOffset);
-
-            this->AddInstr(labelNotNull, offset);
-
-            IR::LabelInstr * labelIsCtor = IR::LabelInstr::New(Js::OpCode::Label, m_func);
-            IR::BranchInstr * brIsCtor = IR::BranchInstr::New(Js::OpCode::BrOnConstructor_A, labelIsCtor, opndExtends, m_func);
-            this->AddInstr(brIsCtor, offset);
-
-            instr = IR::Instr::New(Js::OpCode::RuntimeTypeError, m_func);
-            instr->SetSrc1(IR::IntConstOpnd::New(SCODE_CODE(JSERR_ErrorOnNew), TyInt32, m_func, true));
-            this->AddInstr(instr, offset);
-
-            this->AddInstr(labelIsCtor, offset);
-
-            if (R0 == R2 && opndCtorParent->m_sym != opndExtends->m_sym)
-            {
-                // The byte code doesn't contain a Ld_A, since the byte code regs are the same, but they've been renumbered in the JIT,
-                // so we have to assign from one to the other.
-                instr = IR::Instr::New(Js::OpCode::Ld_A, opndCtorParent, opndExtends, m_func);
-                this->AddInstr(instr, offset);
-            }
-
-            break;
-        }
-
-        default:
-            AssertMsg(false, "Unknown BrReg3 opcode");
-            break;
-
-    }
-}
-
 void
 IRBuilder::BuildEmpty(Js::OpCode newOpcode, uint32 offset)
 {

+ 0 - 1
lib/Backend/IRBuilder.h

@@ -213,7 +213,6 @@ private:
     void                BuildInitClass(uint32 offset, Js::RegSlot constructor, Js::RegSlot proto, IR::Opnd * opndProtoParent, IR::Opnd * opndCtorParent, IR::Opnd * opndEnvironment, uint index);
     void                BuildBrReg1(Js::OpCode newOpcode, uint32 offset, uint targetOffset, Js::RegSlot srcRegSlot);
     void                BuildBrReg2(Js::OpCode newOpcode, uint32 offset, uint targetOffset, Js::RegSlot src1RegSlot, Js::RegSlot src2RegSlot);
-    void                BuildBrReg3(Js::OpCode newOpcode, uint32 offset, uint targetOffset, Js::RegSlot R0, Js::RegSlot R1, Js::RegSlot R2);
     void                BuildBrBReturn(Js::OpCode newOpcode, uint32 offset, Js::RegSlot DestRegSlot, uint32 forInLoopLevel, uint32 targetOffset);
 
     IR::IndirOpnd *     BuildIndirOpnd(IR::RegOpnd *baseReg, IR::RegOpnd *indexReg);

+ 2 - 2
lib/Runtime/ByteCode/ByteCodeCacheReleaseFileVersion.h

@@ -6,7 +6,7 @@
 // NOTE: If there is a merge conflict the correct fix is to make a new GUID.
 // This file was generated with tools/regenByteCode.py
 
-// {ba0f47b7-ac35-42ef-8dfa-1935af336123}
+// {61a8b64e-9359-442c-af0c-5a4fa8058917}
 const GUID byteCodeCacheReleaseFileVersion =
-{ 0xba0f47b7, 0xac35, 0x42ef, {0x8d, 0xfa, 0x19, 0x35, 0xaf, 0x33, 0x61, 0x23 } };
+{ 0x61a8b64e, 0x9359, 0x442c, {0xaf, 0x0c, 0x5a, 0x4f, 0xa8, 0x05, 0x89, 0x17 } };
 

+ 1 - 18
lib/Runtime/ByteCode/ByteCodeDumper.cpp

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 #include "RuntimeByteCodePch.h"
@@ -1620,24 +1621,6 @@ namespace Js
         DumpReg(data->R2);
     }
 
-    template <class T>
-    void ByteCodeDumper::DumpBrReg3(OpCode op, const unaligned T * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
-    {
-        switch (op)
-        {
-            case Js::OpCode::CheckExtends:
-                DumpOffset(data->RelativeJumpOffset, reader);
-                DumpReg(data->R0);
-                DumpReg(data->R1);
-                DumpReg(data->R2);
-                break;
-
-            default:
-                AssertMsg(false, "Unknown BrReg3 opcode");
-                break;
-        }
-    }
-
     void ByteCodeDumper::DumpBrProperty(OpCode op, const unaligned OpLayoutBrProperty * data, FunctionBody * dumpFunction, ByteCodeReader& reader)
     {
         DumpOffset(data->RelativeJumpOffset, reader);

+ 17 - 2
lib/Runtime/ByteCode/ByteCodeEmitter.cpp

@@ -10891,16 +10891,31 @@ void EmitClass(ParseNodeClass * pnodeClass, ByteCodeGenerator * byteCodeGenerato
         Js::RegSlot ctorParentLoc = funcInfo->IsTmpReg(pnodeClass->pnodeExtends->location) ? pnodeClass->pnodeExtends->location : funcInfo->AcquireTmpRegister();
         Js::RegSlot protoParentLoc = funcInfo->AcquireTmpRegister();
 
-        Js::ByteCodeLabel labelParentsFound = byteCodeGenerator->Writer()->DefineLabel();
-        byteCodeGenerator->Writer()->BrReg3(Js::OpCode::CheckExtends, labelParentsFound, ctorParentLoc, protoParentLoc, pnodeClass->pnodeExtends->location);
         if (pnodeClass->pnodeExtends->location != ctorParentLoc)
         {
             byteCodeGenerator->Writer()->Reg2(Js::OpCode::Ld_A_ReuseLoc, ctorParentLoc, pnodeClass->pnodeExtends->location);
         }
+
+        Js::ByteCodeLabel needProto = byteCodeGenerator->Writer()->DefineLabel();
+        Js::ByteCodeLabel haveConstructor = byteCodeGenerator->Writer()->DefineLabel();
+        Js::ByteCodeLabel labelParentsFound = byteCodeGenerator->Writer()->DefineLabel();
+
+        byteCodeGenerator->Writer()->BrReg1(Js::OpCode::BrOnNotNullObj_A, needProto, ctorParentLoc);
+
+        byteCodeGenerator->Writer()->Reg1(Js::OpCode::LdC_A_Null, protoParentLoc);
+        byteCodeGenerator->Writer()->Reg1(Js::OpCode::LdBaseFncProto, ctorParentLoc);
+        byteCodeGenerator->Writer()->Br(labelParentsFound);
+
+        byteCodeGenerator->Writer()->MarkLabel(needProto);
+        byteCodeGenerator->Writer()->BrReg1(Js::OpCode::BrOnConstructor_A, haveConstructor, ctorParentLoc);
+        byteCodeGenerator->Writer()->W1(Js::OpCode::RuntimeTypeError, SCODE_CODE(JSERR_ErrorOnNew));
+
+        byteCodeGenerator->Writer()->MarkLabel(haveConstructor);
         uint cacheId = funcInfo->FindOrAddInlineCacheId(ctorParentLoc, Js::PropertyIds::prototype, false, false);
         byteCodeGenerator->Writer()->PatchableProperty(Js::OpCode::LdFld_ReuseLoc, protoParentLoc, ctorParentLoc, cacheId);
         byteCodeGenerator->Writer()->BrReg1(Js::OpCode::BrOnObjectOrNull_A, labelParentsFound, protoParentLoc);
         byteCodeGenerator->Writer()->W1(Js::OpCode::RuntimeTypeError, SCODE_CODE(JSERR_InvalidPrototype));
+
         byteCodeGenerator->Writer()->MarkLabel(labelParentsFound);
         if (frameDisplayLoc == funcInfo->frameDisplayRegister || frameDisplayLoc  == funcInfo->GetEnvRegister())
         {

+ 1 - 1
lib/Runtime/ByteCode/ByteCodeSerializer.cpp

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft Corporation and contributors. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 
@@ -1077,7 +1078,6 @@ public:
                 DEFAULT_LAYOUT_WITH_ONEBYTE(BrReg1);
                 DEFAULT_LAYOUT_WITH_ONEBYTE(BrReg1Unsigned1);
                 DEFAULT_LAYOUT_WITH_ONEBYTE(BrReg2);
-                DEFAULT_LAYOUT_WITH_ONEBYTE(BrReg3);
                 DEFAULT_LAYOUT(StartCall);
                 DEFAULT_LAYOUT_WITH_ONEBYTE(Profiled2CallI);
                 DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(CallI);

+ 1 - 29
lib/Runtime/ByteCode/ByteCodeWriter.cpp

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 #include "RuntimeByteCodePch.h"
@@ -874,35 +875,6 @@ namespace Js
         MULTISIZE_LAYOUT_WRITE(BrReg2, op, labelID, R1, R2);
     }
 
-    template <typename SizePolicy>
-    bool ByteCodeWriter::TryWriteBrReg3(OpCode op, ByteCodeLabel labelID, RegSlot R0, RegSlot R1, RegSlot R2)
-    {
-        OpLayoutT_BrReg3<SizePolicy> layout;
-        if (SizePolicy::Assign(layout.R0, R0) && SizePolicy::Assign(layout.R1, R1) && SizePolicy::Assign(layout.R2, R2))
-        {
-            size_t const offsetOfRelativeJumpOffsetFromEnd = sizeof(OpLayoutT_BrReg3<SizePolicy>) - offsetof(OpLayoutT_BrReg3<SizePolicy>, RelativeJumpOffset);
-            layout.RelativeJumpOffset = offsetOfRelativeJumpOffsetFromEnd;
-            m_byteCodeData.EncodeT<SizePolicy::LayoutEnum>(op, &layout, sizeof(layout), this);
-            AddJumpOffset(op, labelID, offsetOfRelativeJumpOffsetFromEnd);
-            return true;
-        }
-        return false;
-    }
-
-    void ByteCodeWriter::BrReg3(OpCode op, ByteCodeLabel labelID, RegSlot R0, RegSlot R1, RegSlot R2)
-    {
-        CheckOpen();
-        CheckOp(op, OpLayoutType::BrReg3);
-        Assert(OpCodeAttr::HasMultiSizeLayout(op));
-        CheckLabel(labelID);
-
-        R0 = ConsumeReg(R0);
-        R1 = ConsumeReg(R1);
-        R2 = ConsumeReg(R2);
-
-        MULTISIZE_LAYOUT_WRITE(BrReg3, op, labelID, R0, R1, R2);
-    }
-
     void ByteCodeWriter::BrProperty(OpCode op, ByteCodeLabel labelID, RegSlot instance, PropertyIdIndexType index)
     {
         CheckOpen();

+ 1 - 2
lib/Runtime/ByteCode/ByteCodeWriter.h

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 #pragma once
@@ -266,7 +267,6 @@ namespace Js
         void BrReg1Unsigned1(OpCode op, ByteCodeLabel labelID, RegSlot R1, uint C1);
         void BrS(OpCode op, ByteCodeLabel labelID, byte val);
         void BrReg2(OpCode op, ByteCodeLabel labelID, RegSlot R1, RegSlot R2);
-        void BrReg3(OpCode op, ByteCodeLabel labelID, RegSlot R0, RegSlot R1, RegSlot R2);
         void BrProperty(OpCode op, ByteCodeLabel labelID, RegSlot R1, PropertyIdIndexType propertyIdIndex);
         void BrLocalProperty(OpCode op, ByteCodeLabel labelID, PropertyIdIndexType propertyIdIndex);
         void BrEnvProperty(OpCode op, ByteCodeLabel labelID, PropertyIdIndexType propertyIdIndex, int32 slotIndex);
@@ -316,7 +316,6 @@ namespace Js
         template <typename SizePolicy> bool TryWriteBrReg1(OpCode op, ByteCodeLabel labelID, RegSlot R1);
         template <typename SizePolicy> bool TryWriteBrReg1Unsigned1(OpCode op, ByteCodeLabel labelID, RegSlot R1, uint C2);
         template <typename SizePolicy> bool TryWriteBrReg2(OpCode op, ByteCodeLabel labelID, RegSlot R1, RegSlot R2);
-        template <typename SizePolicy> bool TryWriteBrReg3(OpCode op, ByteCodeLabel labelID, RegSlot R0, RegSlot R1, RegSlot R2);
         template <typename SizePolicy> bool TryWriteCallI(OpCode op, RegSlot returnValueRegister, RegSlot functionRegister, ArgSlot givenArgCount);
         template <typename SizePolicy> bool TryWriteCallIFlags(OpCode op, RegSlot returnValueRegister, RegSlot functionRegister, ArgSlot givenArgCount, CallFlags callFlags);
         template <typename SizePolicy> bool TryWriteCallIWithICIndex(OpCode op, RegSlot returnValueRegister, RegSlot functionRegister, ArgSlot givenArgCount, uint32 inlineCacheIndex, bool isRootLoad);

+ 1 - 1
lib/Runtime/ByteCode/LayoutTypes.h

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 //
@@ -64,7 +65,6 @@ LAYOUT_TYPE                 (Br)
 LAYOUT_TYPE_WMS             (BrReg1)
 LAYOUT_TYPE_WMS             (BrReg2)
 LAYOUT_TYPE_WMS             (BrReg1Unsigned1)
-LAYOUT_TYPE_WMS             (BrReg3)
 LAYOUT_TYPE                 (BrS)
 LAYOUT_TYPE                 (BrProperty)
 LAYOUT_TYPE                 (BrLocalProperty)

+ 4 - 3
lib/Runtime/ByteCode/OpCodes.h

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft Corporation and contributors. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 // Default all macro to nothing
@@ -169,7 +170,7 @@ MACRO(                  BrOnHasLocalEnvProperty, BrEnvProperty,  OpSideEffect|Op
 MACRO_EXTEND(           BrOnNoLocalEnvProperty,  BrEnvProperty,  OpSideEffect|OpTempNumberSources|OpTempObjectSources)                     // Branch if object does not have the given property (NOTE: May have DOM implicit calls)
 MACRO_WMS(              BrOnObject_A,       BrReg1,         OpSideEffect|OpTempNumberSources|OpTempObjectSources)                          // Branch if typeId is not primitive type (i.e. > TypeIds_LastJavascriptPrimitiveType)
 MACRO_WMS(              BrNotNull_A,        BrReg1,         OpSideEffect|OpTempNumberSources|OpTempObjectSources)                          // Branch if not NULL
-MACRO_BACKEND_ONLY(     BrOnNotNullObj_A,   BrReg1,         OpTempNumberSources|OpTempObjectSources)
+MACRO_WMS(              BrOnNotNullObj_A,   BrReg1,         OpTempNumberSources|OpTempObjectSources)
 MACRO_EXTEND_WMS(       BrOnObjectOrNull_A, BrReg1,         OpTempNumberSources|OpTempObjectSources)
 MACRO_EXTEND_WMS(       BrNotUndecl_A,      BrReg1,         OpSideEffect|OpTempNumberSources|OpTempObjectSources)                          // Branch if source reg is NEQ to Undecl
 MACRO_BACKEND_ONLY(     BrNotEq_A,          Empty,          OpSideEffect|OpOpndHasImplicitCall|OpTempNumberSources|OpTempObjectSources) // Branch if !'>='
@@ -394,9 +395,9 @@ MACRO_EXTEND_WMS(       InitClassMemberSetComputedName,ElementI,    OpSideEffect
 MACRO_EXTEND_WMS(       InitClassMemberGetComputedName,ElementI,    OpSideEffect|OpOpndHasImplicitCall|OpPostOpDbgBailOut)                  // Class member in get syntax with computed property name
 MACRO_EXTEND_WMS(       BrOnClassConstructor,       BrReg1,         None)               // Branch if argument is a class constructor
 MACRO_EXTEND_WMS(       BrOnBaseConstructorKind,    BrReg1,         None)               // Branch if argument's [[ConstructorKind]] is 'base'
+MACRO_EXTEND_WMS(       BrOnConstructor_A,          BrReg1,         None)               // Branch if argument is a Constructor
 MACRO_BACKEND_ONLY(     NewClassProto,              Empty,          OpSideEffect)
 MACRO_BACKEND_ONLY(     NewClassConstructor,        Empty,          OpSideEffect)
-MACRO_BACKEND_ONLY(     BrOnConstructor_A,          BrReg1,         None)
 
 MACRO_BACKEND_ONLY(     ArgIn_A,                    Empty,          None)       // Copy from "in slot" to "local slot", unchecked
 MACRO_WMS(              ArgIn0,                     Reg1,           OpByteCodeOnly)     // Copy from "in slot" to "local slot", unchecked
@@ -553,6 +554,7 @@ MACRO_BACKEND_ONLY(     LdEnv,              Reg1,           None)           // L
 MACRO_BACKEND_ONLY(     LdAsmJsEnv,         Reg1,           None)           // Load the asm.js memory
 
 MACRO_WMS(              LdArgCnt,           Reg1,           None)           // Load the argument count from the current function
+MACRO_WMS(              LdBaseFncProto,     Reg1,           None)
 
 MACRO_BACKEND_ONLY(     InitLoopBodyCount,  Reg1,           None)           // fake instruction for loop body counter init
 MACRO_BACKEND_ONLY(     IncrLoopBodyCount,  Reg2,           None)           // fake instruction for loop body counter increment
@@ -611,7 +613,6 @@ MACRO_EXTEND_WMS(       InitBaseClass,      Reg2U,          OpSideEffect|OpPostO
 MACRO_EXTEND_WMS(       InitInnerBaseClass, Reg3U,          OpSideEffect|OpPostOpDbgBailOut)
 MACRO_EXTEND_WMS(       InitClass,          Reg4U,          OpSideEffect|OpPostOpDbgBailOut)
 MACRO_EXTEND_WMS(       InitInnerClass,     Reg5U,          OpSideEffect|OpPostOpDbgBailOut)
-MACRO_EXTEND_WMS(       CheckExtends,       BrReg3,         OpSideEffect)
 
 MACRO_WMS(              NewScFunc,          ElementSlotI1,  OpSideEffect)   // Create new ScriptFunction instance
 MACRO_BACKEND_ONLY(     NewScFuncData,      Reg2,           None)

+ 1 - 9
lib/Runtime/ByteCode/OpLayouts.h

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 #pragma once
@@ -270,15 +271,6 @@ namespace Js {
         typename SizePolicy::RegSlotType     R2;
     };
 
-    template <typename SizePolicy>
-    struct OpLayoutT_BrReg3
-    {
-        JumpOffset  RelativeJumpOffset;
-        typename SizePolicy::RegSlotType     R0;
-        typename SizePolicy::RegSlotType     R1;
-        typename SizePolicy::RegSlotType     R2;
-    };
-
     struct OpLayoutBrProperty     // if (R1.id) goto Offset
     {
         JumpOffset  RelativeJumpOffset;

+ 4 - 1
lib/Runtime/Language/InterpreterHandler.inl

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 // Default all macro to nothing
@@ -61,6 +62,7 @@ EXDEF2    (BRLONG,                  BrLong,                     OP_Br)
   DEF2_WMS(BRB_ALLOW_STACK,         BrOnObject_A,               JavascriptOperators::IsObject)
 EXDEF2_WMS(BRB_ALLOW_STACK,         BrOnObjectOrNull_A,         JavascriptOperators::IsObjectOrNull)
   DEF2_WMS(BRB,                     BrNotNull_A,                OP_BrNotNull_A)
+  DEF2_WMS(BRB,                     BrOnNotNullObj_A,           OP_BrOnNotNullObj_A)
 //Not emitted for byte code, keep it here for completeness
 //EXDEF2_WMS(BRB,                   BrUndecl_A,                 OP_BrUndecl_A)
 EXDEF2_WMS(BRB,                     BrNotUndecl_A,              OP_BrNotUndecl_A)
@@ -236,6 +238,7 @@ EXDEF3_WMS(CUSTOM,                  InitClassMemberGet,         OP_InitClassMemb
 EXDEF3_WMS(CUSTOM,                  InitClassMemberSetComputedName, OP_InitClassMemberSetComputedName, ElementI)
 EXDEF2_WMS(BRB,                     BrOnClassConstructor,       OP_BrOnClassConstructor)
 EXDEF2_WMS(BRB,                     BrOnBaseConstructorKind,    OP_BrOnBaseConstructorKind)
+EXDEF2_WMS(BRB,                     BrOnConstructor_A,          OP_BrOnConstructor)
   DEF3_WMS(GET_ELEM_LOCALSLOTNonVar,LdLocalSlot,                OP_LdSlot, ElementSlotI1)
 EXDEF3_WMS(GET_ELEM_PARAMSLOTNonVar,LdParamSlot,                OP_LdSlot, ElementSlotI1)
   DEF3_WMS(GET_ELEM_INNERSLOTNonVar,LdInnerSlot,                OP_LdInnerSlot, ElementSlotI2)
@@ -311,6 +314,7 @@ EXDEF3_WMS(CALL,                    ProfiledNewScObjectSpread,  PROFILEDOP(OP_Pr
   DEF2_WMS(XXtoA1Mem,               LdTrue_ReuseLoc,            JavascriptBoolean::OP_LdTrue)
   DEF2_WMS(XXtoA1Mem,               LdFalse,                    JavascriptBoolean::OP_LdFalse)
   DEF2_WMS(XXtoA1Mem,               LdFalse_ReuseLoc,           JavascriptBoolean::OP_LdFalse)
+  DEF2_WMS(XXtoA1,                  LdBaseFncProto,             OP_LdBaseFncProto)
   EXDEF2_WMS(XXtoA1Mem,             LdChakraLib,                JavascriptOperators::OP_LdChakraLib)
   DEF2_WMS(A1I1toA1Mem,             LdThis,                     JavascriptOperators::OP_GetThisNoFastPath)
 EXDEF2_WMS(XXtoA1Mem,               LdHomeObj,                  OP_LdHomeObj)
@@ -401,7 +405,6 @@ EXDEF2_WMS(XXtoA2_FB,               InitBaseClass,              OP_InitBaseClass
 EXDEF2_WMS(A1toA2_FB,               InitInnerBaseClass,         OP_InitBaseClass)
 EXDEF2_WMS(A2toA2_FB,               InitClass,                  OP_InitClass)
 EXDEF2_WMS(A3toA2_FB,               InitInnerClass,             OP_InitClass)
-EXDEF2_WMS(BR_AtoA2,                CheckExtends,               OP_CheckExtends)
   DEF2_WMS(BRBReturnP1toA1,         BrOnEmpty,                  JavascriptOperators::OP_BrOnEmpty)
   DEF2    (TRY,                     TryCatch,                   OP_TryCatch)
   DEF2    (TRY,                     TryFinally,                 OP_TryFinally)

+ 16 - 29
lib/Runtime/Language/InterpreterStackFrame.cpp

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft Corporation and contributors. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 
@@ -734,19 +735,6 @@
 
 #define PROCESS_BRCMem(name, func) PROCESS_BRCMem_COMMON(name, func,)
 
-#define PROCESS_BR_AtoA2_COMMON(name, func, suffix) \
-    case OpCode::name: \
-    { \
-        PROCESS_READ_LAYOUT(name, BrReg3, suffix); \
-        if (func(playout->R0, playout->R1, playout->R2)) \
-        { \
-            ip = m_reader.SetCurrentRelativeOffset(ip, playout->RelativeJumpOffset); \
-        } \
-        break; \
-    }
-
-#define PROCESS_BR_AtoA2(name, func) PROCESS_BR_AtoA2_COMMON(name, func,)
-
 #define PROCESS_BRPROP(name, func) \
     case OpCode::name: \
     { \
@@ -7872,22 +7860,6 @@ skipThunk:
         return InitClassHelper(environment, infoRef, protoParent, constructorParent, protoReg);
     }
 
-    bool InterpreterStackFrame::OP_CheckExtends(RegSlot regCtorParent, RegSlot regProtoParent, RegSlot regExtends)
-    {
-        Var extends = GetReg(regExtends);
-        if (JavascriptOperators::IsNull(extends))
-        {
-            SetReg(regProtoParent, scriptContext->GetLibrary()->GetNull());
-            SetReg(regCtorParent, scriptContext->GetLibrary()->GetFunctionPrototype());
-            return true;
-        }
-        if (!JavascriptOperators::IsConstructor(extends))
-        {
-            JavascriptError::ThrowTypeError(scriptContext, JSERR_ErrorOnNew);
-        }            
-        return false;
-    }
-
     Var InterpreterStackFrame::OP_InitClass(FrameDisplay *environment, FunctionInfoPtrPtr infoRef, Var constructorParent, Var protoParent, RegSlot protoReg)
     {
         return InitClassHelper(environment, infoRef, VarTo<RecyclableObject>(protoParent), VarTo<RecyclableObject>(constructorParent), protoReg);
@@ -8648,6 +8620,11 @@ skipThunk:
         return aValue != NULL;
     }
 
+    bool InterpreterStackFrame::OP_BrOnNotNullObj_A(Var aValue)
+    {
+        return aValue != scriptContext->GetLibrary()->GetNull();
+    }
+
     BOOL InterpreterStackFrame::OP_BrUndecl_A(Var aValue)
     {
         return this->scriptContext->GetLibrary()->IsUndeclBlockVar(aValue);
@@ -8687,6 +8664,16 @@ skipThunk:
         return JavascriptOperators::IsBaseConstructorKind(aValue);
     }
 
+    bool InterpreterStackFrame::OP_BrOnConstructor(Var aValue)
+    {
+        return JavascriptOperators::IsConstructor(aValue);
+    }
+
+    Var InterpreterStackFrame::OP_LdBaseFncProto()
+    {
+        return scriptContext->GetLibrary()->GetFunctionPrototype();
+    }
+
     template<class T>
     void InterpreterStackFrame::OP_LdLen(const unaligned T * const playout)
     {

+ 4 - 1
lib/Runtime/Language/InterpreterStackFrame.h

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft Corporation and contributors. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 
@@ -476,6 +477,7 @@ namespace Js
         BOOL OP_BrFalse_A(Var aValue, ScriptContext* scriptContext);
         BOOL OP_BrTrue_A(Var aValue, ScriptContext* scriptContext);
         BOOL OP_BrNotNull_A(Var aValue);
+        bool OP_BrOnNotNullObj_A(Var aValue);
         BOOL OP_BrUndecl_A(Var aValue);
         BOOL OP_BrNotUndecl_A(Var aValue);
         BOOL OP_BrOnHasProperty(Var argInstance, uint propertyIdIndex, ScriptContext* scriptContext);
@@ -483,6 +485,7 @@ namespace Js
         BOOL OP_BrOnHasEnvProperty(Var envInstance, int32 slotIndex, uint propertyIdIndex, ScriptContext* scriptContext);
         BOOL OP_BrOnClassConstructor(Var aValue);
         BOOL OP_BrOnBaseConstructorKind(Var aValue);
+        bool OP_BrOnConstructor(Var aValue);
 
         RecyclableObject * OP_CallGetFunc(Var target);
 
@@ -789,7 +792,7 @@ namespace Js
         Var OP_InitBaseClass(FrameDisplay *environment, FunctionInfoPtrPtr infoRef, RegSlot protoReg);
         Var OP_InitClass(FrameDisplay *environment, FunctionInfoPtrPtr infoRef, Var ctorParent, Var protoParent, RegSlot protoReg);
         Var InitClassHelper(FrameDisplay *environment, FunctionInfoPtrPtr infoRef, RecyclableObject *protoParent, RecyclableObject *constructorParent, RegSlot protoReg);
-        bool OP_CheckExtends(RegSlot ctorParent, RegSlot protoParent, RegSlot extends);
+        Var OP_LdBaseFncProto();
         inline Var OP_LdHomeObj(ScriptContext * scriptContext);
         inline Var OP_LdFuncObj(ScriptContext * scriptContext);
         template <typename T> void OP_LdElementUndefined(const unaligned OpLayoutT_ElementU<T>* playout);

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 433 - 433
lib/Runtime/Library/InJavascript/JsBuiltIn.bc.32b.h


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 433 - 433
lib/Runtime/Library/InJavascript/JsBuiltIn.bc.64b.h


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 410 - 410
lib/Runtime/Library/InJavascript/JsBuiltIn.nojit.bc.32b.h


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 410 - 410
lib/Runtime/Library/InJavascript/JsBuiltIn.nojit.bc.64b.h


+ 12 - 0
test/es6/classes_bugfixes.js

@@ -1,5 +1,6 @@
 //-------------------------------------------------------------------------------------------------------
 // Copyright (C) Microsoft. All rights reserved.
+// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 
@@ -495,6 +496,17 @@ var tests = [
     body: function() {
       assert.throws(function () { eval("1,class extends[]/print(1){}"); }, SyntaxError, "Parsing extends expr should not go past a term", "Expected '{'");
     }
+  },
+  {
+    name : "#6487 Recursive class declaration with extends function call should throw stack space, not nullptr-de-ref",
+    body : function() {
+      function recur() {
+        class a extends 'x'.match({})
+        {}
+        recur();
+      }
+      assert.throws(recur, Error, "Out of stack space");
+    }
   }
 ];
 

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä