Cleanup of contexts in the full code generator.

Review URL: http://codereview.chromium.org/3449004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5511 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
erik.corry@gmail.com 2010-09-23 09:22:45 +00:00
parent 06c867404b
commit 94cf27373c
10 changed files with 1759 additions and 1743 deletions

File diff suppressed because it is too large Load Diff

View File

@ -172,18 +172,6 @@ class Statement: public AstNode {
class Expression: public AstNode {
public:
enum Context {
// Not assigned a context yet, or else will not be visited during
// code generation.
kUninitialized,
// Evaluated for its side effects.
kEffect,
// Evaluated for its value (and side effects).
kValue,
// Evaluated for control flow (and side effects).
kTest
};
Expression() : bitfields_(0) {}
virtual Expression* AsExpression() { return this; }

View File

@ -332,30 +332,93 @@ bool FullCodeGenerator::ShouldInlineSmiCase(Token::Value op) {
}
void FullCodeGenerator::PrepareTest(Label* materialize_true,
void FullCodeGenerator::EffectContext::Plug(Register reg) const {
}
void FullCodeGenerator::AccumulatorValueContext::Plug(Register reg) const {
// Move value into place.
__ Move(result_register(), reg);
}
void FullCodeGenerator::StackValueContext::Plug(Register reg) const {
// Move value into place.
__ push(reg);
}
void FullCodeGenerator::TestContext::Plug(Register reg) const {
// For simplicity we always test the accumulator register.
__ Move(result_register(), reg);
codegen()->DoTest(true_label_, false_label_, fall_through_);
}
void FullCodeGenerator::EffectContext::PlugTOS() const {
__ Drop(1);
}
void FullCodeGenerator::AccumulatorValueContext::PlugTOS() const {
__ pop(result_register());
}
void FullCodeGenerator::StackValueContext::PlugTOS() const {
}
void FullCodeGenerator::TestContext::PlugTOS() const {
// For simplicity we always test the accumulator register.
__ pop(result_register());
codegen()->DoTest(true_label_, false_label_, fall_through_);
}
void FullCodeGenerator::EffectContext::PrepareTest(
Label* materialize_true,
Label* materialize_false,
Label** if_true,
Label** if_false,
Label** fall_through) {
switch (context_) {
case Expression::kUninitialized:
UNREACHABLE();
break;
case Expression::kEffect:
Label** fall_through) const {
// In an effect context, the true and the false case branch to the
// same label.
*if_true = *if_false = *fall_through = materialize_true;
break;
case Expression::kValue:
}
void FullCodeGenerator::AccumulatorValueContext::PrepareTest(
Label* materialize_true,
Label* materialize_false,
Label** if_true,
Label** if_false,
Label** fall_through) const {
*if_true = *fall_through = materialize_true;
*if_false = materialize_false;
break;
case Expression::kTest:
}
void FullCodeGenerator::StackValueContext::PrepareTest(
Label* materialize_true,
Label* materialize_false,
Label** if_true,
Label** if_false,
Label** fall_through) const {
*if_true = *fall_through = materialize_true;
*if_false = materialize_false;
}
void FullCodeGenerator::TestContext::PrepareTest(
Label* materialize_true,
Label* materialize_false,
Label** if_true,
Label** if_false,
Label** fall_through) const {
*if_true = true_label_;
*if_false = false_label_;
*fall_through = fall_through_;
break;
}
}
@ -576,20 +639,20 @@ void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
// Load only the operands that we need to materialize.
if (constant == kNoConstants) {
VisitForValue(left, kStack);
VisitForValue(right, kAccumulator);
VisitForStackValue(left);
VisitForAccumulatorValue(right);
} else if (constant == kRightConstant) {
VisitForValue(left, kAccumulator);
VisitForAccumulatorValue(left);
} else {
ASSERT(constant == kLeftConstant);
VisitForValue(right, kAccumulator);
VisitForAccumulatorValue(right);
}
SetSourcePosition(expr->position());
if (ShouldInlineSmiCase(op)) {
EmitInlineSmiBinaryOp(expr, op, context_, mode, left, right, constant);
EmitInlineSmiBinaryOp(expr, op, mode, left, right, constant);
} else {
EmitBinaryOp(op, context_, mode);
EmitBinaryOp(op, mode);
}
break;
}
@ -603,39 +666,7 @@ void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
void FullCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) {
Label eval_right, done;
// Set up the appropriate context for the left subexpression based
// on the operation and our own context. Initially assume we can
// inherit both true and false labels from our context.
if (expr->op() == Token::OR) {
switch (context_) {
case Expression::kUninitialized:
UNREACHABLE();
case Expression::kEffect:
VisitForControl(expr->left(), &done, &eval_right, &eval_right);
break;
case Expression::kValue:
VisitLogicalForValue(expr->left(), expr->op(), location_, &done);
break;
case Expression::kTest:
VisitForControl(expr->left(), true_label_, &eval_right, &eval_right);
break;
}
} else {
ASSERT_EQ(Token::AND, expr->op());
switch (context_) {
case Expression::kUninitialized:
UNREACHABLE();
case Expression::kEffect:
VisitForControl(expr->left(), &eval_right, &done, &eval_right);
break;
case Expression::kValue:
VisitLogicalForValue(expr->left(), expr->op(), location_, &done);
break;
case Expression::kTest:
VisitForControl(expr->left(), &eval_right, false_label_, &eval_right);
break;
}
}
context()->EmitLogicalLeft(expr, &eval_right, &done);
__ bind(&eval_right);
Visit(expr->right());
@ -644,43 +675,75 @@ void FullCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) {
}
void FullCodeGenerator::VisitLogicalForValue(Expression* expr,
Token::Value op,
Location where,
Label* done) {
ASSERT(op == Token::AND || op == Token::OR);
VisitForValue(expr, kAccumulator);
__ push(result_register());
Label discard;
switch (where) {
case kAccumulator: {
Label restore;
if (op == Token::OR) {
DoTest(&restore, &discard, &restore);
void FullCodeGenerator::EffectContext::EmitLogicalLeft(BinaryOperation* expr,
Label* eval_right,
Label* done) const {
if (expr->op() == Token::OR) {
codegen()->VisitForControl(expr->left(), done, eval_right, eval_right);
} else {
DoTest(&discard, &restore, &restore);
ASSERT(expr->op() == Token::AND);
codegen()->VisitForControl(expr->left(), eval_right, done, eval_right);
}
}
void FullCodeGenerator::AccumulatorValueContext::EmitLogicalLeft(
BinaryOperation* expr,
Label* eval_right,
Label* done) const {
codegen()->Visit(expr->left());
// We want the value in the accumulator for the test, and on the stack in case
// we need it.
__ push(result_register());
Label discard, restore;
if (expr->op() == Token::OR) {
codegen()->DoTest(&restore, &discard, &restore);
} else {
ASSERT(expr->op() == Token::AND);
codegen()->DoTest(&discard, &restore, &restore);
}
__ bind(&restore);
__ pop(result_register());
__ jmp(done);
break;
}
case kStack: {
if (op == Token::OR) {
DoTest(done, &discard, &discard);
} else {
DoTest(&discard, done, &discard);
}
break;
}
}
__ bind(&discard);
__ Drop(1);
}
void FullCodeGenerator::StackValueContext::EmitLogicalLeft(
BinaryOperation* expr,
Label* eval_right,
Label* done) const {
codegen()->VisitForAccumulatorValue(expr->left());
// We want the value in the accumulator for the test, and on the stack in case
// we need it.
__ push(result_register());
Label discard;
if (expr->op() == Token::OR) {
codegen()->DoTest(done, &discard, &discard);
} else {
ASSERT(expr->op() == Token::AND);
codegen()->DoTest(&discard, done, &discard);
}
__ bind(&discard);
__ Drop(1);
}
void FullCodeGenerator::TestContext::EmitLogicalLeft(BinaryOperation* expr,
Label* eval_right,
Label* done) const {
if (expr->op() == Token::OR) {
codegen()->VisitForControl(expr->left(),
true_label_, eval_right, eval_right);
} else {
ASSERT(expr->op() == Token::AND);
codegen()->VisitForControl(expr->left(),
eval_right, false_label_, eval_right);
}
}
void FullCodeGenerator::VisitBlock(Block* stmt) {
Comment cmnt(masm_, "[ Block");
Breakable nested_statement(this, stmt);
@ -761,7 +824,7 @@ void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
Comment cmnt(masm_, "[ ReturnStatement");
SetStatementPosition(stmt);
Expression* expr = stmt->expression();
VisitForValue(expr, kAccumulator);
VisitForAccumulatorValue(expr);
// Exit all nested statements.
NestedStatement* current = nesting_stack_;
@ -780,7 +843,7 @@ void FullCodeGenerator::VisitWithEnterStatement(WithEnterStatement* stmt) {
Comment cmnt(masm_, "[ WithEnterStatement");
SetStatementPosition(stmt);
VisitForValue(stmt->expression(), kStack);
VisitForStackValue(stmt->expression());
if (stmt->is_catch_block()) {
__ CallRuntime(Runtime::kPushCatchContext, 1);
} else {
@ -1061,7 +1124,7 @@ void FullCodeGenerator::VisitConditional(Conditional* expr) {
expr->then_expression_position());
Visit(expr->then_expression());
// If control flow falls through Visit, jump to done.
if (context_ == Expression::kEffect || context_ == Expression::kValue) {
if (!context()->IsTest()) {
__ jmp(&done);
}
@ -1070,7 +1133,7 @@ void FullCodeGenerator::VisitConditional(Conditional* expr) {
expr->else_expression_position());
Visit(expr->else_expression());
// If control flow falls through Visit, merge it with true case here.
if (context_ == Expression::kEffect || context_ == Expression::kValue) {
if (!context()->IsTest()) {
__ bind(&done);
}
}
@ -1084,7 +1147,7 @@ void FullCodeGenerator::VisitSlot(Slot* expr) {
void FullCodeGenerator::VisitLiteral(Literal* expr) {
Comment cmnt(masm_, "[ Literal");
Apply(context_, expr);
context()->Plug(expr->handle());
}
@ -1110,17 +1173,17 @@ void FullCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) {
// Call runtime routine to allocate the catch extension object and
// assign the exception value to the catch variable.
Comment cmnt(masm_, "[ CatchExtensionObject");
VisitForValue(expr->key(), kStack);
VisitForValue(expr->value(), kStack);
VisitForStackValue(expr->key());
VisitForStackValue(expr->value());
// Create catch extension object.
__ CallRuntime(Runtime::kCreateCatchExtensionObject, 2);
Apply(context_, result_register());
context()->Plug(result_register());
}
void FullCodeGenerator::VisitThrow(Throw* expr) {
Comment cmnt(masm_, "[ Throw");
VisitForValue(expr->exception(), kStack);
VisitForStackValue(expr->exception());
__ CallRuntime(Runtime::kThrow, 1);
// Never returns here.
}
@ -1150,9 +1213,9 @@ int FullCodeGenerator::TryCatch::Exit(int stack_depth) {
void FullCodeGenerator::EmitRegExpCloneResult(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
VisitForValue(args->at(0), kStack);
VisitForStackValue(args->at(0));
__ CallRuntime(Runtime::kRegExpCloneResult, 1);
Apply(context_, result_register());
context()->Plug(result_register());
}
#undef __

View File

@ -71,10 +71,7 @@ class FullCodeGenerator: public AstVisitor {
info_(NULL),
nesting_stack_(NULL),
loop_depth_(0),
location_(kStack),
true_label_(NULL),
false_label_(NULL),
fall_through_(NULL) {
context_(NULL) {
}
static Handle<Code> MakeCode(CompilationInfo* info);
@ -232,11 +229,6 @@ class FullCodeGenerator: public AstVisitor {
DISALLOW_COPY_AND_ASSIGN(ForIn);
};
enum Location {
kAccumulator,
kStack
};
enum ConstantOperand {
kNoConstants,
kLeftConstant,
@ -262,39 +254,6 @@ class FullCodeGenerator: public AstVisitor {
Expression* left,
Expression* right);
// Emit code to convert a pure value (in a register, slot, as a literal,
// or on top of the stack) into the result expected according to an
// expression context.
void Apply(Expression::Context context, Register reg);
// Slot cannot have type Slot::LOOKUP.
void Apply(Expression::Context context, Slot* slot);
void Apply(Expression::Context context, Literal* lit);
void ApplyTOS(Expression::Context context);
// Emit code to discard count elements from the top of stack, then convert
// a pure value into the result expected according to an expression
// context.
void DropAndApply(int count, Expression::Context context, Register reg);
// Set up branch labels for a test expression.
void PrepareTest(Label* materialize_true,
Label* materialize_false,
Label** if_true,
Label** if_false,
Label** fall_through);
// Emit code to convert pure control flow to a pair of labels into the
// result expected according to an expression context.
void Apply(Expression::Context context,
Label* materialize_true,
Label* materialize_false);
// Emit code to convert constant control flow (true or false) into
// the result expected according to an expression context.
void Apply(Expression::Context context, bool flag);
// Helper function to convert a pure value into a test context. The value
// is expected on the stack or the accumulator, depending on the platform.
// See the platform-specific implementation for details.
@ -316,39 +275,26 @@ class FullCodeGenerator: public AstVisitor {
MemOperand EmitSlotSearch(Slot* slot, Register scratch);
void VisitForEffect(Expression* expr) {
Expression::Context saved_context = context_;
context_ = Expression::kEffect;
EffectContext context(this);
Visit(expr);
context_ = saved_context;
}
void VisitForValue(Expression* expr, Location where) {
Expression::Context saved_context = context_;
Location saved_location = location_;
context_ = Expression::kValue;
location_ = where;
void VisitForAccumulatorValue(Expression* expr) {
AccumulatorValueContext context(this);
Visit(expr);
}
void VisitForStackValue(Expression* expr) {
StackValueContext context(this);
Visit(expr);
context_ = saved_context;
location_ = saved_location;
}
void VisitForControl(Expression* expr,
Label* if_true,
Label* if_false,
Label* fall_through) {
Expression::Context saved_context = context_;
Label* saved_true = true_label_;
Label* saved_false = false_label_;
Label* saved_fall_through = fall_through_;
context_ = Expression::kTest;
true_label_ = if_true;
false_label_ = if_false;
fall_through_ = fall_through;
TestContext context(this, if_true, if_false, fall_through);
Visit(expr);
context_ = saved_context;
true_label_ = saved_true;
false_label_ = saved_false;
fall_through_ = saved_fall_through;
}
void VisitDeclarations(ZoneList<Declaration*>* declarations);
@ -398,7 +344,7 @@ class FullCodeGenerator: public AstVisitor {
TypeofState typeof_state,
Label* slow,
Label* done);
void EmitVariableLoad(Variable* expr, Expression::Context context);
void EmitVariableLoad(Variable* expr);
// Platform-specific support for allocating a new closure based on
// the given function info.
@ -417,14 +363,12 @@ class FullCodeGenerator: public AstVisitor {
// Apply the compound assignment operator. Expects the left operand on top
// of the stack and the right one in the accumulator.
void EmitBinaryOp(Token::Value op,
Expression::Context context,
OverwriteMode mode);
// Helper functions for generating inlined smi code for certain
// binary operations.
void EmitInlineSmiBinaryOp(Expression* expr,
Token::Value op,
Expression::Context context,
OverwriteMode mode,
Expression* left,
Expression* right,
@ -432,31 +376,26 @@ class FullCodeGenerator: public AstVisitor {
void EmitConstantSmiBinaryOp(Expression* expr,
Token::Value op,
Expression::Context context,
OverwriteMode mode,
bool left_is_constant_smi,
Smi* value);
void EmitConstantSmiBitOp(Expression* expr,
Token::Value op,
Expression::Context context,
OverwriteMode mode,
Smi* value);
void EmitConstantSmiShiftOp(Expression* expr,
Token::Value op,
Expression::Context context,
OverwriteMode mode,
Smi* value);
void EmitConstantSmiAdd(Expression* expr,
Expression::Context context,
OverwriteMode mode,
bool left_is_constant_smi,
Smi* value);
void EmitConstantSmiSub(Expression* expr,
Expression::Context context,
OverwriteMode mode,
bool left_is_constant_smi,
Smi* value);
@ -468,8 +407,7 @@ class FullCodeGenerator: public AstVisitor {
// Complete a variable assignment. The right-hand-side value is expected
// in the accumulator.
void EmitVariableAssignment(Variable* var,
Token::Value op,
Expression::Context context);
Token::Value op);
// Complete a named property assignment. The receiver is expected on top
// of the stack and the right-hand-side value in the accumulator.
@ -501,6 +439,10 @@ class FullCodeGenerator: public AstVisitor {
MacroAssembler* masm() { return masm_; }
class ExpressionContext;
const ExpressionContext* context() { return context_; }
void set_new_context(const ExpressionContext* context) { context_ = context; }
Handle<Script> script() { return info_->script(); }
bool is_eval() { return info_->is_eval(); }
FunctionLiteral* function() { return info_->function(); }
@ -530,13 +472,7 @@ class FullCodeGenerator: public AstVisitor {
// Handles the shortcutted logical binary operations in VisitBinaryOperation.
void EmitLogicalOperation(BinaryOperation* expr);
void VisitForTypeofValue(Expression* expr, Location where);
void VisitLogicalForValue(Expression* expr,
Token::Value op,
Location where,
Label* done);
void VisitForTypeofValue(Expression* expr);
MacroAssembler* masm_;
CompilationInfo* info_;
@ -545,11 +481,178 @@ class FullCodeGenerator: public AstVisitor {
NestedStatement* nesting_stack_;
int loop_depth_;
Expression::Context context_;
Location location_;
class ExpressionContext {
public:
explicit ExpressionContext(FullCodeGenerator* codegen)
: masm_(codegen->masm()), old_(codegen->context()), codegen_(codegen) {
codegen->set_new_context(this);
}
virtual ~ExpressionContext() {
codegen_->set_new_context(old_);
}
// Convert constant control flow (true or false) to the result expected for
// this expression context.
virtual void Plug(bool flag) const = 0;
// Emit code to convert a pure value (in a register, slot, as a literal,
// or on top of the stack) into the result expected according to this
// expression context.
virtual void Plug(Register reg) const = 0;
virtual void Plug(Slot* slot) const = 0;
virtual void Plug(Handle<Object> lit) const = 0;
virtual void Plug(Heap::RootListIndex index) const = 0;
virtual void PlugTOS() const = 0;
// Emit code to convert pure control flow to a pair of unbound labels into
// the result expected according to this expression context. The
// implementation may decide to bind either of the labels.
virtual void Plug(Label* materialize_true,
Label* materialize_false) const = 0;
// Emit code to discard count elements from the top of stack, then convert
// a pure value into the result expected according to this expression
// context.
virtual void DropAndPlug(int count, Register reg) const = 0;
// For shortcutting operations || and &&.
virtual void EmitLogicalLeft(BinaryOperation* expr,
Label* eval_right,
Label* done) const = 0;
// Set up branch labels for a test expression. The three Label** parameters
// are output parameters.
virtual void PrepareTest(Label* materialize_true,
Label* materialize_false,
Label** if_true,
Label** if_false,
Label** fall_through) const = 0;
// Returns true if we are evaluating only for side effects (ie if the result
// will be discarded.
virtual bool IsEffect() const { return false; }
// Returns true if we are branching on the value rather than materializing
// it.
virtual bool IsTest() const { return false; }
protected:
FullCodeGenerator* codegen() const { return codegen_; }
MacroAssembler* masm() const { return masm_; }
MacroAssembler* masm_;
private:
const ExpressionContext* old_;
FullCodeGenerator* codegen_;
};
class AccumulatorValueContext : public ExpressionContext {
public:
explicit AccumulatorValueContext(FullCodeGenerator* codegen)
: ExpressionContext(codegen) { }
virtual void Plug(bool flag) const;
virtual void Plug(Register reg) const;
virtual void Plug(Label* materialize_true, Label* materialize_false) const;
virtual void Plug(Slot* slot) const;
virtual void Plug(Handle<Object> lit) const;
virtual void Plug(Heap::RootListIndex) const;
virtual void PlugTOS() const;
virtual void DropAndPlug(int count, Register reg) const;
virtual void EmitLogicalLeft(BinaryOperation* expr,
Label* eval_right,
Label* done) const;
virtual void PrepareTest(Label* materialize_true,
Label* materialize_false,
Label** if_true,
Label** if_false,
Label** fall_through) const;
};
class StackValueContext : public ExpressionContext {
public:
explicit StackValueContext(FullCodeGenerator* codegen)
: ExpressionContext(codegen) { }
virtual void Plug(bool flag) const;
virtual void Plug(Register reg) const;
virtual void Plug(Label* materialize_true, Label* materialize_false) const;
virtual void Plug(Slot* slot) const;
virtual void Plug(Handle<Object> lit) const;
virtual void Plug(Heap::RootListIndex) const;
virtual void PlugTOS() const;
virtual void DropAndPlug(int count, Register reg) const;
virtual void EmitLogicalLeft(BinaryOperation* expr,
Label* eval_right,
Label* done) const;
virtual void PrepareTest(Label* materialize_true,
Label* materialize_false,
Label** if_true,
Label** if_false,
Label** fall_through) const;
};
class TestContext : public ExpressionContext {
public:
explicit TestContext(FullCodeGenerator* codegen,
Label* true_label,
Label* false_label,
Label* fall_through)
: ExpressionContext(codegen),
true_label_(true_label),
false_label_(false_label),
fall_through_(fall_through) { }
virtual void Plug(bool flag) const;
virtual void Plug(Register reg) const;
virtual void Plug(Label* materialize_true, Label* materialize_false) const;
virtual void Plug(Slot* slot) const;
virtual void Plug(Handle<Object> lit) const;
virtual void Plug(Heap::RootListIndex) const;
virtual void PlugTOS() const;
virtual void DropAndPlug(int count, Register reg) const;
virtual void EmitLogicalLeft(BinaryOperation* expr,
Label* eval_right,
Label* done) const;
virtual void PrepareTest(Label* materialize_true,
Label* materialize_false,
Label** if_true,
Label** if_false,
Label** fall_through) const;
virtual bool IsTest() const { return true; }
private:
Label* true_label_;
Label* false_label_;
Label* fall_through_;
};
class EffectContext : public ExpressionContext {
public:
explicit EffectContext(FullCodeGenerator* codegen)
: ExpressionContext(codegen) { }
virtual void Plug(bool flag) const;
virtual void Plug(Register reg) const;
virtual void Plug(Label* materialize_true, Label* materialize_false) const;
virtual void Plug(Slot* slot) const;
virtual void Plug(Handle<Object> lit) const;
virtual void Plug(Heap::RootListIndex) const;
virtual void PlugTOS() const;
virtual void DropAndPlug(int count, Register reg) const;
virtual void EmitLogicalLeft(BinaryOperation* expr,
Label* eval_right,
Label* done) const;
virtual void PrepareTest(Label* materialize_true,
Label* materialize_false,
Label** if_true,
Label** if_false,
Label** fall_through) const;
virtual bool IsEffect() const { return true; }
};
const ExpressionContext* context_;
friend class NestedStatement;

File diff suppressed because it is too large Load Diff

View File

@ -1361,6 +1361,13 @@ void MacroAssembler::Drop(int stack_elements) {
}
void MacroAssembler::Move(Register dst, Register src) {
if (!dst.is(src)) {
mov(dst, src);
}
}
void MacroAssembler::Move(Register dst, Handle<Object> value) {
mov(dst, value);
}

View File

@ -505,6 +505,9 @@ class MacroAssembler: public Assembler {
void Call(Label* target) { call(target); }
// Move if the registers are not identical.
void Move(Register target, Register source);
void Move(Register target, Handle<Object> value);
Handle<Object> CodeObject() { return code_object_; }

File diff suppressed because it is too large Load Diff

View File

@ -1207,6 +1207,15 @@ SmiIndex MacroAssembler::SmiToNegativeIndex(Register dst,
}
void MacroAssembler::Move(Register dst, Register src) {
if (!dst.is(src)) {
movq(dst, src);
}
}
void MacroAssembler::Move(Register dst, Handle<Object> source) {
ASSERT(!source->IsFailure());
if (source->IsSmi()) {

View File

@ -557,6 +557,9 @@ class MacroAssembler: public Assembler {
void Set(Register dst, int64_t x);
void Set(const Operand& dst, int64_t x);
// Move if the registers are not identical.
void Move(Register target, Register source);
// Handle support
void Move(Register dst, Handle<Object> source);
void Move(const Operand& dst, Handle<Object> source);