diff options
Diffstat (limited to 'src/x64/code-stubs-x64.cc')
-rw-r--r-- | src/x64/code-stubs-x64.cc | 189 |
1 files changed, 188 insertions, 1 deletions
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc index 60ec35d0..59522d22 100644 --- a/src/x64/code-stubs-x64.cc +++ b/src/x64/code-stubs-x64.cc @@ -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); } |