diff --git a/src/compiler/BytecodeGenerator.cpp b/src/compiler/BytecodeGenerator.cpp index f24aa7e5..d23150d6 100644 --- a/src/compiler/BytecodeGenerator.cpp +++ b/src/compiler/BytecodeGenerator.cpp @@ -76,6 +76,25 @@ void BytecodeGenerator::EmitPUSHLOCAL(MethodGenerationContext* mgenc, long idx, void BytecodeGenerator::EmitPUSHARGUMENT(MethodGenerationContext* mgenc, long idx, int ctx) { + assert(idx >= 0); + assert(ctx >= 0); + + if (ctx == 0) { + if (idx == 0) { + EMIT1(BC_PUSH_SELF); + return; + } + + if (idx == 1) { + EMIT1(BC_PUSH_ARG_1); + return; + } + + if (idx == 2) { + EMIT1(BC_PUSH_ARG_2); + return; + } + } EMIT3(BC_PUSH_ARGUMENT, idx, ctx); } diff --git a/src/compiler/MethodGenerationContext.cpp b/src/compiler/MethodGenerationContext.cpp index 71a2819a..fc562e11 100644 --- a/src/compiler/MethodGenerationContext.cpp +++ b/src/compiler/MethodGenerationContext.cpp @@ -130,12 +130,12 @@ uint8_t MethodGenerationContext::ComputeStackDepth() { i++; break; case BC_DUP: - depth++; - i++; - break; case BC_PUSH_LOCAL_0: case BC_PUSH_LOCAL_1: case BC_PUSH_LOCAL_2: + case BC_PUSH_SELF: + case BC_PUSH_ARG_1: + case BC_PUSH_ARG_2: depth++; i += 1; break; diff --git a/src/interpreter/InterpreterLoop.h b/src/interpreter/InterpreterLoop.h index 53e359e7..9cc4ce53 100644 --- a/src/interpreter/InterpreterLoop.h +++ b/src/interpreter/InterpreterLoop.h @@ -80,11 +80,32 @@ vm_oop_t Start() { DISPATCH_NOGC(); LABEL_BC_PUSH_ARGUMENT: + PROLOGUE(3); + doPushArgument(bytecodeIndexGlobal - 3); + DISPATCH_NOGC(); + LABEL_BC_PUSH_SELF: + PROLOGUE(1); + { + vm_oop_t argument = GetFrame()->GetArgumentInCurrentContext(0); + GetFrame()->Push(argument); + } + DISPATCH_NOGC(); + LABEL_BC_PUSH_ARG_1: + PROLOGUE(1); + { + vm_oop_t argument = GetFrame()->GetArgumentInCurrentContext(1); + GetFrame()->Push(argument); + } + DISPATCH_NOGC(); + LABEL_BC_PUSH_ARG_2: - PROLOGUE(3); - doPushArgument(bytecodeIndexGlobal - 3); + PROLOGUE(1); + { + vm_oop_t argument = GetFrame()->GetArgumentInCurrentContext(2); + GetFrame()->Push(argument); + } DISPATCH_NOGC(); LABEL_BC_PUSH_FIELD: diff --git a/src/unitTests/BytecodeGenerationTest.cpp b/src/unitTests/BytecodeGenerationTest.cpp index d00b4236..75822dbd 100644 --- a/src/unitTests/BytecodeGenerationTest.cpp +++ b/src/unitTests/BytecodeGenerationTest.cpp @@ -76,10 +76,8 @@ std::vector BytecodeGenerationTest::blockToBytecode(const char* source, void BytecodeGenerationTest::testEmptyMethodReturnsSelf() { auto bytecodes = methodToBytecode("test = ( )"); - CPPUNIT_ASSERT_EQUAL((size_t) 4, bytecodes.size()); - check(bytecodes, { - BC_PUSH_ARGUMENT, 0, 0, + BC_PUSH_SELF, BC_RETURN_LOCAL}); } @@ -95,7 +93,7 @@ void BytecodeGenerationTest::testPushConstant() { BC_PUSH_CONSTANT_0, BC_POP, BC_PUSH_CONSTANT_1, BC_POP, BC_PUSH_CONSTANT_2, BC_POP, - BC_PUSH_ARGUMENT, 0, 0, + BC_PUSH_SELF, BC_RETURN_LOCAL }); } @@ -116,7 +114,7 @@ void BytecodeGenerationTest::testIfPushConstantSame() { BC_PUSH_BLOCK, 5, BC_SEND, 6, BC_POP, - BC_PUSH_ARGUMENT, 0, 0, + BC_PUSH_SELF, BC_RETURN_LOCAL }); } @@ -136,7 +134,7 @@ void BytecodeGenerationTest::testIfPushConstantDifferent() { BC_PUSH_BLOCK, 5, BC_SEND, 6, BC_POP, - BC_PUSH_ARGUMENT, 0, 0, + BC_PUSH_SELF, BC_RETURN_LOCAL }); } @@ -145,7 +143,7 @@ void BytecodeGenerationTest::testExplicitReturnSelf() { auto bytecodes = methodToBytecode("test = ( ^ self )"); check(bytecodes, { - BC_PUSH_ARGUMENT, 0, 0, + BC_PUSH_SELF, BC_RETURN_LOCAL }); } @@ -158,7 +156,7 @@ void BytecodeGenerationTest::testDupPopArgumentPop() { BC_DUP, BC_POP_ARGUMENT, 1, 0, BC_POP, - BC_PUSH_ARGUMENT, 0, 0, + BC_PUSH_SELF, BC_RETURN_LOCAL }); } @@ -171,7 +169,7 @@ void BytecodeGenerationTest::testDupPopArgumentPopImplicitReturnSelf() { BC_DUP, BC_POP_ARGUMENT, 1, 0, BC_POP, - BC_PUSH_ARGUMENT, 0, 0, + BC_PUSH_SELF, BC_RETURN_LOCAL }); } @@ -184,7 +182,7 @@ void BytecodeGenerationTest::testDupPopLocalPop() { BC_DUP, BC_POP_LOCAL, 0, 0, BC_POP, - BC_PUSH_ARGUMENT, 0, 0, + BC_PUSH_SELF, BC_RETURN_LOCAL }); } @@ -198,7 +196,7 @@ void BytecodeGenerationTest::testDupPopField0Pop() { BC_DUP, BC_POP_FIELD, 0, BC_POP, - BC_PUSH_ARGUMENT, 0, 0, + BC_PUSH_SELF, BC_RETURN_LOCAL }); } @@ -216,7 +214,7 @@ void BytecodeGenerationTest::testDupPopFieldPop() { BC_DUP, BC_POP_FIELD, 4, BC_POP, - BC_PUSH_ARGUMENT, 0, 0, + BC_PUSH_SELF, BC_RETURN_LOCAL }); } @@ -226,11 +224,11 @@ void BytecodeGenerationTest::testDupPopFieldReturnSelf() { auto bytecodes = methodToBytecode("test: val = ( field := val )"); check(bytecodes, { - BC_PUSH_ARGUMENT, 1, 0, + BC_PUSH_ARG_1, BC_DUP, BC_POP_FIELD, 0, BC_POP, - BC_PUSH_ARGUMENT, 0, 0, + BC_PUSH_SELF, BC_RETURN_LOCAL }); } @@ -245,11 +243,11 @@ void BytecodeGenerationTest::testDupPopFieldNReturnSelf() { auto bytecodes = methodToBytecode("test: val = ( field := val )"); check(bytecodes, { - BC_PUSH_ARGUMENT, 1, 0, + BC_PUSH_ARG_1, BC_DUP, BC_POP_FIELD, 5, BC_POP, - BC_PUSH_ARGUMENT, 0, 0, + BC_PUSH_SELF, BC_RETURN_LOCAL }); } @@ -259,7 +257,7 @@ void BytecodeGenerationTest::testSendDupPopFieldReturnLocal() { auto bytecodes = methodToBytecode("test = ( ^ field := self method )"); check(bytecodes, { - BC_PUSH_ARGUMENT, 1, 0, + BC_PUSH_SELF, BC_SEND, 0, BC_DUP, BC_POP_FIELD, 0, @@ -272,7 +270,7 @@ void BytecodeGenerationTest::testSendDupPopFieldReturnLocalPeriod() { auto bytecodes = methodToBytecode("test = ( ^ field := self method. )"); check(bytecodes, { - BC_PUSH_ARGUMENT, 1, 0, + BC_PUSH_SELF, BC_SEND, 0, BC_DUP, BC_POP_FIELD, 0, @@ -289,7 +287,7 @@ void BytecodeGenerationTest::testBlockDupPopArgumentPopReturnArg() { BC_DUP, BC_POP_ARGUMENT, 1, 0, BC_POP, - BC_PUSH_ARGUMENT, 1, 0, + BC_PUSH_ARG_1, BC_RETURN_LOCAL }); } @@ -358,7 +356,23 @@ void BytecodeGenerationTest::testPushLocalOpt() { BC_PUSH_LOCAL_2, BC_POP, BC_PUSH_LOCAL, 3, 0, BC_POP, - BC_PUSH_ARGUMENT, 0, 0, + BC_PUSH_SELF, + BC_RETURN_LOCAL + }); +} + +void BytecodeGenerationTest::testPushArgOpt() { + auto bytecodes = methodToBytecode(R"""( + test: a1 and: a2 and: a3 and: a4 = ( + self. a1. a2. a3. a4. + ) )"""); + check(bytecodes, { + BC_PUSH_SELF, BC_POP, + BC_PUSH_ARG_1, BC_POP, + BC_PUSH_ARG_2, BC_POP, + BC_PUSH_ARGUMENT, 3, 0, BC_POP, + BC_PUSH_ARGUMENT, 4, 0, BC_POP, + BC_PUSH_SELF, BC_RETURN_LOCAL }); } diff --git a/src/unitTests/BytecodeGenerationTest.h b/src/unitTests/BytecodeGenerationTest.h index 5be1f139..92265785 100644 --- a/src/unitTests/BytecodeGenerationTest.h +++ b/src/unitTests/BytecodeGenerationTest.h @@ -30,6 +30,7 @@ class BytecodeGenerationTest: public CPPUNIT_NS::TestCase { CPPUNIT_TEST(testBlockDupPopFieldReturnLocal); CPPUNIT_TEST(testBlockDupPopFieldReturnLocalDot); CPPUNIT_TEST(testPushLocalOpt); + CPPUNIT_TEST(testPushArgOpt); CPPUNIT_TEST_SUITE_END(); @@ -86,6 +87,7 @@ class BytecodeGenerationTest: public CPPUNIT_NS::TestCase { void testBlockDupPopFieldReturnLocalDot(); void testPushLocalOpt(); + void testPushArgOpt(); void dump(MethodGenerationContext* mgenc); diff --git a/src/vmobjects/VMFrame.h b/src/vmobjects/VMFrame.h index e16bfae6..00ebc79e 100644 --- a/src/vmobjects/VMFrame.h +++ b/src/vmobjects/VMFrame.h @@ -97,6 +97,10 @@ class VMFrame: public VMObject { return load_ptr(context->arguments[index]); } + inline vm_oop_t GetArgumentInCurrentContext(long index) { + return load_ptr(this->arguments[index]); + } + void SetArgument(long, long, vm_oop_t); void PrintStackTrace() const; long ArgumentStackIndex(long index) const;