Example #1
0
static VMFnWrap instrAssignStringKey(VMState *state) {
    const auto *instruction = (Instruction::AssignStringKey *)state->m_instr;
    const Slot objectSlot = instruction->m_objectSlot;
    const Slot valueSlot = instruction->m_valueSlot;
    VM_ASSERTION(objectSlot < state->m_cf->m_count, "slot addressing error");
    VM_ASSERTION(valueSlot < state->m_cf->m_count, "slot addressing error");
    Object *object = state->m_cf->m_slots[objectSlot];
    Object *valueObject = state->m_cf->m_slots[valueSlot];
    const char *key = instruction->m_key;
    AssignType assignType = instruction->m_assignType;
    switch (assignType) {
        case kAssignPlain: {
            Object::setNormal(state->m_restState, object, key, valueObject);
            break;
        }
        case kAssignExisting: {
            const char *error = Object::setExisting(state->m_restState, object, key, valueObject);
            VM_ASSERTION(!error, "%s for '%s'", error, key);
            break;
        }
        case kAssignShadowing: {
            bool keySet = false;
            const char *error = Object::setShadowing(state->m_restState, object, key, valueObject, &keySet);
            VM_ASSERTION(!error, "%s for '%s'", error, key);
            VM_ASSERTION(keySet, "key '%s' not found in object", key);
            break;
        }
    }
    state->m_instr = (Instruction *)(instruction + 1);
    return { instrFunctions[state->m_instr->m_type] };
}
Example #2
0
static VMFnWrap instrCloseObject(VMState *state) {
    const auto *instruction = (Instruction::CloseObject *)state->m_instr;
    const Slot slot = instruction->m_slot;
    VM_ASSERTION(slot < state->m_cf->m_count, "slot addressing error");
    Object *object = state->m_cf->m_slots[slot];
    VM_ASSERTION(!(object->m_flags & kClosed), "object is already closed");
    object->m_flags |= kClosed;
    state->m_instr = (Instruction *)(instruction + 1);
    return { instrFunctions[state->m_instr->m_type] };
}
Example #3
0
static VMFnWrap instrCall(VMState *state) {
    const auto *instruction = (Instruction::Call *)state->m_instr;

    const Slot functionSlot = instruction->m_functionSlot;
    const Slot thisSlot = instruction->m_thisSlot;

    const size_t argsLength = instruction->m_count;

    VM_ASSERTION(functionSlot < state->m_cf->m_count, "slot addressing error");
    VM_ASSERTION(thisSlot < state->m_cf->m_count, "slot addressing error");

    Object *thisObject_ = state->m_cf->m_slots[thisSlot];
    Object *functionObject_ = state->m_cf->m_slots[functionSlot];

    Object **arguments = nullptr;
    if (argsLength < 10) {
        arguments = state->m_restState->m_shared->m_valueCache.m_preallocatedArguments[argsLength];
    } else {
        arguments = (Object **)Memory::allocate(sizeof(Object *) * argsLength);
    }

    for (size_t i = 0; i < argsLength; i++) {
        const Slot argumentSlot = instruction->m_arguments[i];
        VM_ASSERTION(argumentSlot < state->m_cf->m_count, "slot addressing error");
        arguments[i] = state->m_cf->m_slots[argumentSlot];
    }

    CallFrame *oldCallFrame = state->m_restState->m_frame;

    // TODO: verify if any callable needs to access cf->m_instr
    state->m_cf->m_instructions = state->m_instr;

    if (!VM::callCallable(state->m_restState, thisObject_, functionObject_, arguments, argsLength)) {
        return { instrHalt };
    }

    if (state->m_restState->m_runState == kErrored) {
        if (argsLength >= 10) {
            Memory::free(arguments);
        }
        return { instrHalt };
    }

    // Step over the call in the old stack frame
    oldCallFrame->m_instructions = (Instruction *)(instruction + 1);

    if (argsLength >= 10) {
        Memory::free(arguments);
    }

    state->m_cf = state->m_restState->m_frame;
    state->m_instr = state->m_cf->m_instructions;

    return { instrFunctions[state->m_instr->m_type] };
}
Example #4
0
static VMFnWrap instrFreeze(VMState *state) {
    const auto *instruction = (Instruction::Freeze *)state->m_instr;
    const Slot slot = instruction->m_slot;

    VM_ASSERTION(slot < state->m_cf->m_count, "slot addressing error");

    Object *object = state->m_cf->m_slots[slot];
    VM_ASSERTION(!(object->m_flags & kImmutable), "object is already frozen");
    object->m_flags |= kImmutable;
    state->m_instr = (Instruction *)(instruction + 1);
    return { instrFunctions[state->m_instr->m_type] };
}
Example #5
0
static VMFnWrap instrNewClosureObject(VMState *state) {
    const auto *instruction = (Instruction::NewClosureObject *)state->m_instr;
    const Slot targetSlot = instruction->m_targetSlot;
    const Slot contextSlot = instruction->m_contextSlot;
    VM_ASSERTION(targetSlot < state->m_cf->m_count, "slot addressing error");
    VM_ASSERTION(contextSlot < state->m_cf->m_count, "slot addressing error");
    Object *context = state->m_cf->m_slots[contextSlot];
    state->m_cf->m_slots[targetSlot] = Object::newClosure(state->m_restState,
                                                          context,
                                                          instruction->m_function);
    state->m_instr = (Instruction *)(instruction + 1);
    return { instrFunctions[state->m_instr->m_type] };
}
Example #6
0
static VMFnWrap instrWriteFastSlot(VMState *state) {
    const auto *instruction = (Instruction::WriteFastSlot *)state->m_instr;

    const Slot targetSlot = instruction->m_targetSlot;
    const Slot sourceSlot = instruction->m_sourceSlot;

    VM_ASSERTION(targetSlot < state->m_cf->m_fastSlotsCount, "fast slot addressing error");
    VM_ASSERTION(sourceSlot < state->m_cf->m_count, "slot addressing error");

    *state->m_cf->m_fastSlots[targetSlot] = state->m_cf->m_slots[sourceSlot];

    state->m_instr = (Instruction *)(instruction + 1);
    return { instrFunctions[state->m_instr->m_type] };
}
Example #7
0
static VMFnWrap instrCall(VMState *state) {
    const auto *instruction = (Instruction::Call *)state->m_instr;

    const Slot functionSlot = instruction->m_functionSlot;
    const Slot thisSlot = instruction->m_thisSlot;

    const size_t argsLength = instruction->m_count;

    VM_ASSERTION(functionSlot < state->m_cf->m_count, "slot addressing error");
    VM_ASSERTION(thisSlot < state->m_cf->m_count, "slot addressing error");

    Object *thisObject_ = state->m_slots[thisSlot];
    Object *functionObject_ = state->m_slots[functionSlot];

    Object **arguments = nullptr;
    if (argsLength < 10) {
        arguments = state->m_restState->m_shared->m_valueCache.m_preallocatedArguments[argsLength];
    } else {
        arguments = (Object **)Memory::allocate(sizeof(Object *) * argsLength);
    }

    for (size_t i = 0; i < argsLength; i++) {
        const Slot argumentSlot = ((Slot *)(instruction + 1))[i];
        VM_ASSERTION(argumentSlot < state->m_cf->m_count, "slot addressing error");
        arguments[i] = state->m_slots[argumentSlot];
    }

    state->m_instr = (Instruction *)((Slot *)(instruction + 1) + instruction->m_count);
    state->m_cf->m_instructions = state->m_instr;

    if (!VM::callCallable(state->m_restState, thisObject_, functionObject_, arguments, argsLength)) {
        return { instrHalt };
    }

    if (state->m_restState->m_runState == kErrored) {
        if (argsLength >= 10) {
            Memory::free(arguments);
        }
        return { instrHalt };
    }

    if (argsLength >= 10) {
        Memory::free(arguments);
    }

    VMState::refresh(state);

    return { instrFunctions[state->m_instr->m_type] };
}
Example #8
0
static VMFnWrap instrNewObject(VMState *state) {
    const auto *instruction = (Instruction::NewObject *)state->m_instr;
    const Slot targetSlot = instruction->m_targetSlot;
    const Slot parentSlot = instruction->m_parentSlot;

    VM_ASSERTION(targetSlot < state->m_cf->m_count, "slot addressing error");
    VM_ASSERTION(parentSlot < state->m_cf->m_count, "slot addressing error");

    Object *parentObject = state->m_cf->m_slots[parentSlot];
    if (parentObject) {
        VM_ASSERTION(!(parentObject->m_flags & kNoInherit), "cannot inherit from this object");
    }
    state->m_cf->m_slots[targetSlot] = Object::newObject(state->m_restState, parentObject);
    state->m_instr = (Instruction *)(instruction + 1);
    return { instrFunctions[state->m_instr->m_type] };
}
Example #9
0
static VMFnWrap instrTestBranch(VMState *state) {
    const auto *instruction = (Instruction::TestBranch *)state->m_instr;

    const Slot testSlot = instruction->m_testSlot;

    const size_t trueBlock = instruction->m_trueBlock;
    const size_t falseBlock = instruction->m_falseBlock;

    VM_ASSERTION(testSlot < state->m_cf->m_count, "slot addressing error");

    Object *testObject = state->m_cf->m_slots[testSlot];

    Object *boolBase = state->m_restState->m_shared->m_valueCache.m_boolBase;
    Object *intBase = state->m_restState->m_shared->m_valueCache.m_intBase;
    Object *boolObject = Object::instanceOf(testObject, boolBase);
    Object *intObject = Object::instanceOf(testObject, intBase);

    bool test = false;
    if (boolObject) {
        if (((BoolObject *)boolObject)->m_value) {
            test = true;
        }
    } else if (intObject) {
        if (((IntObject *)intObject)->m_value != 0) {
            test = true;
        }
    } else {
        test = !!testObject;
    }

    const size_t targetBlock = test ? trueBlock : falseBlock;
    state->m_instr = (Instruction *)((unsigned char *)state->m_cf->m_function->m_body.m_instructions
        + state->m_cf->m_function->m_body.m_blocks[targetBlock].m_offset);
    return { instrFunctions[state->m_instr->m_type] };
}
Example #10
0
static VMFnWrap instrSetConstraintStringKey(VMState *state) {
    const auto *instruction = (Instruction::SetConstraintStringKey *)state->m_instr;
    const Slot objectSlot = instruction->m_objectSlot;
    const Slot constraintSlot = instruction->m_constraintSlot;
    VM_ASSERTION(objectSlot < state->m_cf->m_count, "slot addressing error");
    VM_ASSERTION(constraintSlot < state->m_cf->m_count, "slot addressing error");
    Object *object = state->m_cf->m_slots[objectSlot];
    Object *constraint = state->m_cf->m_slots[constraintSlot];
    const char *error = Object::setConstraint(state->m_restState,
                                              object,
                                              instruction->m_key,
                                              instruction->m_keyLength,
                                              constraint);
    VM_ASSERTION(!error, error);
    state->m_instr = (Instruction *)(instruction + 1);
    return { instrFunctions[state->m_instr->m_type] };
}
Example #11
0
static VMFnWrap instrBranch(VMState *state) {
    const auto *instruction = (Instruction::Branch *)state->m_instr;
    const size_t block = instruction->m_block;
    VM_ASSERTION(block < state->m_cf->m_function->m_body.m_count, "block addressing error");
    state->m_instr = (Instruction *)((unsigned char *)state->m_cf->m_function->m_body.m_instructions
        + state->m_cf->m_function->m_body.m_blocks[block].m_offset);
    return { instrFunctions[state->m_instr->m_type] };
}
Example #12
0
static VMFnWrap instrAccessStringKey(VMState *state) {
    const auto *instruction = (Instruction::AccessStringKey *)state->m_instr;

    const Slot objectSlot = instruction->m_objectSlot;
    const Slot targetSlot = instruction->m_targetSlot;

    VM_ASSERTION(objectSlot < state->m_cf->m_count, "slot addressing error");
    VM_ASSERTION(targetSlot < state->m_cf->m_count, "slot addressing error");

    Object *object = state->m_cf->m_slots[objectSlot];

    const char *key = instruction->m_key;
    bool objectFound = false;

    state->m_cf->m_slots[targetSlot] = Object::lookup(object, key, &objectFound);

    if (!objectFound) {
        Object *indexOperation = Object::lookup(object, "[]", nullptr);
        if (indexOperation) {
            Object *keyObject = Object::newString(state->m_restState, instruction->m_key, strlen(instruction->m_key));

            State subState = { };
            subState.m_parent = state->m_restState;
            subState.m_root = state->m_root;
            subState.m_shared = state->m_restState->m_shared;

            if (!VM::callCallable(&subState, object, indexOperation, &keyObject, 1)) {
                return { instrHalt };
            }

            VM::run(&subState);

            VM_ASSERTION(subState.m_runState != kErrored, "[] overload failed: %s\n",
                subState.m_error.c_str());

            state->m_cf->m_slots[targetSlot] = subState.m_resultValue;

            objectFound = true;
        }
    }
    if (!objectFound) {
        VM_ASSERTION(false, "property not found: '%s'", key);
    }
    state->m_instr = (Instruction *)(instruction + 1);
    return { instrFunctions[state->m_instr->m_type] };
}
Example #13
0
static VMFnWrap instrSaveResult(VMState *state) {
    const auto *instruction = (Instruction::SaveResult *)state->m_instr;
    const Slot saveSlot = instruction->m_targetSlot;
    VM_ASSERTION(saveSlot < state->m_cf->m_count, "slot addressing error");
    state->m_cf->m_slots[saveSlot] = state->m_restState->m_resultValue;
    state->m_restState->m_resultValue = nullptr;
    state->m_instr = (Instruction *)(instruction + 1);
    return { instrFunctions[state->m_instr->m_type] };
}
Example #14
0
static VMFnWrap instrAssign(VMState *state) {
    const auto *instruction = (Instruction::Assign *)state->m_instr;

    const Slot objectSlot = instruction->m_objectSlot;
    const Slot valueSlot = instruction->m_valueSlot;
    const Slot keySlot = instruction->m_keySlot;

    VM_ASSERTION(objectSlot < state->m_cf->m_count, "slot addressing error");
    VM_ASSERTION(valueSlot < state->m_cf->m_count, "slot addressing error");
    VM_ASSERTION(keySlot < state->m_cf->m_count, "slot addressing error");
    VM_ASSERTION(state->m_cf->m_slots[keySlot], "null key slot");

    Object *object = state->m_cf->m_slots[objectSlot];
    Object *valueObject = state->m_cf->m_slots[valueSlot];
    Object *stringBase = state->m_restState->m_shared->m_valueCache.m_stringBase;
    Object *keyObject = state->m_cf->m_slots[keySlot];
    StringObject *stringKey = (StringObject *)Object::instanceOf(keyObject, stringBase);
    if (!stringKey) {
        Object *indexAssignOperation = Object::lookup(object, "[]=", nullptr);
        if (indexAssignOperation) {
            Object *keyValuePair[] = { state->m_cf->m_slots[instruction->m_keySlot], valueObject };
            if (!VM::callCallable(state->m_restState, object, indexAssignOperation, keyValuePair, 2)) {
                return { instrHalt };
            }
            state->m_instr = (Instruction *)(instruction + 1);
            return { instrFunctions[state->m_instr->m_type] };
        }
        VM_ASSERTION(false, "key is not string");
    }

    char *key = stringKey->m_value;
    GC::addPermanent(state->m_restState, keyObject);
    const AssignType assignType = instruction->m_assignType;
    switch (assignType) {
        case kAssignPlain: {
            Object::setNormal(state->m_restState, object, key, valueObject);
            break;
        }
        case kAssignExisting: {
            const char *error = Object::setExisting(state->m_restState, object, key, valueObject);
            VM_ASSERTION(!error, "%s for '%s'", error, key);
            break;
        }
        case kAssignShadowing: {
            bool keySet = false;
            const char *error = Object::setShadowing(state->m_restState, object, key, valueObject, &keySet);
            VM_ASSERTION(!error, "%s for '%s'", error, key);
            VM_ASSERTION(keySet, "key '%s' not found in object", key);
            break;
        }
    }
    state->m_instr = (Instruction *)(instruction + 1);
    return { instrFunctions[state->m_instr->m_type] };
}
Example #15
0
static VMFnWrap instrDefineFastSlot(VMState *state) {
    const auto *instruction = (Instruction::DefineFastSlot *)state->m_instr;

    const Slot targetSlot = instruction->m_targetSlot;
    const Slot objectSlot = instruction->m_objectSlot;

    VM_ASSERTION(objectSlot < state->m_cf->m_count, "slot addressing error");

    Object *object = state->m_cf->m_slots[objectSlot];
    Object **target = Object::lookupReferenceWithHash(object,
                                                      instruction->m_key,
                                                      instruction->m_keyLength,
                                                      instruction->m_keyHash);

    VM_ASSERTION(target, "key not in object");

    state->m_cf->m_fastSlots[targetSlot] = target;
    state->m_instr = (Instruction *)(instruction + 1);
    return { instrFunctions[state->m_instr->m_type] };
}
Example #16
0
static VMFnWrap instrNewArrayObject(VMState *state) {
    const auto *instruction = (Instruction::NewArrayObject *)state->m_instr;
    const Slot targetSlot = instruction->m_targetSlot;
    VM_ASSERTION(targetSlot < state->m_cf->m_count, "slot addressing error");
    auto *array = Object::newArray(state->m_restState,
                                   nullptr,
                                   (IntObject *)state->m_restState->m_shared->m_valueCache.m_intZero);
    state->m_cf->m_slots[targetSlot] = array;
    state->m_instr = (Instruction *)(instruction + 1);
    return { instrFunctions[state->m_instr->m_type] };
}
Example #17
0
static VMFnWrap instrSetConstraint(VMState *state) {
    const auto *instruction = (Instruction::SetConstraint *)state->m_instr;
    const Slot keySlot = instruction->m_keySlot;
    const Slot objectSlot = instruction->m_objectSlot;
    const Slot constraintSlot = instruction->m_constraintSlot;
    VM_ASSERTION(keySlot < state->m_cf->m_count, "slot addressing error");
    VM_ASSERTION(objectSlot < state->m_cf->m_count, "slot addressing error");
    VM_ASSERTION(constraintSlot < state->m_cf->m_count, "slot addressing error");
    Object *object = state->m_cf->m_slots[objectSlot];
    Object *constraint = state->m_cf->m_slots[constraintSlot];
    Object *stringBase = state->m_restState->m_shared->m_valueCache.m_stringBase;
    Object *keyObject = state->m_cf->m_slots[keySlot];
    StringObject *stringKey = (StringObject *)Object::instanceOf(keyObject, stringBase);
    VM_ASSERTION(stringKey, "internal error");
    const char *key = stringKey->m_value;
    const char *error = Object::setConstraint(state->m_restState, object, key, strlen(key), constraint);
    VM_ASSERTION(!error, "failed setting type constraint: %s", error);
    state->m_instr = (Instruction *)(instruction + 1);
    return { instrFunctions[state->m_instr->m_type] };
}
Example #18
0
static VMFnWrap instrNewStringObject(VMState *state) {
    auto *instruction = (Instruction::NewStringObject *)state->m_instr;
    const Slot targetSlot = instruction->m_targetSlot;
    const char *value = instruction->m_value;
    VM_ASSERTION(targetSlot < state->m_cf->m_count, "slot addressing error");
    if (U_UNLIKELY(!instruction->m_stringObject)) {
        Object *object = Object::newString(state->m_restState, value, strlen(value));
        instruction->m_stringObject = object;
        GC::addPermanent(state->m_restState, object);
    }
    state->m_cf->m_slots[targetSlot] = instruction->m_stringObject;
    state->m_instr = (Instruction *)(instruction + 1);
    return { instrFunctions[state->m_instr->m_type] };
}
Example #19
0
static VMFnWrap instrReturn(VMState *state) {
    const auto *instruction = (Instruction::Return *)state->m_instr;
    const Slot returnSlot = instruction->m_returnSlot;
    VM_ASSERTION(returnSlot < state->m_cf->m_count, "slot addressing error");
    Object *result = state->m_cf->m_slots[returnSlot];
    GC::delRoots(state->m_restState, &state->m_cf->m_root);
    VM::delFrame(state->m_restState);
    state->m_restState->m_resultValue = result;

    if (!state->m_restState->m_frame) {
        return { instrHalt };
    }

    state->m_cf = state->m_restState->m_frame;
    state->m_instr = state->m_cf->m_instructions;
    return { instrFunctions[state->m_instr->m_type] };
}
Example #20
0
static VMFnWrap instrAccess(VMState *state) {
    const auto *instruction = (Instruction::Access *)state->m_instr;

    const Slot objectSlot = instruction->m_objectSlot;
    const Slot targetSlot = instruction->m_targetSlot;

    const Slot keySlot = instruction->m_keySlot;

    VM_ASSERTION(objectSlot < state->m_cf->m_count, "slot addressing error");
    VM_ASSERTION(targetSlot < state->m_cf->m_count, "slot addressing error");
    VM_ASSERTION(keySlot < state->m_cf->m_count, "slot addressing error");
    VM_ASSERTION(state->m_cf->m_slots[keySlot], "null key slot");

    char *key = nullptr;
    bool hasKey = false;

    Object *object = state->m_cf->m_slots[objectSlot];

    Object *stringBase = state->m_restState->m_shared->m_valueCache.m_stringBase;
    Object *keyObject = state->m_cf->m_slots[keySlot];

    auto *stringKey = (StringObject *)Object::instanceOf(keyObject, stringBase);

    bool objectFound = false;

    if (stringKey) {
        GC::addPermanent(state->m_restState, keyObject);
        key = stringKey->m_value;
        state->m_cf->m_slots[targetSlot] = Object::lookup(object, key, &objectFound);
    }
    if (!objectFound) {
        Object *indexOperation = Object::lookup(object, "[]", nullptr);
        if (indexOperation) {
            Object *keyObject = state->m_cf->m_slots[keySlot];

            State subState = { };
            subState.m_parent = state->m_restState;
            subState.m_root = state->m_root;
            subState.m_shared = state->m_restState->m_shared;

            if (!VM::callCallable(&subState, object, indexOperation, &keyObject, 1)) {
                return { instrHalt };
            }

            VM::run(&subState);

            VM_ASSERTION(subState.m_runState != kErrored, "[] overload failed: %s\n",
                subState.m_error.c_str());

            state->m_cf->m_slots[targetSlot] = subState.m_resultValue;

            objectFound = true;
        }
    }
    if (!objectFound) {
        if (hasKey) {
            VM_ASSERTION(false, "property not found: '%s'", key);
        } else {
            VM_ASSERTION(false, "property not found");
        }
    }
    state->m_instr = (Instruction *)(instruction + 1);
    return { instrFunctions[state->m_instr->m_type] };
}