Example #1
0
    void VM::ExecuteFrame()
    {
        CallInfo *call = &state_->calls_.back();
        Closure *cl = call->func_ ? call->func_->closure_ : nullptr;
        Function *proto = cl ? cl->GetPrototype() : nullptr;
        Value *a = nullptr;
        Value *b = nullptr;

        while (call->instruction_ < call->end_)
        {
            Instruction i = *call->instruction_++;

            switch (Instruction::GetOpCode(i)) {
                case OpType_LoadConst:
                    a = GET_REGISTER_A(i);
                    b = GET_CONST_VALUE(i);
                    *a = *b;
                    SET_NEW_TOP(a);
                    break;
                case OpType_Move:
                    a = GET_REGISTER_A(i);
                    b = GET_REGISTER_B(i);
                    *a = *b;
                    SET_NEW_TOP(a);
                    break;
                case OpType_Call:
                    a = GET_REGISTER_A(i);
                    if (Call(a, i)) return ;
                    break;
                case OpType_SetTop:
                    a = GET_REGISTER_A(i);
                    state_->stack_.SetNewTop(a);
                    break;
                case OpType_GetUpTable:
                    GetUpTable(GET_REGISTER_A(i), GET_UPVALUE_B(i), GET_REGISTER_C(i));
                    break;
            }
        }

        // For bootstrap CallInfo, we use call->register_ as new top
        Value *new_top = call->func_ ? call->func_ : call->register_;
        // Reset top value
        state_->stack_.SetNewTop(new_top);
        // Set expect result
        if (call->expect_result != EXP_VALUE_COUNT_ANY)
            state_->stack_.SetNewTop(new_top + call->expect_result);

        // Pop current CallInfo, and return to last CallInfo
        state_->calls_.pop_back();
    }
Example #2
0
File: VM.cpp Project: Gwill/luna
    void VM::ExecuteFrame()
    {
        CallInfo *call = &state_->calls_.back();
        Closure *cl = call->func_->closure_;
        Function *proto = cl->GetPrototype();
        Value *a = nullptr;
        Value *b = nullptr;
        Value *c = nullptr;

        while (call->instruction_ < call->end_)
        {
            state_->CheckRunGC();
            Instruction i = *call->instruction_++;

            switch (Instruction::GetOpCode(i)) {
                case OpType_LoadNil:
                    a = GET_REGISTER_A(i);
                    GET_REAL_VALUE(a)->SetNil();
                    break;
                case OpType_LoadBool:
                    a = GET_REGISTER_A(i);
                    GET_REAL_VALUE(a)->SetBool(Instruction::GetParamB(i) ? true : false);
                    break;
                case OpType_LoadInt:
                    a = GET_REGISTER_A(i);
                    assert(call->instruction_ < call->end_);
                    a->num_ = (*call->instruction_++).opcode_;
                    a->type_ = ValueT_Number;
                    break;
                case OpType_LoadConst:
                    a = GET_REGISTER_A(i);
                    b = GET_CONST_VALUE(i);
                    *GET_REAL_VALUE(a) = *b;
                    break;
                case OpType_Move:
                    a = GET_REGISTER_A(i);
                    b = GET_REGISTER_B(i);
                    *GET_REAL_VALUE(a) = *GET_REAL_VALUE(b);
                    break;
                case OpType_Call:
                    a = GET_REGISTER_A(i);
                    if (Call(a, i)) return ;
                    break;
                case OpType_GetUpvalue:
                    a = GET_REGISTER_A(i);
                    b = GET_UPVALUE_B(i)->GetValue();
                    *GET_REAL_VALUE(a) = *b;
                    break;
                case OpType_SetUpvalue:
                    a = GET_REGISTER_A(i);
                    b = GET_UPVALUE_B(i)->GetValue();
                    *b = *a;
                    break;
                case OpType_GetGlobal:
                    a = GET_REGISTER_A(i);
                    b = GET_CONST_VALUE(i);
                    *GET_REAL_VALUE(a) = state_->global_.table_->GetValue(*b);
                    break;
                case OpType_SetGlobal:
                    a = GET_REGISTER_A(i);
                    b = GET_CONST_VALUE(i);
                    state_->global_.table_->SetValue(*b, *a);
                    break;
                case OpType_Closure:
                    a = GET_REGISTER_A(i);
                    GenerateClosure(a, i);
                    break;
                case OpType_VarArg:
                    a = GET_REGISTER_A(i);
                    CopyVarArg(a, i);
                    break;
                case OpType_Ret:
                    a = GET_REGISTER_A(i);
                    return Return(a, i);
                case OpType_JmpFalse:
                    a = GET_REGISTER_A(i);
                    if (GET_REAL_VALUE(a)->IsFalse())
                        call->instruction_ += -1 + Instruction::GetParamsBx(i);
                    break;
                case OpType_JmpTrue:
                    a = GET_REGISTER_A(i);
                    if (!GET_REAL_VALUE(a)->IsFalse())
                        call->instruction_ += -1 + Instruction::GetParamsBx(i);
                    break;
                case OpType_JmpNil:
                    a = GET_REGISTER_A(i);
                    if (a->type_ == ValueT_Nil)
                        call->instruction_ += -1 + Instruction::GetParamsBx(i);
                    break;
                case OpType_Jmp:
                    call->instruction_ += -1 + Instruction::GetParamsBx(i);
                    break;
                case OpType_Neg:
                    a = GET_REGISTER_A(i);
                    CheckType(a, ValueT_Number, "neg");
                    a->num_ = -a->num_;
                    break;
                case OpType_Not:
                    a = GET_REGISTER_A(i);
                    a->SetBool(a->IsFalse() ? true : false);
                    break;
                case OpType_Len:
                    a = GET_REGISTER_A(i);
                    if (a->type_ == ValueT_Table)
                        a->num_ = a->table_->ArraySize();
                    else if (a->type_ == ValueT_String)
                        a->num_ = a->str_->GetLength();
                    else
                        ReportTypeError(a, "length of");
                    a->type_ = ValueT_Number;
                    break;
                case OpType_Add:
                    GET_REGISTER_ABC(i);
                    CheckArithType(b, c, "add");
                    a->num_ = b->num_ + c->num_;
                    a->type_ = ValueT_Number;
                    break;
                case OpType_Sub:
                    GET_REGISTER_ABC(i);
                    CheckArithType(b, c, "sub");
                    a->num_ = b->num_ - c->num_;
                    a->type_ = ValueT_Number;
                    break;
                case OpType_Mul:
                    GET_REGISTER_ABC(i);
                    CheckArithType(b, c, "multiply");
                    a->num_ = b->num_ * c->num_;
                    a->type_ = ValueT_Number;
                    break;
                case OpType_Div:
                    GET_REGISTER_ABC(i);
                    CheckArithType(b, c, "div");
                    a->num_ = b->num_ / c->num_;
                    a->type_ = ValueT_Number;
                    break;
                case OpType_Pow:
                    GET_REGISTER_ABC(i);
                    CheckArithType(b, c, "power");
                    a->num_ = pow(b->num_, c->num_);
                    a->type_ = ValueT_Number;
                    break;
                case OpType_Mod:
                    GET_REGISTER_ABC(i);
                    CheckArithType(b, c, "mod");
                    a->num_ = fmod(b->num_, c->num_);
                    a->type_ = ValueT_Number;
                    break;
                case OpType_Concat:
                    GET_REGISTER_ABC(i);
                    Concat(a, b, c);
                    break;
                case OpType_Less:
                    GET_REGISTER_ABC(i);
                    CheckInequalityType(b, c, "compare(<)");
                    if (b->type_ == ValueT_Number)
                        a->SetBool(b->num_ < c->num_);
                    else
                        a->SetBool(*b->str_ < *c->str_);
                    break;
                case OpType_Greater:
                    GET_REGISTER_ABC(i);
                    CheckInequalityType(b, c, "compare(>)");
                    if (b->type_ == ValueT_Number)
                        a->SetBool(b->num_ > c->num_);
                    else
                        a->SetBool(*b->str_ > *c->str_);
                    break;
                case OpType_Equal:
                    GET_REGISTER_ABC(i);
                    a->SetBool(*b == *c);
                    break;
                case OpType_UnEqual:
                    GET_REGISTER_ABC(i);
                    a->SetBool(*b != *c);
                    break;
                case OpType_LessEqual:
                    GET_REGISTER_ABC(i);
                    CheckInequalityType(b, c, "compare(<=)");
                    if (b->type_ == ValueT_Number)
                        a->SetBool(b->num_ <= c->num_);
                    else
                        a->SetBool(*b->str_ <= *c->str_);
                    break;
                case OpType_GreaterEqual:
                    GET_REGISTER_ABC(i);
                    CheckInequalityType(b, c, "compare(>=)");
                    if (b->type_ == ValueT_Number)
                        a->SetBool(b->num_ >= c->num_);
                    else
                        a->SetBool(*b->str_ >= *c->str_);
                    break;
                case OpType_NewTable:
                    a = GET_REGISTER_A(i);
                    a->table_ = state_->NewTable();
                    a->type_ = ValueT_Table;
                    break;
                case OpType_SetTable:
                    GET_REGISTER_ABC(i);
                    CheckTableType(a, b, "set", "to");
                    if (a->type_ == ValueT_Table)
                        a->table_->SetValue(*b, *c);
                    else if (a->type_ == ValueT_UserData)
                        a->user_data_->GetMetatable()->SetValue(*b, *c);
                    else
                        assert(0);
                    break;
                case OpType_GetTable:
                    GET_REGISTER_ABC(i);
                    CheckTableType(a, b, "get", "from");
                    if (a->type_ == ValueT_Table)
                        *c = a->table_->GetValue(*b);
                    else if (a->type_ == ValueT_UserData)
                        *c = a->user_data_->GetMetatable()->GetValue(*b);
                    else
                        assert(0);
                    break;
                case OpType_ForInit:
                    GET_REGISTER_ABC(i);
                    ForInit(a, b, c);
                    break;
                case OpType_ForStep:
                    GET_REGISTER_ABC(i);
                    i = *call->instruction_++;
                    if ((c->num_ > 0.0 && a->num_ > b->num_) ||
                        (c->num_ <= 0.0 && a->num_ < b->num_))
                        call->instruction_ += -1 + Instruction::GetParamsBx(i);
                    break;
                default:
                    break;
            }
        }

        Value *new_top = call->func_;
        // Reset top value
        state_->stack_.SetNewTop(new_top);
        // Set expect results
        if (call->expect_result_ != EXP_VALUE_COUNT_ANY)
            state_->stack_.SetNewTop(new_top + call->expect_result_);

        // Pop current CallInfo, and return to last CallInfo
        state_->calls_.pop_back();
    }