|
@@ -1091,15 +1091,145 @@ static Value cxx_get_variable(VM& vm, DeprecatedFlyString const& name, Bytecode:
|
|
|
|
|
|
void Compiler::compile_get_variable(Bytecode::Op::GetVariable const& op)
|
|
|
{
|
|
|
- m_assembler.mov(
|
|
|
- Assembler::Operand::Register(ARG1),
|
|
|
- Assembler::Operand::Imm(bit_cast<u64>(&m_bytecode_executable.get_identifier(op.identifier()))));
|
|
|
+ Assembler::Label slow_case;
|
|
|
+
|
|
|
+ // if (!cache.has_value()) goto slow_case;
|
|
|
m_assembler.mov(
|
|
|
Assembler::Operand::Register(ARG2),
|
|
|
Assembler::Operand::Imm(bit_cast<u64>(&m_bytecode_executable.environment_variable_caches[op.cache_index()])));
|
|
|
+
|
|
|
+ // FIXME: Figure out a nicer way to load a single byte. :^)
|
|
|
+ m_assembler.mov(
|
|
|
+ Assembler::Operand::Register(GPR0),
|
|
|
+ Assembler::Operand::Mem64BaseAndOffset(ARG2, Bytecode::EnvironmentVariableCache::has_value_offset()));
|
|
|
+ m_assembler.bitwise_and(
|
|
|
+ Assembler::Operand::Register(GPR0),
|
|
|
+ Assembler::Operand::Imm(0xff));
|
|
|
+
|
|
|
+ m_assembler.jump_if(
|
|
|
+ Assembler::Operand::Register(GPR0),
|
|
|
+ Assembler::Condition::EqualTo,
|
|
|
+ Assembler::Operand::Imm(0),
|
|
|
+ slow_case);
|
|
|
+
|
|
|
+ // auto environment = vm.running_execution_context().lexical_environment;
|
|
|
+ // GPR1 = current lexical environment
|
|
|
+ m_assembler.mov(
|
|
|
+ Assembler::Operand::Register(GPR1),
|
|
|
+ Assembler::Operand::Mem64BaseAndOffset(RUNNING_EXECUTION_CONTEXT_BASE, ExecutionContext::lexical_environment_offset()));
|
|
|
+
|
|
|
+ // for (size_t i = 0; i < cache->hops; ++i)
|
|
|
+ // environment = environment->outer_environment();
|
|
|
+
|
|
|
+ // GPR0 = hops
|
|
|
+ // FIXME: Load 32 bits directly instead of 64 and masking.
|
|
|
+ m_assembler.mov(
|
|
|
+ Assembler::Operand::Register(GPR0),
|
|
|
+ Assembler::Operand::Mem64BaseAndOffset(ARG2, Bytecode::EnvironmentVariableCache::value_offset() + EnvironmentCoordinate::hops_offset()));
|
|
|
+ m_assembler.mov(
|
|
|
+ Assembler::Operand::Register(GPR2),
|
|
|
+ Assembler::Operand::Imm(0xffffffff));
|
|
|
+ m_assembler.bitwise_and(
|
|
|
+ Assembler::Operand::Register(GPR0),
|
|
|
+ Assembler::Operand::Register(GPR2));
|
|
|
+
|
|
|
+ {
|
|
|
+ // while (GPR0--)
|
|
|
+ // GPR1 = GPR1->outer_environment()
|
|
|
+ Assembler::Label loop_start;
|
|
|
+ Assembler::Label loop_end;
|
|
|
+ loop_start.link(m_assembler);
|
|
|
+ m_assembler.jump_if(
|
|
|
+ Assembler::Operand::Register(GPR0),
|
|
|
+ Assembler::Condition::EqualTo,
|
|
|
+ Assembler::Operand::Imm(0),
|
|
|
+ loop_end);
|
|
|
+ m_assembler.sub(
|
|
|
+ Assembler::Operand::Register(GPR0),
|
|
|
+ Assembler::Operand::Imm(1));
|
|
|
+ m_assembler.mov(
|
|
|
+ Assembler::Operand::Register(GPR1),
|
|
|
+ Assembler::Operand::Mem64BaseAndOffset(GPR1, Environment::outer_environment_offset()));
|
|
|
+ m_assembler.jump(loop_start);
|
|
|
+ loop_end.link(m_assembler);
|
|
|
+ }
|
|
|
+
|
|
|
+ // GPR1 now points to the environment holding our binding.
|
|
|
+
|
|
|
+ // if (environment->is_permanently_screwed_by_eval()) goto slow_case;
|
|
|
+ // FIXME: Load 8 bits here directly instead of loading 64 and masking.
|
|
|
+ m_assembler.mov(
|
|
|
+ Assembler::Operand::Register(GPR0),
|
|
|
+ Assembler::Operand::Mem64BaseAndOffset(GPR1, Environment::is_permanently_screwed_by_eval_offset()));
|
|
|
+ m_assembler.bitwise_and(
|
|
|
+ Assembler::Operand::Register(GPR0),
|
|
|
+ Assembler::Operand::Imm(0xff));
|
|
|
+ m_assembler.jump_if(
|
|
|
+ Assembler::Operand::Register(GPR0),
|
|
|
+ Assembler::Condition::NotEqualTo,
|
|
|
+ Assembler::Operand::Imm(0),
|
|
|
+ slow_case);
|
|
|
+
|
|
|
+ // GPR1 = environment->m_bindings.outline_buffer()
|
|
|
+ m_assembler.mov(
|
|
|
+ Assembler::Operand::Register(GPR1),
|
|
|
+ Assembler::Operand::Mem64BaseAndOffset(GPR1, DeclarativeEnvironment::bindings_offset() + Vector<DeclarativeEnvironment::Binding>::outline_buffer_offset()));
|
|
|
+
|
|
|
+ // GPR0 = index
|
|
|
+ // FIXME: Load 32 bits directly instead of 64 and masking.
|
|
|
+ m_assembler.mov(
|
|
|
+ Assembler::Operand::Register(GPR0),
|
|
|
+ Assembler::Operand::Mem64BaseAndOffset(ARG2, Bytecode::EnvironmentVariableCache::value_offset() + EnvironmentCoordinate::index_offset()));
|
|
|
+ m_assembler.mov(
|
|
|
+ Assembler::Operand::Register(GPR2),
|
|
|
+ Assembler::Operand::Imm(0xffffffff));
|
|
|
+ m_assembler.bitwise_and(
|
|
|
+ Assembler::Operand::Register(GPR0),
|
|
|
+ Assembler::Operand::Register(GPR2));
|
|
|
+
|
|
|
+ // GPR0 *= sizeof(DeclarativeEnvironment::Binding)
|
|
|
+ m_assembler.mul32(
|
|
|
+ Assembler::Operand::Register(GPR0),
|
|
|
+ Assembler::Operand::Imm(sizeof(DeclarativeEnvironment::Binding)),
|
|
|
+ slow_case);
|
|
|
+
|
|
|
+ // GPR1 = &binding
|
|
|
+ m_assembler.add(
|
|
|
+ Assembler::Operand::Register(GPR1),
|
|
|
+ Assembler::Operand::Register(GPR0));
|
|
|
+
|
|
|
+ // if (!binding.initialized) goto slow_case;
|
|
|
+ m_assembler.mov(
|
|
|
+ Assembler ::Operand::Register(GPR0),
|
|
|
+ Assembler::Operand::Mem64BaseAndOffset(GPR1, DeclarativeEnvironment::Binding::initialized_offset()));
|
|
|
+ m_assembler.bitwise_and(
|
|
|
+ Assembler::Operand::Register(GPR0),
|
|
|
+ Assembler::Operand::Imm(0xff));
|
|
|
+ m_assembler.jump_if(
|
|
|
+ Assembler::Operand::Register(GPR0),
|
|
|
+ Assembler::Condition::EqualTo,
|
|
|
+ Assembler::Operand::Imm(0),
|
|
|
+ slow_case);
|
|
|
+
|
|
|
+ // accumulator = binding.value;
|
|
|
+ m_assembler.mov(
|
|
|
+ Assembler::Operand::Register(GPR0),
|
|
|
+ Assembler::Operand::Mem64BaseAndOffset(GPR1, DeclarativeEnvironment::Binding::value_offset()));
|
|
|
+
|
|
|
+ store_accumulator(GPR0);
|
|
|
+ Assembler::Label end;
|
|
|
+ m_assembler.jump(end);
|
|
|
+
|
|
|
+ // Slow case: Uncached access. Call C++ helper.
|
|
|
+ slow_case.link(m_assembler);
|
|
|
+ m_assembler.mov(
|
|
|
+ Assembler::Operand::Register(ARG1),
|
|
|
+ Assembler::Operand::Imm(bit_cast<u64>(&m_bytecode_executable.get_identifier(op.identifier()))));
|
|
|
native_call((void*)cxx_get_variable);
|
|
|
store_accumulator(RET);
|
|
|
check_exception();
|
|
|
+
|
|
|
+ end.link(m_assembler);
|
|
|
}
|
|
|
|
|
|
static Value cxx_get_callee_and_this_from_environment(VM& vm, DeprecatedFlyString const& name, u32 cache_index, Bytecode::Register callee_reg, Bytecode::Register this_reg)
|