Add partially-implemented TypeRecordingBinaryOpStub to x64 platform.
Review URL: http://codereview.chromium.org/6084010 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6177 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
f5fb75ce09
commit
7cdd2f6494
@ -1772,7 +1772,6 @@ void TypeRecordingBinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
void TypeRecordingBinaryOpStub::GenerateStringStub(MacroAssembler* masm) {
|
||||
Label call_runtime;
|
||||
ASSERT(operands_type_ == TRBinaryOpIC::STRING);
|
||||
|
@ -250,13 +250,6 @@ class TypeRecordingBinaryOpStub: public CodeStub {
|
||||
result_type_(result_type),
|
||||
name_(NULL) { }
|
||||
|
||||
// Generate code to call the stub with the supplied arguments. This will add
|
||||
// code at the call site to prepare arguments either in registers or on the
|
||||
// stack together with the actual call.
|
||||
void GenerateCall(MacroAssembler* masm, Register left, Register right);
|
||||
void GenerateCall(MacroAssembler* masm, Register left, Smi* right);
|
||||
void GenerateCall(MacroAssembler* masm, Smi* left, Register right);
|
||||
|
||||
private:
|
||||
enum SmiCodeGenerateHeapNumberResults {
|
||||
ALLOW_HEAPNUMBER_RESULTS,
|
||||
@ -321,10 +314,6 @@ class TypeRecordingBinaryOpStub: public CodeStub {
|
||||
void GenerateTypeTransition(MacroAssembler* masm);
|
||||
void GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm);
|
||||
|
||||
bool IsOperationCommutative() {
|
||||
return (op_ == Token::ADD) || (op_ == Token::MUL);
|
||||
}
|
||||
|
||||
virtual int GetCodeKind() { return Code::TYPE_RECORDING_BINARY_OP_IC; }
|
||||
|
||||
virtual InlineCacheState GetICState() {
|
||||
|
@ -988,8 +988,195 @@ Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) {
|
||||
Handle<Code> GetTypeRecordingBinaryOpStub(int key,
|
||||
TRBinaryOpIC::TypeInfo type_info,
|
||||
TRBinaryOpIC::TypeInfo result_type_info) {
|
||||
TypeRecordingBinaryOpStub stub(key, type_info, result_type_info);
|
||||
return stub.GetCode();
|
||||
}
|
||||
|
||||
|
||||
void TypeRecordingBinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
|
||||
__ pop(rcx); // Save return address.
|
||||
__ push(rdx);
|
||||
__ push(rax);
|
||||
// Left and right arguments are now on top.
|
||||
// Push this stub's key. Although the operation and the type info are
|
||||
// encoded into the key, the encoding is opaque, so push them too.
|
||||
__ Push(Smi::FromInt(MinorKey()));
|
||||
__ Push(Smi::FromInt(op_));
|
||||
__ Push(Smi::FromInt(operands_type_));
|
||||
|
||||
__ push(rcx); // Push return address.
|
||||
|
||||
// Patch the caller to an appropriate specialized stub and return the
|
||||
// operation result to the caller of the stub.
|
||||
__ TailCallExternalReference(
|
||||
ExternalReference(IC_Utility(IC::kTypeRecordingBinaryOp_Patch)),
|
||||
5,
|
||||
1);
|
||||
}
|
||||
|
||||
|
||||
// Prepare for a type transition runtime call when the args are already on
|
||||
// the stack, under the return address.
|
||||
void TypeRecordingBinaryOpStub::GenerateTypeTransitionWithSavedArgs(
|
||||
MacroAssembler* masm) {
|
||||
__ pop(rcx); // Save return address.
|
||||
// Left and right arguments are already on top of the stack.
|
||||
// Push this stub's key. Although the operation and the type info are
|
||||
// encoded into the key, the encoding is opaque, so push them too.
|
||||
__ Push(Smi::FromInt(MinorKey()));
|
||||
__ Push(Smi::FromInt(op_));
|
||||
__ Push(Smi::FromInt(operands_type_));
|
||||
|
||||
__ push(rcx); // Push return address.
|
||||
|
||||
// Patch the caller to an appropriate specialized stub and return the
|
||||
// operation result to the caller of the stub.
|
||||
__ TailCallExternalReference(
|
||||
ExternalReference(IC_Utility(IC::kTypeRecordingBinaryOp_Patch)),
|
||||
5,
|
||||
1);
|
||||
}
|
||||
|
||||
|
||||
void TypeRecordingBinaryOpStub::Generate(MacroAssembler* masm) {
|
||||
switch (operands_type_) {
|
||||
case TRBinaryOpIC::UNINITIALIZED:
|
||||
GenerateTypeTransition(masm);
|
||||
break;
|
||||
case TRBinaryOpIC::SMI:
|
||||
GenerateSmiStub(masm);
|
||||
break;
|
||||
case TRBinaryOpIC::INT32:
|
||||
GenerateInt32Stub(masm);
|
||||
break;
|
||||
case TRBinaryOpIC::HEAP_NUMBER:
|
||||
GenerateHeapNumberStub(masm);
|
||||
break;
|
||||
case TRBinaryOpIC::STRING:
|
||||
GenerateStringStub(masm);
|
||||
break;
|
||||
case TRBinaryOpIC::GENERIC:
|
||||
GenerateGeneric(masm);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char* TypeRecordingBinaryOpStub::GetName() {
|
||||
if (name_ != NULL) return name_;
|
||||
const int kMaxNameLength = 100;
|
||||
name_ = Bootstrapper::AllocateAutoDeletedArray(kMaxNameLength);
|
||||
if (name_ == NULL) return "OOM";
|
||||
const char* op_name = Token::Name(op_);
|
||||
const char* overwrite_name;
|
||||
switch (mode_) {
|
||||
case NO_OVERWRITE: overwrite_name = "Alloc"; break;
|
||||
case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break;
|
||||
case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break;
|
||||
default: overwrite_name = "UnknownOverwrite"; break;
|
||||
}
|
||||
|
||||
OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
|
||||
"TypeRecordingBinaryOpStub_%s_%s_%s",
|
||||
op_name,
|
||||
overwrite_name,
|
||||
TRBinaryOpIC::GetName(operands_type_));
|
||||
return name_;
|
||||
}
|
||||
|
||||
|
||||
void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm,
|
||||
Label* slow,
|
||||
SmiCodeGenerateHeapNumberResults allow_heapnumber_results) {
|
||||
UNIMPLEMENTED();
|
||||
return Handle<Code>::null();
|
||||
}
|
||||
|
||||
|
||||
void TypeRecordingBinaryOpStub::GenerateSmiStub(MacroAssembler* masm) {
|
||||
Label call_runtime;
|
||||
|
||||
switch (op_) {
|
||||
case Token::ADD:
|
||||
case Token::SUB:
|
||||
case Token::MUL:
|
||||
case Token::DIV:
|
||||
break;
|
||||
case Token::MOD:
|
||||
case Token::BIT_OR:
|
||||
case Token::BIT_AND:
|
||||
case Token::BIT_XOR:
|
||||
case Token::SAR:
|
||||
case Token::SHL:
|
||||
case Token::SHR:
|
||||
GenerateRegisterArgsPush(masm);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
if (result_type_ == TRBinaryOpIC::UNINITIALIZED ||
|
||||
result_type_ == TRBinaryOpIC::SMI) {
|
||||
GenerateSmiCode(masm, &call_runtime, NO_HEAPNUMBER_RESULTS);
|
||||
} else {
|
||||
GenerateSmiCode(masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS);
|
||||
}
|
||||
__ bind(&call_runtime);
|
||||
switch (op_) {
|
||||
case Token::ADD:
|
||||
case Token::SUB:
|
||||
case Token::MUL:
|
||||
case Token::DIV:
|
||||
GenerateTypeTransition(masm);
|
||||
break;
|
||||
case Token::MOD:
|
||||
case Token::BIT_OR:
|
||||
case Token::BIT_AND:
|
||||
case Token::BIT_XOR:
|
||||
case Token::SAR:
|
||||
case Token::SHL:
|
||||
case Token::SHR:
|
||||
GenerateTypeTransitionWithSavedArgs(masm);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TypeRecordingBinaryOpStub::GenerateStringStub(MacroAssembler* masm) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
|
||||
void TypeRecordingBinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
|
||||
void TypeRecordingBinaryOpStub::GenerateHeapNumberStub(MacroAssembler* masm) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
|
||||
void TypeRecordingBinaryOpStub::GenerateGeneric(MacroAssembler* masm) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
|
||||
void TypeRecordingBinaryOpStub::GenerateHeapResultAllocation(
|
||||
MacroAssembler* masm,
|
||||
Label* alloc_failure) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
|
||||
void TypeRecordingBinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
|
||||
__ pop(rcx);
|
||||
__ push(rdx);
|
||||
__ push(rax);
|
||||
__ push(rcx);
|
||||
}
|
||||
|
||||
|
||||
|
@ -131,7 +131,7 @@ class GenericBinaryOpStub: public CodeStub {
|
||||
#ifdef DEBUG
|
||||
void Print() {
|
||||
PrintF("GenericBinaryOpStub %d (op %s), "
|
||||
"(mode %d, flags %d, registers %d, reversed %d, only_numbers %s)\n",
|
||||
"(mode %d, flags %d, registers %d, reversed %d, type_info %s)\n",
|
||||
MinorKey(),
|
||||
Token::String(op_),
|
||||
static_cast<int>(mode_),
|
||||
@ -200,6 +200,104 @@ class GenericBinaryOpStub: public CodeStub {
|
||||
friend class CodeGenerator;
|
||||
};
|
||||
|
||||
|
||||
class TypeRecordingBinaryOpStub: public CodeStub {
|
||||
public:
|
||||
TypeRecordingBinaryOpStub(Token::Value op, OverwriteMode mode)
|
||||
: op_(op),
|
||||
mode_(mode),
|
||||
operands_type_(TRBinaryOpIC::UNINITIALIZED),
|
||||
result_type_(TRBinaryOpIC::UNINITIALIZED),
|
||||
name_(NULL) {
|
||||
ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
|
||||
}
|
||||
|
||||
TypeRecordingBinaryOpStub(
|
||||
int key,
|
||||
TRBinaryOpIC::TypeInfo operands_type,
|
||||
TRBinaryOpIC::TypeInfo result_type = TRBinaryOpIC::UNINITIALIZED)
|
||||
: op_(OpBits::decode(key)),
|
||||
mode_(ModeBits::decode(key)),
|
||||
operands_type_(operands_type),
|
||||
result_type_(result_type),
|
||||
name_(NULL) { }
|
||||
|
||||
private:
|
||||
enum SmiCodeGenerateHeapNumberResults {
|
||||
ALLOW_HEAPNUMBER_RESULTS,
|
||||
NO_HEAPNUMBER_RESULTS
|
||||
};
|
||||
|
||||
Token::Value op_;
|
||||
OverwriteMode mode_;
|
||||
|
||||
// Operand type information determined at runtime.
|
||||
TRBinaryOpIC::TypeInfo operands_type_;
|
||||
TRBinaryOpIC::TypeInfo result_type_;
|
||||
|
||||
char* name_;
|
||||
|
||||
const char* GetName();
|
||||
|
||||
#ifdef DEBUG
|
||||
void Print() {
|
||||
PrintF("TypeRecordingBinaryOpStub %d (op %s), "
|
||||
"(mode %d, runtime_type_info %s)\n",
|
||||
MinorKey(),
|
||||
Token::String(op_),
|
||||
static_cast<int>(mode_),
|
||||
TRBinaryOpIC::GetName(operands_type_));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Minor key encoding in 15 bits RRRTTTOOOOOOOMM.
|
||||
class ModeBits: public BitField<OverwriteMode, 0, 2> {};
|
||||
class OpBits: public BitField<Token::Value, 2, 7> {};
|
||||
class OperandTypeInfoBits: public BitField<TRBinaryOpIC::TypeInfo, 9, 3> {};
|
||||
class ResultTypeInfoBits: public BitField<TRBinaryOpIC::TypeInfo, 12, 3> {};
|
||||
|
||||
Major MajorKey() { return TypeRecordingBinaryOp; }
|
||||
int MinorKey() {
|
||||
return OpBits::encode(op_)
|
||||
| ModeBits::encode(mode_)
|
||||
| OperandTypeInfoBits::encode(operands_type_)
|
||||
| ResultTypeInfoBits::encode(result_type_);
|
||||
}
|
||||
|
||||
void Generate(MacroAssembler* masm);
|
||||
void GenerateGeneric(MacroAssembler* masm);
|
||||
void GenerateSmiCode(MacroAssembler* masm,
|
||||
Label* slow,
|
||||
SmiCodeGenerateHeapNumberResults heapnumber_results);
|
||||
void GenerateLoadArguments(MacroAssembler* masm);
|
||||
void GenerateReturn(MacroAssembler* masm);
|
||||
void GenerateUninitializedStub(MacroAssembler* masm);
|
||||
void GenerateSmiStub(MacroAssembler* masm);
|
||||
void GenerateInt32Stub(MacroAssembler* masm);
|
||||
void GenerateHeapNumberStub(MacroAssembler* masm);
|
||||
void GenerateStringStub(MacroAssembler* masm);
|
||||
void GenerateGenericStub(MacroAssembler* masm);
|
||||
|
||||
void GenerateHeapResultAllocation(MacroAssembler* masm, Label* alloc_failure);
|
||||
void GenerateRegisterArgsPush(MacroAssembler* masm);
|
||||
void GenerateTypeTransition(MacroAssembler* masm);
|
||||
void GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm);
|
||||
|
||||
virtual int GetCodeKind() { return Code::TYPE_RECORDING_BINARY_OP_IC; }
|
||||
|
||||
virtual InlineCacheState GetICState() {
|
||||
return TRBinaryOpIC::ToState(operands_type_);
|
||||
}
|
||||
|
||||
virtual void FinishCode(Code* code) {
|
||||
code->set_type_recording_binary_op_type(operands_type_);
|
||||
code->set_type_recording_binary_op_result_type(result_type_);
|
||||
}
|
||||
|
||||
friend class CodeGenerator;
|
||||
};
|
||||
|
||||
|
||||
class StringHelper : public AllStatic {
|
||||
public:
|
||||
// Generate code for copying characters using a simple loop. This should only
|
||||
|
Loading…
Reference in New Issue
Block a user