diff --git a/src/compiler/BytecodeGenerator.cpp b/src/compiler/BytecodeGenerator.cpp index ce9147be..6b59b07e 100644 --- a/src/compiler/BytecodeGenerator.cpp +++ b/src/compiler/BytecodeGenerator.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include "../interpreter/bytecodes.h" #include "../vm/Globals.h" @@ -39,19 +40,20 @@ #include "../vmobjects/VMMethod.h" #include "../vmobjects/VMSymbol.h" #include "MethodGenerationContext.h" +#include "Parser.h" void Emit1(MethodGenerationContext& mgenc, uint8_t bytecode, int64_t stackEffect) { mgenc.AddBytecode(bytecode, stackEffect); } -void Emit2(MethodGenerationContext& mgenc, uint8_t bytecode, size_t idx, +void Emit2(MethodGenerationContext& mgenc, uint8_t bytecode, uint8_t idx, int64_t stackEffect) { mgenc.AddBytecode(bytecode, stackEffect); mgenc.AddBytecodeArgument(idx); } -void Emit3(MethodGenerationContext& mgenc, uint8_t bytecode, size_t idx, +void Emit3(MethodGenerationContext& mgenc, uint8_t bytecode, uint8_t idx, size_t ctx, int64_t stackEffect) { mgenc.AddBytecode(bytecode, stackEffect); mgenc.AddBytecodeArgument(idx); @@ -66,9 +68,23 @@ void EmitDUP(MethodGenerationContext& mgenc) { Emit1(mgenc, BC_DUP, 1); } -void EmitPUSHLOCAL(MethodGenerationContext& mgenc, size_t idx, size_t ctx) { - assert(idx >= 0); - assert(ctx >= 0); +void EmitPUSHLOCAL(MethodGenerationContext& mgenc, const Parser& parser, + size_t index, size_t context) { + if (index > std::numeric_limits::max()) { + parser.ParseError( + "The method has too many local variables. You may be able to split " + "up this method into multiple to avoid the issue."); + } + + if (context > std::numeric_limits::max()) { + parser.ParseError( + "This block is too deeply nested. You may be able to split up this " + "method into multiple to avoid the issue."); + } + + const uint8_t idx = index; + const uint8_t ctx = context; + if (ctx == 0) { if (idx == 0) { Emit1(mgenc, BC_PUSH_LOCAL_0, 1); @@ -86,9 +102,22 @@ void EmitPUSHLOCAL(MethodGenerationContext& mgenc, size_t idx, size_t ctx) { Emit3(mgenc, BC_PUSH_LOCAL, idx, ctx, 1); } -void EmitPUSHARGUMENT(MethodGenerationContext& mgenc, size_t idx, size_t ctx) { - assert(idx >= 0); - assert(ctx >= 0); +void EmitPUSHARGUMENT(MethodGenerationContext& mgenc, const Parser& parser, + size_t index, size_t context) { + if (index > std::numeric_limits::max()) { + parser.ParseError( + "The method has too many arguments. You may be able to split up " + "this method into multiple to avoid the issue."); + } + + if (context > std::numeric_limits::max()) { + parser.ParseError( + "This block is too deeply nested. You may be able to split up this " + "method into multiple to avoid the issue."); + } + + const uint8_t idx = index; + const uint8_t ctx = context; if (ctx == 0) { if (idx == 0) { @@ -109,23 +138,27 @@ void EmitPUSHARGUMENT(MethodGenerationContext& mgenc, size_t idx, size_t ctx) { Emit3(mgenc, BC_PUSH_ARGUMENT, idx, ctx, 1); } -void EmitPUSHFIELD(MethodGenerationContext& mgenc, VMSymbol* field) { - const uint8_t idx = mgenc.GetFieldIndex(field); - if (idx == 0) { - Emit1(mgenc, BC_PUSH_FIELD_0, 1); - } else if (idx == 1) { - Emit1(mgenc, BC_PUSH_FIELD_1, 1); - } else { - Emit2(mgenc, BC_PUSH_FIELD, idx, 1); +void EmitPUSHFIELD(MethodGenerationContext& mgenc, const Parser& parser, + VMSymbol* field) { + const int64_t idx = mgenc.GetFieldIndex(field); + if (idx < 0 || idx > std::numeric_limits::max()) { + parser.ParseError( + "The method tries to access a field that cannot be represented in " + "the SOM++ bytecodes. Make sure this class and its superclasses " + "have less than 256 fields in total."); } + + EmitPushFieldWithIndex(mgenc, idx); } -void EmitPUSHBLOCK(MethodGenerationContext& mgenc, VMInvokable* block) { - const uint8_t idx = mgenc.AddLiteralIfAbsent(block); +void EmitPUSHBLOCK(MethodGenerationContext& mgenc, const Parser& parser, + VMInvokable* block) { + const uint8_t idx = mgenc.AddLiteralIfAbsent(block, parser); Emit2(mgenc, BC_PUSH_BLOCK, idx, 1); } -void EmitPUSHCONSTANT(MethodGenerationContext& mgenc, vm_oop_t cst) { +void EmitPUSHCONSTANT(MethodGenerationContext& mgenc, const Parser& parser, + vm_oop_t cst) { // this isn't very robust with respect to initialization order // so, we check here, and hope it's working, but alternatively // we also make sure that we don't miss anything in the else @@ -148,7 +181,7 @@ void EmitPUSHCONSTANT(MethodGenerationContext& mgenc, vm_oop_t cst) { return; } - const uint8_t idx = mgenc.AddLiteralIfAbsent(cst); + const uint8_t idx = mgenc.AddLiteralIfAbsent(cst, parser); if (idx == 0) { Emit1(mgenc, BC_PUSH_CONSTANT_0, 1); return; @@ -173,15 +206,16 @@ void EmitPUSHCONSTANTString(MethodGenerationContext& mgenc, VMString* str) { Emit2(mgenc, BC_PUSH_CONSTANT, mgenc.FindLiteralIndex(str), 1); } -void EmitPUSHGLOBAL(MethodGenerationContext& mgenc, VMSymbol* global) { +void EmitPUSHGLOBAL(MethodGenerationContext& mgenc, const Parser& parser, + VMSymbol* global) { if (global == SymbolFor("nil")) { - EmitPUSHCONSTANT(mgenc, load_ptr(nilObject)); + EmitPUSHCONSTANT(mgenc, parser, load_ptr(nilObject)); } else if (global == SymbolFor("true")) { - EmitPUSHCONSTANT(mgenc, load_ptr(trueObject)); + EmitPUSHCONSTANT(mgenc, parser, load_ptr(trueObject)); } else if (global == SymbolFor("false")) { - EmitPUSHCONSTANT(mgenc, load_ptr(falseObject)); + EmitPUSHCONSTANT(mgenc, parser, load_ptr(falseObject)); } else { - const uint8_t idx = mgenc.AddLiteralIfAbsent(global); + const uint8_t idx = mgenc.AddLiteralIfAbsent(global, parser); Emit2(mgenc, BC_PUSH_GLOBAL, idx, 1); } } @@ -192,9 +226,23 @@ void EmitPOP(MethodGenerationContext& mgenc) { } } -void EmitPOPLOCAL(MethodGenerationContext& mgenc, size_t idx, size_t ctx) { - assert(idx >= 0); - assert(ctx >= 0); +void EmitPOPLOCAL(MethodGenerationContext& mgenc, const Parser& parser, + size_t index, size_t context) { + if (index > std::numeric_limits::max()) { + parser.ParseError( + "The method has too many local variables. You may be able to split " + "up this method into multiple to avoid the issue."); + } + + if (context > std::numeric_limits::max()) { + parser.ParseError( + "This block is too deeply nested. You may be able to split up this " + "method into multiple to avoid the issue."); + } + + const uint8_t idx = index; + const uint8_t ctx = context; + if (ctx == 0) { if (idx == 0) { Emit1(mgenc, BC_POP_LOCAL_0, -1); @@ -215,12 +263,32 @@ void EmitPOPLOCAL(MethodGenerationContext& mgenc, size_t idx, size_t ctx) { Emit3(mgenc, BC_POP_LOCAL, idx, ctx, -1); } -void EmitPOPARGUMENT(MethodGenerationContext& mgenc, size_t idx, size_t ctx) { +void EmitPOPARGUMENT(MethodGenerationContext& mgenc, const Parser& parser, + size_t idx, size_t ctx) { + if (idx > std::numeric_limits::max()) { + parser.ParseError( + "The method has too many arguments. You may be able to split up " + "this method into multiple to avoid the issue."); + } + + if (ctx > std::numeric_limits::max()) { + parser.ParseError( + "This block is too deeply nested. You may be able to split up this " + "method into multiple to avoid the issue."); + } + Emit3(mgenc, BC_POP_ARGUMENT, idx, ctx, -1); } -void EmitPOPFIELD(MethodGenerationContext& mgenc, VMSymbol* field) { - const uint8_t idx = mgenc.GetFieldIndex(field); +void EmitPOPFIELD(MethodGenerationContext& mgenc, const Parser& parser, + VMSymbol* field) { + const int64_t idx = mgenc.GetFieldIndex(field); + if (idx < 0 || idx > std::numeric_limits::max()) { + parser.ParseError( + "The method tries to access a field that cannot be represented in " + "the SOM++ bytecodes. Make sure this class and its superclasses " + "have less than 256 fields in total."); + } if (mgenc.OptimizeIncField(idx)) { return; @@ -229,8 +297,9 @@ void EmitPOPFIELD(MethodGenerationContext& mgenc, VMSymbol* field) { EmitPopFieldWithIndex(mgenc, idx); } -void EmitSEND(MethodGenerationContext& mgenc, VMSymbol* msg) { - const uint8_t idx = mgenc.AddLiteralIfAbsent(msg); +void EmitSEND(MethodGenerationContext& mgenc, const Parser& parser, + VMSymbol* msg) { + const uint8_t idx = mgenc.AddLiteralIfAbsent(msg, parser); const uint8_t numArgs = Signature::GetNumberOfArguments(msg); const int64_t stackEffect = -numArgs + 1; // +1 for the result @@ -238,8 +307,9 @@ void EmitSEND(MethodGenerationContext& mgenc, VMSymbol* msg) { Emit2(mgenc, numArgs == 1 ? BC_SEND_1 : BC_SEND, idx, stackEffect); } -void EmitSUPERSEND(MethodGenerationContext& mgenc, VMSymbol* msg) { - const uint8_t idx = mgenc.AddLiteralIfAbsent(msg); +void EmitSUPERSEND(MethodGenerationContext& mgenc, const Parser& parser, + VMSymbol* msg) { + const uint8_t idx = mgenc.AddLiteralIfAbsent(msg, parser); const uint8_t numArgs = Signature::GetNumberOfArguments(msg); const int64_t stackEffect = -numArgs + 1; // +1 for the result @@ -251,8 +321,8 @@ void EmitRETURNSELF(MethodGenerationContext& mgenc) { Emit1(mgenc, BC_RETURN_SELF, 0); } -void EmitRETURNLOCAL(MethodGenerationContext& mgenc) { - if (!mgenc.OptimizeReturnField()) { +void EmitRETURNLOCAL(MethodGenerationContext& mgenc, const Parser& parser) { + if (!mgenc.OptimizeReturnField(parser)) { Emit1(mgenc, BC_RETURN_LOCAL, 0); } } @@ -261,18 +331,21 @@ void EmitRETURNNONLOCAL(MethodGenerationContext& mgenc) { Emit1(mgenc, BC_RETURN_NON_LOCAL, 0); } -void EmitRETURNFIELD(MethodGenerationContext& mgenc, size_t index) { - assert(index <= 2); +void EmitRETURNFIELD(MethodGenerationContext& mgenc, const Parser& parser, + size_t index) { + if (index > 2) { + parser.ParseError( + "Internal Error: EmitRETURNFIELD has unsupported argument"); + } + uint8_t bc = 0; switch (index) { case 0: bc = BC_RETURN_FIELD_0; break; - case 1: bc = BC_RETURN_FIELD_1; break; - case 2: bc = BC_RETURN_FIELD_2; break; diff --git a/src/compiler/BytecodeGenerator.h b/src/compiler/BytecodeGenerator.h index 8f077427..52b6f196 100644 --- a/src/compiler/BytecodeGenerator.h +++ b/src/compiler/BytecodeGenerator.h @@ -34,31 +34,43 @@ void Emit1(MethodGenerationContext& mgenc, uint8_t bytecode, int64_t stackEffect); -void Emit2(MethodGenerationContext& mgenc, uint8_t bytecode, size_t idx, +void Emit2(MethodGenerationContext& mgenc, uint8_t bytecode, uint8_t idx, int64_t stackEffect); -void Emit3(MethodGenerationContext& mgenc, uint8_t bytecode, size_t idx, +void Emit3(MethodGenerationContext& mgenc, uint8_t bytecode, uint8_t idx, size_t ctx, int64_t stackEffect); void EmitHALT(MethodGenerationContext& mgenc); void EmitDUP(MethodGenerationContext& mgenc); -void EmitPUSHLOCAL(MethodGenerationContext& mgenc, size_t idx, size_t ctx); -void EmitPUSHARGUMENT(MethodGenerationContext& mgenc, size_t idx, size_t ctx); -void EmitPUSHFIELD(MethodGenerationContext& mgenc, VMSymbol* field); -void EmitPUSHBLOCK(MethodGenerationContext& mgenc, VMInvokable* block); -void EmitPUSHCONSTANT(MethodGenerationContext& mgenc, vm_oop_t cst); +void EmitPUSHLOCAL(MethodGenerationContext& mgenc, const Parser& parser, + size_t index, size_t context); +void EmitPUSHARGUMENT(MethodGenerationContext& mgenc, const Parser& parser, + size_t index, size_t context); +void EmitPUSHFIELD(MethodGenerationContext& mgenc, const Parser& parser, + VMSymbol* field); +void EmitPUSHBLOCK(MethodGenerationContext& mgenc, const Parser& parser, + VMInvokable* block); +void EmitPUSHCONSTANT(MethodGenerationContext& mgenc, const Parser& parser, + vm_oop_t cst); void EmitPUSHCONSTANT(MethodGenerationContext& mgenc, uint8_t literalIndex); void EmitPUSHCONSTANTString(MethodGenerationContext& mgenc, VMString* str); -void EmitPUSHGLOBAL(MethodGenerationContext& mgenc, VMSymbol* global); +void EmitPUSHGLOBAL(MethodGenerationContext& mgenc, const Parser& parser, + VMSymbol* global); void EmitPOP(MethodGenerationContext& mgenc); -void EmitPOPLOCAL(MethodGenerationContext& mgenc, size_t idx, size_t ctx); -void EmitPOPARGUMENT(MethodGenerationContext& mgenc, size_t idx, size_t ctx); -void EmitPOPFIELD(MethodGenerationContext& mgenc, VMSymbol* field); -void EmitSEND(MethodGenerationContext& mgenc, VMSymbol* msg); -void EmitSUPERSEND(MethodGenerationContext& mgenc, VMSymbol* msg); +void EmitPOPLOCAL(MethodGenerationContext& mgenc, const Parser& parser, + size_t index, size_t context); +void EmitPOPARGUMENT(MethodGenerationContext& mgenc, const Parser& parser, + size_t idx, size_t ctx); +void EmitPOPFIELD(MethodGenerationContext& mgenc, const Parser& parser, + VMSymbol* field); +void EmitSEND(MethodGenerationContext& mgenc, const Parser& parser, + VMSymbol* msg); +void EmitSUPERSEND(MethodGenerationContext& mgenc, const Parser& parser, + VMSymbol* msg); void EmitRETURNSELF(MethodGenerationContext& mgenc); -void EmitRETURNLOCAL(MethodGenerationContext& mgenc); +void EmitRETURNLOCAL(MethodGenerationContext& mgenc, const Parser& parser); void EmitRETURNNONLOCAL(MethodGenerationContext& mgenc); -void EmitRETURNFIELD(MethodGenerationContext& mgenc, size_t index); +void EmitRETURNFIELD(MethodGenerationContext& mgenc, const Parser& parser, + size_t index); void EmitINC(MethodGenerationContext& mgenc); void EmitDEC(MethodGenerationContext& mgenc); diff --git a/src/compiler/MethodGenerationContext.cpp b/src/compiler/MethodGenerationContext.cpp index 602b7900..6bb59bcb 100644 --- a/src/compiler/MethodGenerationContext.cpp +++ b/src/compiler/MethodGenerationContext.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,7 @@ #include "BytecodeGenerator.h" #include "ClassGenerationContext.h" #include "LexicalScope.h" +#include "Parser.h" #include "SourceCoordinate.h" #include "Variable.h" @@ -367,15 +369,24 @@ void MethodGenerationContext::AddLocal(std::string& local, locals.emplace_back(local, index, false, coord); } -uint8_t MethodGenerationContext::AddLiteral(vm_oop_t lit) { +uint8_t MethodGenerationContext::AddLiteral(vm_oop_t lit, + const Parser& parser) { assert(!AS_OBJ(lit)->IsMarkedInvalid()); - uint8_t const idx = literals.size(); + size_t const index = literals.size(); + + if (index > std::numeric_limits::max()) { + parser.ParseError( + "The method has too many literals. You may be able to split up " + "this method into multiple."); + } + literals.push_back(lit); - return idx; + return index; } -uint8_t MethodGenerationContext::AddLiteralIfAbsent(vm_oop_t lit) { +uint8_t MethodGenerationContext::AddLiteralIfAbsent(vm_oop_t lit, + const Parser& parser) { int64_t const idx = IndexOf(literals, lit); if (idx != -1) { assert(idx < 256); @@ -383,7 +394,7 @@ uint8_t MethodGenerationContext::AddLiteralIfAbsent(vm_oop_t lit) { "Expect index to be inside the literals vector."); return (uint8_t)idx; } - return AddLiteral(lit); + return AddLiteral(lit, parser); } void MethodGenerationContext::UpdateLiteral(vm_oop_t oldValue, uint8_t index, @@ -431,11 +442,11 @@ void MethodGenerationContext::AddBytecode(uint8_t bc, int64_t stackEffect) { last4Bytecodes[3] = bc; } -void MethodGenerationContext::AddBytecodeArgument(uint8_t bc) { - bytecode.push_back(bc); +void MethodGenerationContext::AddBytecodeArgument(uint8_t arg) { + bytecode.push_back(arg); } -size_t MethodGenerationContext::AddBytecodeArgumentAndGetIndex(uint8_t bc) { +size_t MethodGenerationContext::AddBytecodeArgumentAndGetIndex(size_t bc) { size_t const index = bytecode.size(); AddBytecodeArgument(bc); return index; @@ -522,7 +533,8 @@ MethodGenerationContext::extractBlockMethodsAndRemoveBytecodes() { return {toBeInlined1, toBeInlined2}; } -bool MethodGenerationContext::InlineThenBranch(JumpCondition condition) { +bool MethodGenerationContext::InlineThenBranch(const Parser& parser, + JumpCondition condition) { // HACK: We do assume that the receiver on the stack is a boolean, // HACK: similar to the IfTrueIfFalseNode. // HACK: We don't support anything but booleans at the moment. @@ -538,7 +550,7 @@ bool MethodGenerationContext::InlineThenBranch(JumpCondition condition) { isCurrentlyInliningABlock = true; - toBeInlined->InlineInto(*this); + toBeInlined->InlineInto(*this, parser); PatchJumpOffsetToPointToNextInstruction(jumpOffsetIdxToSkipBody); // with the jumping, it's best to prevent any subsequent optimizations here @@ -548,7 +560,8 @@ bool MethodGenerationContext::InlineThenBranch(JumpCondition condition) { return true; } -bool MethodGenerationContext::InlineThenElseBranches(JumpCondition condition) { +bool MethodGenerationContext::InlineThenElseBranches(const Parser& parser, + JumpCondition condition) { // HACK: We do assume that the receiver on the stack is a boolean, // HACK: similar to the IfTrueIfFalseNode. // HACK: We don't support anything but booleans at the moment. @@ -568,7 +581,7 @@ bool MethodGenerationContext::InlineThenElseBranches(JumpCondition condition) { EmitJumpOnWithDummyOffset(*this, condition, true); isCurrentlyInliningABlock = true; - condMethod->InlineInto(*this); + condMethod->InlineInto(*this, parser); size_t const jumpOffsetIdxToSkipFalseBranch = EmitJumpWithDumyOffset(*this); @@ -577,7 +590,7 @@ bool MethodGenerationContext::InlineThenElseBranches(JumpCondition condition) { // prevent optimizations between blocks to avoid issues with jump targets resetLastBytecodeBuffer(); - bodyMethod->InlineInto(*this); + bodyMethod->InlineInto(*this, parser); isCurrentlyInliningABlock = false; @@ -589,7 +602,8 @@ bool MethodGenerationContext::InlineThenElseBranches(JumpCondition condition) { return true; } -bool MethodGenerationContext::InlineWhile(Parser& parser, bool isWhileTrue) { +bool MethodGenerationContext::InlineWhile(const Parser& parser, + bool isWhileTrue) { if (!hasTwoLiteralBlockArguments()) { return false; } @@ -604,12 +618,12 @@ bool MethodGenerationContext::InlineWhile(Parser& parser, bool isWhileTrue) { size_t const loopBeginIdx = OffsetOfNextInstruction(); isCurrentlyInliningABlock = true; - condMethod->InlineInto(*this); + condMethod->InlineInto(*this, parser); size_t const jumpOffsetIdxToSkipLoopBody = EmitJumpOnWithDummyOffset( *this, isWhileTrue ? ON_FALSE : ON_TRUE, true); - bodyMethod->InlineInto(*this); + bodyMethod->InlineInto(*this, parser); completeJumpsAndEmitReturningNil(parser, loopBeginIdx, jumpOffsetIdxToSkipLoopBody); @@ -619,7 +633,7 @@ bool MethodGenerationContext::InlineWhile(Parser& parser, bool isWhileTrue) { return true; } -bool MethodGenerationContext::InlineAndOr(bool isOr) { +bool MethodGenerationContext::InlineAndOr(const Parser& parser, bool isOr) { // HACK: We do assume that the receiver on the stack is a boolean, // HACK: similar to the IfTrueIfFalseNode. // HACK: We don't support anything but booleans at the moment. @@ -635,13 +649,13 @@ bool MethodGenerationContext::InlineAndOr(bool isOr) { EmitJumpOnWithDummyOffset(*this, isOr ? ON_TRUE : ON_FALSE, true); isCurrentlyInliningABlock = true; - toBeInlined->InlineInto(*this); + toBeInlined->InlineInto(*this, parser); isCurrentlyInliningABlock = false; size_t const jumpOffsetIdxToSkipPushTrue = EmitJumpWithDumyOffset(*this); PatchJumpOffsetToPointToNextInstruction(jumpOffsetIdxToSkipBranch); - EmitPUSHCONSTANT(*this, + EmitPUSHCONSTANT(*this, parser, isOr ? load_ptr(trueObject) : load_ptr(falseObject)); PatchJumpOffsetToPointToNextInstruction(jumpOffsetIdxToSkipPushTrue); @@ -651,7 +665,7 @@ bool MethodGenerationContext::InlineAndOr(bool isOr) { return true; } -bool MethodGenerationContext::InlineToDo() { +bool MethodGenerationContext::InlineToDo(const Parser& parser) { // HACK: We do assume that the receiver on the stack is a integer, // HACK: similar to the other inlined messages. // HACK: We don't support anything but integer at the moment. @@ -675,9 +689,9 @@ bool MethodGenerationContext::InlineToDo() { EmitDUP(*this); - EmitPOPLOCAL(*this, iVarIdx, 0); + EmitPOPLOCAL(*this, parser, iVarIdx, 0); - toBeInlined->InlineInto(*this, false); + toBeInlined->InlineInto(*this, parser, false); EmitPOP(*this); EmitINC(*this); @@ -797,7 +811,7 @@ void MethodGenerationContext::EmitBackwardsJumpOffsetToTarget( } void MethodGenerationContext::completeJumpsAndEmitReturningNil( - Parser& /*parser*/, size_t loopBeginIdx, + const Parser& parser, size_t loopBeginIdx, size_t jumpOffsetIdxToSkipLoopBody) { resetLastBytecodeBuffer(); EmitPOP(*this); @@ -805,7 +819,7 @@ void MethodGenerationContext::completeJumpsAndEmitReturningNil( EmitBackwardsJumpOffsetToTarget(loopBeginIdx); PatchJumpOffsetToPointToNextInstruction(jumpOffsetIdxToSkipLoopBody); - EmitPUSHCONSTANT(*this, load_ptr(nilObject)); + EmitPUSHCONSTANT(*this, parser, load_ptr(nilObject)); resetLastBytecodeBuffer(); } @@ -1015,7 +1029,7 @@ bool MethodGenerationContext::OptimizeIncField(uint8_t fieldIdx) { return false; } -bool MethodGenerationContext::OptimizeReturnField() { +bool MethodGenerationContext::OptimizeReturnField(const Parser& parser) { if (isCurrentlyInliningABlock) { return false; } @@ -1048,6 +1062,6 @@ bool MethodGenerationContext::OptimizeReturnField() { removeLastBytecodes(1); resetLastBytecodeBuffer(); - EmitRETURNFIELD(*this, index); + EmitRETURNFIELD(*this, parser, index); return true; } diff --git a/src/compiler/MethodGenerationContext.h b/src/compiler/MethodGenerationContext.h index 9b9dcb07..6a126bae 100644 --- a/src/compiler/MethodGenerationContext.h +++ b/src/compiler/MethodGenerationContext.h @@ -67,8 +67,8 @@ class MethodGenerationContext { void SetPrimitive(bool prim = true); - uint8_t AddLiteral(vm_oop_t lit); - uint8_t AddLiteralIfAbsent(vm_oop_t lit); + uint8_t AddLiteral(vm_oop_t lit, const Parser& parser); + uint8_t AddLiteralIfAbsent(vm_oop_t lit, const Parser& parser); void UpdateLiteral(vm_oop_t oldValue, uint8_t index, vm_oop_t newValue); void MarkFinished(); @@ -96,18 +96,18 @@ class MethodGenerationContext { uint8_t GetNumberOfArguments(); void AddBytecode(uint8_t bc, int64_t stackEffect); - void AddBytecodeArgument(uint8_t bc); - size_t AddBytecodeArgumentAndGetIndex(uint8_t bc); + void AddBytecodeArgument(uint8_t arg); + size_t AddBytecodeArgumentAndGetIndex(size_t bc); bool HasBytecodes(); std::vector GetBytecodes() { return bytecode; } - bool InlineWhile(Parser& parser, bool isWhileTrue); - bool InlineThenElseBranches(JumpCondition condition); - bool InlineThenBranch(JumpCondition condition); - bool InlineAndOr(bool isOr); - bool InlineToDo(); + bool InlineWhile(const Parser& parser, bool isWhileTrue); + bool InlineThenElseBranches(const Parser& parser, JumpCondition condition); + bool InlineThenBranch(const Parser& parser, JumpCondition condition); + bool InlineAndOr(const Parser& parser, bool isOr); + bool InlineToDo(const Parser& parser); inline size_t OffsetOfNextInstruction() { return bytecode.size(); } @@ -123,7 +123,7 @@ class MethodGenerationContext { bool OptimizeDupPopPopSequence(); bool OptimizeIncField(uint8_t fieldIdx); - bool OptimizeReturnField(); + bool OptimizeReturnField(const Parser& parser); bool LastBytecodeIs(size_t indexFromEnd, uint8_t bytecode); @@ -155,7 +155,8 @@ class MethodGenerationContext { VMInvokable* getLastBlockMethodAndFreeLiteral(uint8_t blockLiteralIdx); - void completeJumpsAndEmitReturningNil(Parser& parser, size_t loopBeginIdx, + void completeJumpsAndEmitReturningNil(const Parser& parser, + size_t loopBeginIdx, size_t jumpOffsetIdxToSkipLoopBody); static void checkJumpOffset(size_t jumpOffset, uint8_t bytecode); diff --git a/src/compiler/Parser.cpp b/src/compiler/Parser.cpp index c4d53808..f5d8fe12 100644 --- a/src/compiler/Parser.cpp +++ b/src/compiler/Parser.cpp @@ -131,7 +131,8 @@ bool Parser::expectOneOf(Symbol* ss) { return false; } -void Parser::genPushVariable(MethodGenerationContext& mgenc, std::string& var) { +void Parser::genPushVariable(MethodGenerationContext& mgenc, + std::string& var) const { // The purpose of this function is to find out whether the variable to be // pushed on the stack is a local variable, argument, or object field. This // is done by examining all available lexical contexts, starting with the @@ -142,21 +143,22 @@ void Parser::genPushVariable(MethodGenerationContext& mgenc, std::string& var) { if (mgenc.FindVar(var, &index, &context, &is_argument)) { if (is_argument) { - EmitPUSHARGUMENT(mgenc, index, context); + EmitPUSHARGUMENT(mgenc, *this, index, context); } else { - EmitPUSHLOCAL(mgenc, index, context); + EmitPUSHLOCAL(mgenc, *this, index, context); } } else { auto* varSymbol = SymbolFor(var); if (mgenc.HasField(varSymbol)) { - EmitPUSHFIELD(mgenc, varSymbol); + EmitPUSHFIELD(mgenc, *this, varSymbol); } else { - EmitPUSHGLOBAL(mgenc, varSymbol); + EmitPUSHGLOBAL(mgenc, *this, varSymbol); } } } -void Parser::genPopVariable(MethodGenerationContext& mgenc, std::string& var) { +void Parser::genPopVariable(MethodGenerationContext& mgenc, + std::string& var) const { // The purpose of this function is to find out whether the variable to be // popped off the stack is a local variable, argument, or object field. This // is done by examining all available lexical contexts, starting with the @@ -167,13 +169,13 @@ void Parser::genPopVariable(MethodGenerationContext& mgenc, std::string& var) { if (mgenc.FindVar(var, &index, &context, &is_argument)) { if (is_argument) { - EmitPOPARGUMENT(mgenc, index, context); + EmitPOPARGUMENT(mgenc, *this, index, context); } else { - EmitPOPLOCAL(mgenc, index, context); + EmitPOPLOCAL(mgenc, *this, index, context); } } else { auto* varSymbol = SymbolFor(var); - EmitPOPFIELD(mgenc, varSymbol); + EmitPOPFIELD(mgenc, *this, varSymbol); } } @@ -430,9 +432,9 @@ void Parser::blockBody(MethodGenerationContext& mgenc, bool seen_period, if (!is_inlined) { // if the block is empty, we need to return nil if (mgenc.IsBlockMethod() && !mgenc.HasBytecodes()) { - EmitPUSHCONSTANT(mgenc, load_ptr(nilObject)); + EmitPUSHCONSTANT(mgenc, *this, load_ptr(nilObject)); } - EmitRETURNLOCAL(mgenc); + EmitRETURNLOCAL(mgenc, *this); mgenc.MarkFinished(); } } else if (sym == EndTerm) { @@ -469,7 +471,7 @@ void Parser::result(MethodGenerationContext& mgenc) { if (mgenc.IsBlockMethod()) { EmitRETURNNONLOCAL(mgenc); } else { - EmitRETURNLOCAL(mgenc); + EmitRETURNLOCAL(mgenc, *this); } mgenc.MarkFinished(); @@ -551,7 +553,7 @@ bool Parser::primary(MethodGenerationContext& mgenc) { nestedBlock(bgenc); VMInvokable* blockMethod = bgenc.Assemble(); - EmitPUSHBLOCK(mgenc, blockMethod); + EmitPUSHBLOCK(mgenc, *this, blockMethod); break; } default: @@ -600,9 +602,9 @@ void Parser::unaryMessage(MethodGenerationContext& mgenc, bool super) { VMSymbol* msg = unarySelector(); if (super) { - EmitSUPERSEND(mgenc, msg); + EmitSUPERSEND(mgenc, *this, msg); } else { - EmitSEND(mgenc, msg); + EmitSEND(mgenc, *this, msg); } } @@ -643,15 +645,15 @@ void Parser::binaryMessage(MethodGenerationContext& mgenc, bool super) { binaryOperand(mgenc); - if (!super && ((msgSelector == "||" && mgenc.InlineAndOr(true)) || - (msgSelector == "&&" && mgenc.InlineAndOr(false)))) { + if (!super && ((msgSelector == "||" && mgenc.InlineAndOr(*this, true)) || + (msgSelector == "&&" && mgenc.InlineAndOr(*this, false)))) { return; } if (super) { - EmitSUPERSEND(mgenc, msg); + EmitSUPERSEND(mgenc, *this, msg); } else { - EmitSEND(mgenc, msg); + EmitSEND(mgenc, *this, msg); } } @@ -680,30 +682,30 @@ void Parser::keywordMessage(MethodGenerationContext& mgenc, bool super) { if (!super) { if (numParts == 1 && ((kw == "ifTrue:" && - mgenc.InlineThenBranch(JumpCondition::ON_FALSE)) || + mgenc.InlineThenBranch(*this, JumpCondition::ON_FALSE)) || (kw == "ifFalse:" && - mgenc.InlineThenBranch(JumpCondition::ON_TRUE)) || + mgenc.InlineThenBranch(*this, JumpCondition::ON_TRUE)) || (kw == "ifNil:" && - mgenc.InlineThenBranch(JumpCondition::ON_NOT_NIL)) || + mgenc.InlineThenBranch(*this, JumpCondition::ON_NOT_NIL)) || (kw == "ifNotNil:" && - mgenc.InlineThenBranch(JumpCondition::ON_NIL)) || + mgenc.InlineThenBranch(*this, JumpCondition::ON_NIL)) || (kw == "whileTrue:" && mgenc.InlineWhile(*this, true)) || (kw == "whileFalse:" && mgenc.InlineWhile(*this, false)) || - (kw == "or:" && mgenc.InlineAndOr(true)) || - (kw == "and:" && mgenc.InlineAndOr(false)))) { + (kw == "or:" && mgenc.InlineAndOr(*this, true)) || + (kw == "and:" && mgenc.InlineAndOr(*this, false)))) { return; } if (numParts == 2 && ((kw == "ifTrue:ifFalse:" && - mgenc.InlineThenElseBranches(JumpCondition::ON_FALSE)) || + mgenc.InlineThenElseBranches(*this, JumpCondition::ON_FALSE)) || (kw == "ifFalse:ifTrue:" && - mgenc.InlineThenElseBranches(JumpCondition::ON_TRUE)) || + mgenc.InlineThenElseBranches(*this, JumpCondition::ON_TRUE)) || (kw == "ifNil:ifNotNil:" && - mgenc.InlineThenElseBranches(JumpCondition::ON_NOT_NIL)) || + mgenc.InlineThenElseBranches(*this, JumpCondition::ON_NOT_NIL)) || (kw == "ifNotNil:ifNil:" && - mgenc.InlineThenElseBranches(JumpCondition::ON_NIL)) || - (kw == "to:do:" && mgenc.InlineToDo()))) { + mgenc.InlineThenElseBranches(*this, JumpCondition::ON_NIL)) || + (kw == "to:do:" && mgenc.InlineToDo(*this)))) { return; } } @@ -711,9 +713,9 @@ void Parser::keywordMessage(MethodGenerationContext& mgenc, bool super) { VMSymbol* msg = SymbolFor(kw); if (super) { - EmitSUPERSEND(mgenc, msg); + EmitSUPERSEND(mgenc, *this, msg); } else { - EmitSEND(mgenc, msg); + EmitSEND(mgenc, *this, msg); } } @@ -764,7 +766,7 @@ vm_oop_t Parser::literalNumberOop() { void Parser::literalNumber(MethodGenerationContext& mgenc) { vm_oop_t lit = literalNumberOop(); - EmitPUSHCONSTANT(mgenc, lit); + EmitPUSHCONSTANT(mgenc, *this, lit); } vm_oop_t Parser::literalDecimal(bool negateValue) { @@ -804,7 +806,7 @@ void Parser::literalSymbol(MethodGenerationContext& mgenc) { } else { symb = selector(); } - EmitPUSHCONSTANT(mgenc, symb); + EmitPUSHCONSTANT(mgenc, *this, symb); } void Parser::literalArray(MethodGenerationContext& mgenc) { @@ -817,20 +819,20 @@ void Parser::literalArray(MethodGenerationContext& mgenc) { VMSymbol* atPutMessage = SymbolFor("at:put:"); const uint8_t arraySizeLiteralIndex = - mgenc.AddLiteral(arraySizePlaceholder); + mgenc.AddLiteral(arraySizePlaceholder, *this); // create bytecode sequence for instantiating new array - EmitPUSHGLOBAL(mgenc, arrayClassName); + EmitPUSHGLOBAL(mgenc, *this, arrayClassName); EmitPUSHCONSTANT(mgenc, arraySizeLiteralIndex); - EmitSEND(mgenc, newMessage); + EmitSEND(mgenc, *this, newMessage); int64_t i = 1; while (sym != EndTerm) { vm_oop_t pushIndex = NEW_INT(i); - EmitPUSHCONSTANT(mgenc, pushIndex); + EmitPUSHCONSTANT(mgenc, *this, pushIndex); literal(mgenc); - EmitSEND(mgenc, atPutMessage); + EmitSEND(mgenc, *this, atPutMessage); i += 1; } @@ -845,7 +847,7 @@ void Parser::literalString(MethodGenerationContext& mgenc) { std::string const s = _string(); VMString* str = Universe::NewString(s); - EmitPUSHCONSTANT(mgenc, str); + EmitPUSHCONSTANT(mgenc, *this, str); } VMSymbol* Parser::selector() { @@ -897,9 +899,9 @@ void Parser::nestedBlock(MethodGenerationContext& mgenc) { if (!mgenc.IsFinished()) { if (!mgenc.HasBytecodes()) { // if the block is empty, we need to return nil - EmitPUSHCONSTANT(mgenc, load_ptr(nilObject)); + EmitPUSHCONSTANT(mgenc, *this, load_ptr(nilObject)); } - EmitRETURNLOCAL(mgenc); + EmitRETURNLOCAL(mgenc, *this); mgenc.MarkFinished(); } @@ -954,6 +956,22 @@ __attribute__((noreturn)) void Parser::parseError(const char* msg, Quit(ERR_FAIL); } +__attribute__((noreturn)) void Parser::ParseError(const char* msg) const { + std::string msgWithMeta = + "%(file)s:%(line)d:%(column)d: error: " + std::string(msg); + + ReplacePattern(msgWithMeta, "%(file)s", fname); + + std::string line = std::to_string(lexer.GetCurrentLineNumber()); + ReplacePattern(msgWithMeta, "%(line)d", line); + + std::string column = std::to_string(lexer.GetCurrentColumn()); + ReplacePattern(msgWithMeta, "%(column)d", column); + + ErrorPrint(msgWithMeta); + Quit(ERR_FAIL); +} + __attribute__((noreturn)) void Parser::parseError(const char* msg, Symbol* expected) { bool first = true; diff --git a/src/compiler/Parser.h b/src/compiler/Parser.h index b8ff55db..29cf1285 100644 --- a/src/compiler/Parser.h +++ b/src/compiler/Parser.h @@ -45,6 +45,8 @@ class Parser { void method(MethodGenerationContext& mgenc); void nestedBlock(MethodGenerationContext& mgenc); + __attribute__((noreturn)) void ParseError(const char* msg) const; + private: __attribute__((noreturn)) void parseError(const char* msg, Symbol expected); __attribute__((noreturn)) void parseError(const char* msg, @@ -118,10 +120,10 @@ class Parser { std::string _string(); void blockPattern(MethodGenerationContext& mgenc); void blockArguments(MethodGenerationContext& mgenc); - static void genPushVariable(MethodGenerationContext& /*mgenc*/, - std::string& /*var*/); - static void genPopVariable(MethodGenerationContext& /*mgenc*/, - std::string& /*var*/); + void genPushVariable(MethodGenerationContext& /*mgenc*/, + std::string& /*var*/) const; + void genPopVariable(MethodGenerationContext& /*mgenc*/, + std::string& /*var*/) const; Lexer lexer; std::string& fname; diff --git a/src/vmobjects/VMEvaluationPrimitive.cpp b/src/vmobjects/VMEvaluationPrimitive.cpp index 1d94fe33..c08c0c90 100644 --- a/src/vmobjects/VMEvaluationPrimitive.cpp +++ b/src/vmobjects/VMEvaluationPrimitive.cpp @@ -135,6 +135,7 @@ bool VMEvaluationPrimitive::IsMarkedInvalid() const { } void VMEvaluationPrimitive::InlineInto(MethodGenerationContext& /*mgenc*/, + const Parser& /*parser*/, bool /*mergeScope*/) { ErrorExit( "VMEvaluationPrimitive::InlineInto is not supported, and should not be " diff --git a/src/vmobjects/VMEvaluationPrimitive.h b/src/vmobjects/VMEvaluationPrimitive.h index e454532e..fdcbab34 100644 --- a/src/vmobjects/VMEvaluationPrimitive.h +++ b/src/vmobjects/VMEvaluationPrimitive.h @@ -51,7 +51,7 @@ class VMEvaluationPrimitive : public VMInvokable { VMFrame* Invoke(VMFrame* frm) override; VMFrame* Invoke1(VMFrame* frm) override; - void InlineInto(MethodGenerationContext& mgenc, + void InlineInto(MethodGenerationContext& mgenc, const Parser& parser, bool mergeScope = true) final; [[nodiscard]] inline uint8_t GetNumberOfArguments() const final { diff --git a/src/vmobjects/VMInvokable.h b/src/vmobjects/VMInvokable.h index a76f4552..93f82065 100644 --- a/src/vmobjects/VMInvokable.h +++ b/src/vmobjects/VMInvokable.h @@ -33,6 +33,7 @@ class MethodGenerationContext; class Variable; class VMFrame; +class Parser; class VMInvokable : public AbstractVMObject { public: @@ -46,7 +47,7 @@ class VMInvokable : public AbstractVMObject { virtual VMFrame* Invoke(VMFrame*) = 0; virtual VMFrame* Invoke1(VMFrame*) = 0; virtual void InlineInto(MethodGenerationContext& mgenc, - bool mergeScope = true) = 0; + const Parser& parser, bool mergeScope = true) = 0; virtual void MergeScopeInto( MethodGenerationContext& /*unused*/) { /* NOOP for everything but VMMethods */ diff --git a/src/vmobjects/VMMethod.cpp b/src/vmobjects/VMMethod.cpp index be013345..e5d4c496 100644 --- a/src/vmobjects/VMMethod.cpp +++ b/src/vmobjects/VMMethod.cpp @@ -181,11 +181,12 @@ std::string VMMethod::AsDebugString() const { ")"; } -void VMMethod::InlineInto(MethodGenerationContext& mgenc, bool mergeScope) { +void VMMethod::InlineInto(MethodGenerationContext& mgenc, const Parser& parser, + bool mergeScope) { if (mergeScope) { mgenc.MergeIntoScope(*lexicalScope); } - inlineInto(mgenc); + inlineInto(mgenc, parser); } std::priority_queue VMMethod::createBackJumpHeap() { @@ -200,7 +201,8 @@ std::priority_queue VMMethod::createBackJumpHeap() { return loops; } -void VMMethod::inlineInto(MethodGenerationContext& mgenc) { +void VMMethod::inlineInto(MethodGenerationContext& mgenc, + const Parser& parser) { std::priority_queue jumps; // priority queue sorted by originalJumpTargetIdx std::priority_queue backJumps = createBackJumpHeap(); @@ -269,7 +271,7 @@ void VMMethod::inlineInto(MethodGenerationContext& mgenc) { assert(ctxLevel > 0); assert(bytecode == BC_POP_ARGUMENT); - EmitPOPARGUMENT(mgenc, idx, ctxLevel - 1); + EmitPOPARGUMENT(mgenc, parser, idx, ctxLevel - 1); break; } case BC_PUSH_ARGUMENT: { @@ -277,7 +279,7 @@ void VMMethod::inlineInto(MethodGenerationContext& mgenc) { const uint8_t ctxLevel = bytecodes[i + 2]; assert(ctxLevel > 0); - EmitPUSHARGUMENT(mgenc, idx, ctxLevel - 1); + EmitPUSHARGUMENT(mgenc, parser, idx, ctxLevel - 1); break; } case BC_INC_FIELD: @@ -301,9 +303,9 @@ void VMMethod::inlineInto(MethodGenerationContext& mgenc) { } if (bytecode == BC_PUSH_LOCAL) { - EmitPUSHLOCAL(mgenc, idx, ctxLevel); + EmitPUSHLOCAL(mgenc, parser, idx, ctxLevel); } else { - EmitPOPLOCAL(mgenc, idx, ctxLevel); + EmitPOPLOCAL(mgenc, parser, idx, ctxLevel); } break; } @@ -314,7 +316,7 @@ void VMMethod::inlineInto(MethodGenerationContext& mgenc) { uint8_t const idx = bytecode - BC_PUSH_LOCAL_0; const auto* oldVar = lexicalScope->GetLocal(idx, 0); uint8_t const newIdx = mgenc.GetInlinedLocalIdx(oldVar); - EmitPUSHLOCAL(mgenc, newIdx, 0); + EmitPUSHLOCAL(mgenc, parser, newIdx, 0); break; } @@ -324,7 +326,7 @@ void VMMethod::inlineInto(MethodGenerationContext& mgenc) { uint8_t const idx = bytecode - BC_POP_LOCAL_0; const auto* oldVar = lexicalScope->GetLocal(idx, 0); uint8_t const newIdx = mgenc.GetInlinedLocalIdx(oldVar); - EmitPOPLOCAL(mgenc, newIdx, 0); + EmitPOPLOCAL(mgenc, parser, newIdx, 0); break; } @@ -335,19 +337,19 @@ void VMMethod::inlineInto(MethodGenerationContext& mgenc) { const Variable* arg = lexicalScope->GetArgument(argIdx, 0); size_t const inlinedLocalIndex = mgenc.GetInlinedLocalIdx(arg); - EmitPUSHLOCAL(mgenc, inlinedLocalIndex, 0); + EmitPUSHLOCAL(mgenc, parser, inlinedLocalIndex, 0); break; } case BC_PUSH_BLOCK: { auto* blockMethod = (VMInvokable*)GetConstant(i); blockMethod->AdaptAfterOuterInlined(1, mgenc); - EmitPUSHBLOCK(mgenc, blockMethod); + EmitPUSHBLOCK(mgenc, parser, blockMethod); break; } case BC_PUSH_CONSTANT: { vm_oop_t literal = GetConstant(i); - EmitPUSHCONSTANT(mgenc, literal); + EmitPUSHCONSTANT(mgenc, parser, literal); break; } case BC_PUSH_CONSTANT_0: @@ -355,7 +357,7 @@ void VMMethod::inlineInto(MethodGenerationContext& mgenc) { case BC_PUSH_CONSTANT_2: { const uint8_t literalIdx = bytecode - BC_PUSH_CONSTANT_0; vm_oop_t literal = GetIndexableField(literalIdx); - EmitPUSHCONSTANT(mgenc, literal); + EmitPUSHCONSTANT(mgenc, parser, literal); break; } case BC_PUSH_0: @@ -378,7 +380,7 @@ void VMMethod::inlineInto(MethodGenerationContext& mgenc) { } case BC_PUSH_GLOBAL: { auto* const sym = (VMSymbol*)GetConstant(i); - EmitPUSHGLOBAL(mgenc, sym); + EmitPUSHGLOBAL(mgenc, parser, sym); break; } case BC_SEND: @@ -387,12 +389,12 @@ void VMMethod::inlineInto(MethodGenerationContext& mgenc) { case BC_SEND_3: case BC_SEND_N: { auto* const sym = (VMSymbol*)GetConstant(i); - EmitSEND(mgenc, sym); + EmitSEND(mgenc, parser, sym); break; } case BC_SUPER_SEND: { auto* const sym = (VMSymbol*)GetConstant(i); - EmitSUPERSEND(mgenc, sym); + EmitSUPERSEND(mgenc, parser, sym); break; } case BC_RETURN_LOCAL: { @@ -404,7 +406,7 @@ void VMMethod::inlineInto(MethodGenerationContext& mgenc) { assert(mgenc.GetMaxContextLevel() > 0); EmitRETURNNONLOCAL(mgenc); } else { - EmitRETURNLOCAL(mgenc); + EmitRETURNLOCAL(mgenc, parser); } break; } diff --git a/src/vmobjects/VMMethod.h b/src/vmobjects/VMMethod.h index 114d1b34..e25da6ab 100644 --- a/src/vmobjects/VMMethod.h +++ b/src/vmobjects/VMMethod.h @@ -37,6 +37,7 @@ class MethodGenerationContext; class Interpreter; +class Parser; class Jump { public: @@ -169,7 +170,7 @@ class VMMethod : public VMInvokable { [[nodiscard]] std::string AsDebugString() const override; - void InlineInto(MethodGenerationContext& mgenc, + void InlineInto(MethodGenerationContext& mgenc, const Parser& parser, bool mergeScope = true) final; void AdaptAfterOuterInlined( @@ -184,7 +185,7 @@ class VMMethod : public VMInvokable { void Dump(const char* indent, bool printObjects) override; private: - void inlineInto(MethodGenerationContext& mgenc); + void inlineInto(MethodGenerationContext& mgenc, const Parser& parser); std::priority_queue createBackJumpHeap(); static void prepareBackJumpToCurrentAddress( diff --git a/src/vmobjects/VMPrimitive.cpp b/src/vmobjects/VMPrimitive.cpp index 75b08026..36b82e98 100644 --- a/src/vmobjects/VMPrimitive.cpp +++ b/src/vmobjects/VMPrimitive.cpp @@ -65,7 +65,7 @@ bool VMPrimitive::IsEmpty() const { } void VMPrimitive::InlineInto(MethodGenerationContext& /*mgenc*/, - bool /*mergeScope*/) { + const Parser& /*parser*/, bool /*mergeScope*/) { ErrorExit( "VMPrimitive::InlineInto is not supported, and should not be reached"); } diff --git a/src/vmobjects/VMPrimitive.h b/src/vmobjects/VMPrimitive.h index ed232ad6..b37c4dbb 100644 --- a/src/vmobjects/VMPrimitive.h +++ b/src/vmobjects/VMPrimitive.h @@ -66,7 +66,7 @@ class VMPrimitive : public VMInvokable { return nullptr; }; - void InlineInto(MethodGenerationContext& mgenc, + void InlineInto(MethodGenerationContext& mgenc, const Parser& parser, bool mergeScope = true) final; [[nodiscard]] bool IsPrimitive() const override { return true; }; diff --git a/src/vmobjects/VMSafePrimitive.cpp b/src/vmobjects/VMSafePrimitive.cpp index 57d26289..1cac43bc 100644 --- a/src/vmobjects/VMSafePrimitive.cpp +++ b/src/vmobjects/VMSafePrimitive.cpp @@ -94,6 +94,7 @@ AbstractVMObject* VMSafeTernaryPrimitive::CloneForMovingGC() const { } void VMSafePrimitive::InlineInto(MethodGenerationContext& /*mgenc*/, + const Parser& /*parser*/, bool /*mergeScope*/) { ErrorExit( "VMPrimitive::InlineInto is not supported, and should not be reached"); diff --git a/src/vmobjects/VMSafePrimitive.h b/src/vmobjects/VMSafePrimitive.h index 68740fa8..bbad44e9 100644 --- a/src/vmobjects/VMSafePrimitive.h +++ b/src/vmobjects/VMSafePrimitive.h @@ -16,7 +16,7 @@ class VMSafePrimitive : public VMInvokable { [[nodiscard]] bool IsPrimitive() const final { return true; }; - void InlineInto(MethodGenerationContext& mgenc, + void InlineInto(MethodGenerationContext& mgenc, const Parser& parser, bool mergeScope = true) final; static VMSafePrimitive* GetSafeUnary(VMSymbol* sig, UnaryPrim prim); diff --git a/src/vmobjects/VMTrivialMethod.cpp b/src/vmobjects/VMTrivialMethod.cpp index 9e7f0ca3..54cac64c 100644 --- a/src/vmobjects/VMTrivialMethod.cpp +++ b/src/vmobjects/VMTrivialMethod.cpp @@ -83,8 +83,8 @@ void VMLiteralReturn::WalkObjects(walk_heap_fn walk) { } void VMLiteralReturn::InlineInto(MethodGenerationContext& mgenc, - bool /*mergeScope*/) { - EmitPUSHCONSTANT(mgenc, load_ptr(literal)); + const Parser& parser, bool /*mergeScope*/) { + EmitPUSHCONSTANT(mgenc, parser, load_ptr(literal)); } VMFrame* VMGlobalReturn::Invoke(VMFrame* frame) { @@ -117,8 +117,8 @@ VMFrame* VMGlobalReturn::Invoke1(VMFrame* frame) { } void VMGlobalReturn::InlineInto(MethodGenerationContext& mgenc, - bool /*mergeScope*/) { - EmitPUSHGLOBAL(mgenc, load_ptr(globalName)); + const Parser& parser, bool /*mergeScope*/) { + EmitPUSHGLOBAL(mgenc, parser, load_ptr(globalName)); } void VMGlobalReturn::WalkObjects(walk_heap_fn walk) { @@ -177,7 +177,8 @@ VMFrame* VMGetter::Invoke1(VMFrame* frame) { return nullptr; } -void VMGetter::InlineInto(MethodGenerationContext& mgenc, bool /*mergeScope*/) { +void VMGetter::InlineInto(MethodGenerationContext& mgenc, + const Parser& /*parser*/, bool /*mergeScope*/) { EmitPushFieldWithIndex(mgenc, fieldIndex); } @@ -224,7 +225,7 @@ VMFrame* VMSetter::Invoke1(VMFrame* /*unused*/) { } void VMSetter::InlineInto(MethodGenerationContext& /*mgenc*/, - bool /*mergeScope*/) { + const Parser& /*parser*/, bool /*mergeScope*/) { ErrorExit("We don't currently support blocks for trivial setters"); } diff --git a/src/vmobjects/VMTrivialMethod.h b/src/vmobjects/VMTrivialMethod.h index 8997c8b5..f3a47c15 100644 --- a/src/vmobjects/VMTrivialMethod.h +++ b/src/vmobjects/VMTrivialMethod.h @@ -73,7 +73,7 @@ class VMLiteralReturn : public VMTrivialMethod { VMFrame* Invoke(VMFrame* /*frame*/) override; VMFrame* Invoke1(VMFrame* /*frame*/) override; - void InlineInto(MethodGenerationContext& mgenc, + void InlineInto(MethodGenerationContext& mgenc, const Parser& parser, bool mergeScope = true) final; [[nodiscard]] AbstractVMObject* CloneForMovingGC() const final; @@ -116,7 +116,7 @@ class VMGlobalReturn : public VMTrivialMethod { VMFrame* Invoke(VMFrame* /*frame*/) override; VMFrame* Invoke1(VMFrame* /*frame*/) override; - void InlineInto(MethodGenerationContext& mgenc, + void InlineInto(MethodGenerationContext& mgenc, const Parser& parser, bool mergeScope = true) final; [[nodiscard]] AbstractVMObject* CloneForMovingGC() const final; @@ -156,7 +156,7 @@ class VMGetter : public VMTrivialMethod { VMFrame* Invoke(VMFrame* /*frame*/) override; VMFrame* Invoke1(VMFrame* /*frame*/) override; - void InlineInto(MethodGenerationContext& mgenc, + void InlineInto(MethodGenerationContext& mgenc, const Parser& parser, bool mergeScope = true) final; [[nodiscard]] AbstractVMObject* CloneForMovingGC() const final; @@ -195,7 +195,7 @@ class VMSetter : public VMTrivialMethod { VMFrame* Invoke(VMFrame* /*frame*/) override; VMFrame* Invoke1(VMFrame* /*unused*/) override; - void InlineInto(MethodGenerationContext& mgenc, + void InlineInto(MethodGenerationContext& mgenc, const Parser& parser, bool mergeScope = true) final; [[nodiscard]] AbstractVMObject* CloneForMovingGC() const final;