Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(297)

Side by Side Diff: src/ia32/codegen-ia32.cc

Issue 553117: Implementing inline caches for binary operations (ia32).... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/ic.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 832 matching lines...) Expand 10 before | Expand all | Expand 10 after
843 const char* op_name = Token::Name(op_); 843 const char* op_name = Token::Name(op_);
844 const char* overwrite_name; 844 const char* overwrite_name;
845 switch (mode_) { 845 switch (mode_) {
846 case NO_OVERWRITE: overwrite_name = "Alloc"; break; 846 case NO_OVERWRITE: overwrite_name = "Alloc"; break;
847 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break; 847 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break;
848 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break; 848 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break;
849 default: overwrite_name = "UnknownOverwrite"; break; 849 default: overwrite_name = "UnknownOverwrite"; break;
850 } 850 }
851 851
852 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), 852 OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
853 "GenericBinaryOpStub_%s_%s%s_%s%s_%s", 853 "GenericBinaryOpStub_%s_%s%s_%s%s_%s_%s",
854 op_name, 854 op_name,
855 overwrite_name, 855 overwrite_name,
856 (flags_ & NO_SMI_CODE_IN_STUB) ? "_NoSmiInStub" : "", 856 (flags_ & NO_SMI_CODE_IN_STUB) ? "_NoSmiInStub" : "",
857 args_in_registers_ ? "RegArgs" : "StackArgs", 857 args_in_registers_ ? "RegArgs" : "StackArgs",
858 args_reversed_ ? "_R" : "", 858 args_reversed_ ? "_R" : "",
859 NumberInfo::ToString(operands_type_)); 859 NumberInfo::ToString(static_operands_type_),
860 BinaryOpIC::GetName(runtime_operands_type_));
860 return name_; 861 return name_;
861 } 862 }
862 863
863 864
864 // Call the specialized stub for a binary operation. 865 // Call the specialized stub for a binary operation.
865 class DeferredInlineBinaryOperation: public DeferredCode { 866 class DeferredInlineBinaryOperation: public DeferredCode {
866 public: 867 public:
867 DeferredInlineBinaryOperation(Token::Value op, 868 DeferredInlineBinaryOperation(Token::Value op,
868 Register dst, 869 Register dst,
869 Register left, 870 Register left,
(...skipping 7206 matching lines...) Expand 10 before | Expand all | Expand 10 after
8076 8077
8077 8078
8078 void GenericBinaryOpStub::Generate(MacroAssembler* masm) { 8079 void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
8079 Label call_runtime; 8080 Label call_runtime;
8080 8081
8081 __ IncrementCounter(&Counters::generic_binary_stub_calls, 1); 8082 __ IncrementCounter(&Counters::generic_binary_stub_calls, 1);
8082 8083
8083 // Generate fast case smi code if requested. This flag is set when the fast 8084 // Generate fast case smi code if requested. This flag is set when the fast
8084 // case smi code is not generated by the caller. Generating it here will speed 8085 // case smi code is not generated by the caller. Generating it here will speed
8085 // up common operations. 8086 // up common operations.
8086 if (HasSmiCodeInStub()) { 8087 if (ShouldGenerateSmiCode()) {
8087 GenerateSmiCode(masm, &call_runtime); 8088 GenerateSmiCode(masm, &call_runtime);
8088 } else if (op_ != Token::MOD) { // MOD goes straight to runtime. 8089 } else if (op_ != Token::MOD) { // MOD goes straight to runtime.
8089 GenerateLoadArguments(masm); 8090 if (!HasArgsInRegisters()) {
8091 GenerateLoadArguments(masm);
8092 }
8090 } 8093 }
8091 8094
8092 // Floating point case. 8095 // Floating point case.
8093 switch (op_) { 8096 if (ShouldGenerateFPCode()) {
8094 case Token::ADD: 8097 switch (op_) {
8095 case Token::SUB: 8098 case Token::ADD:
8096 case Token::MUL: 8099 case Token::SUB:
8097 case Token::DIV: { 8100 case Token::MUL:
8098 if (CpuFeatures::IsSupported(SSE2)) { 8101 case Token::DIV: {
8099 CpuFeatures::Scope use_sse2(SSE2); 8102 if (runtime_operands_type_ == BinaryOpIC::DEFAULT &&
8100 if (NumberInfo::IsNumber(operands_type_)) { 8103 HasSmiCodeInStub()) {
8101 if (FLAG_debug_code) { 8104 // Execution reaches this point when the first non-smi argument occurs
8102 // Assert at runtime that inputs are only numbers. 8105 // (and only if smi code is generated). This is the right moment to
8103 __ AbortIfNotNumber(edx, 8106 // patch to HEAP_NUMBERS state. The transition is attempted only for
8104 "GenericBinaryOpStub operand not a number."); 8107 // the four basic operations. The stub stays in the DEFAULT state
8105 __ AbortIfNotNumber(eax, 8108 // forever for all other operations (also if smi code is skipped).
8106 "GenericBinaryOpStub operand not a number."); 8109 GenerateTypeTransition(masm);
8107 }
8108 FloatingPointHelper::LoadSSE2Operands(masm);
8109 } else {
8110 FloatingPointHelper::LoadSSE2Operands(masm, &call_runtime);
8111 } 8110 }
8112 8111
8112 Label not_floats;
8113 if (CpuFeatures::IsSupported(SSE2)) {
8114 CpuFeatures::Scope use_sse2(SSE2);
8115 if (NumberInfo::IsNumber(static_operands_type_)) {
8116 if (FLAG_debug_code) {
8117 // Assert at runtime that inputs are only numbers.
8118 __ AbortIfNotNumber(edx,
8119 "GenericBinaryOpStub operand not a number.");
8120 __ AbortIfNotNumber(eax,
8121 "GenericBinaryOpStub operand not a number.");
8122 }
8123 FloatingPointHelper::LoadSSE2Operands(masm);
8124 } else {
8125 FloatingPointHelper::LoadSSE2Operands(masm, &call_runtime);
8126 }
8127
8128 switch (op_) {
8129 case Token::ADD: __ addsd(xmm0, xmm1); break;
8130 case Token::SUB: __ subsd(xmm0, xmm1); break;
8131 case Token::MUL: __ mulsd(xmm0, xmm1); break;
8132 case Token::DIV: __ divsd(xmm0, xmm1); break;
8133 default: UNREACHABLE();
8134 }
8135 GenerateHeapResultAllocation(masm, &call_runtime);
8136 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
8137 GenerateReturn(masm);
8138 } else { // SSE2 not available, use FPU.
8139 if (NumberInfo::IsNumber(static_operands_type_)) {
8140 if (FLAG_debug_code) {
8141 // Assert at runtime that inputs are only numbers.
8142 __ AbortIfNotNumber(edx,
8143 "GenericBinaryOpStub operand not a number.");
8144 __ AbortIfNotNumber(eax,
8145 "GenericBinaryOpStub operand not a number.");
8146 }
8147 } else {
8148 FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx);
8149 }
8150 FloatingPointHelper::LoadFloatOperands(
8151 masm,
8152 ecx,
8153 FloatingPointHelper::ARGS_IN_REGISTERS);
8154 switch (op_) {
8155 case Token::ADD: __ faddp(1); break;
8156 case Token::SUB: __ fsubp(1); break;
8157 case Token::MUL: __ fmulp(1); break;
8158 case Token::DIV: __ fdivp(1); break;
8159 default: UNREACHABLE();
8160 }
8161 Label after_alloc_failure;
8162 GenerateHeapResultAllocation(masm, &after_alloc_failure);
8163 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
8164 GenerateReturn(masm);
8165 __ bind(&after_alloc_failure);
8166 __ ffree();
8167 __ jmp(&call_runtime);
8168 }
8169 __ bind(&not_floats);
8170 if (runtime_operands_type_ == BinaryOpIC::DEFAULT &&
8171 !HasSmiCodeInStub()) {
8172 // Execution reaches this point when the first non-number argument
8173 // occurs (and only if smi code is skipped from the stub, otherwise
8174 // the patching has already been done earlier in this case branch).
8175 // Try patching to STRINGS for ADD operation.
8176 if (op_ == Token::ADD) {
8177 GenerateTypeTransition(masm);
8178 }
8179 }
8180 break;
8181 }
8182 case Token::MOD: {
8183 // For MOD we go directly to runtime in the non-smi case.
8184 break;
8185 }
8186 case Token::BIT_OR:
8187 case Token::BIT_AND:
8188 case Token::BIT_XOR:
8189 case Token::SAR:
8190 case Token::SHL:
8191 case Token::SHR: {
8192 Label non_smi_result;
8193 FloatingPointHelper::LoadAsIntegers(masm, use_sse3_, &call_runtime);
8113 switch (op_) { 8194 switch (op_) {
8114 case Token::ADD: __ addsd(xmm0, xmm1); break; 8195 case Token::BIT_OR: __ or_(eax, Operand(ecx)); break;
8115 case Token::SUB: __ subsd(xmm0, xmm1); break; 8196 case Token::BIT_AND: __ and_(eax, Operand(ecx)); break;
8116 case Token::MUL: __ mulsd(xmm0, xmm1); break; 8197 case Token::BIT_XOR: __ xor_(eax, Operand(ecx)); break;
8117 case Token::DIV: __ divsd(xmm0, xmm1); break; 8198 case Token::SAR: __ sar_cl(eax); break;
8199 case Token::SHL: __ shl_cl(eax); break;
8200 case Token::SHR: __ shr_cl(eax); break;
8118 default: UNREACHABLE(); 8201 default: UNREACHABLE();
8119 } 8202 }
8120 GenerateHeapResultAllocation(masm, &call_runtime); 8203 if (op_ == Token::SHR) {
8121 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); 8204 // Check if result is non-negative and fits in a smi.
8205 __ test(eax, Immediate(0xc0000000));
8206 __ j(not_zero, &call_runtime);
8207 } else {
8208 // Check if result fits in a smi.
8209 __ cmp(eax, 0xc0000000);
8210 __ j(negative, &non_smi_result);
8211 }
8212 // Tag smi result and return.
8213 __ SmiTag(eax);
8122 GenerateReturn(masm); 8214 GenerateReturn(masm);
8123 } else { // SSE2 not available, use FPU. 8215
8124 if (NumberInfo::IsNumber(operands_type_)) { 8216 // All ops except SHR return a signed int32 that we load in
8125 if (FLAG_debug_code) { 8217 // a HeapNumber.
8126 // Assert at runtime that inputs are only numbers. 8218 if (op_ != Token::SHR) {
8127 __ AbortIfNotNumber(edx, 8219 __ bind(&non_smi_result);
8128 "GenericBinaryOpStub operand not a number."); 8220 // Allocate a heap number if needed.
8129 __ AbortIfNotNumber(eax, 8221 __ mov(ebx, Operand(eax)); // ebx: result
8130 "GenericBinaryOpStub operand not a number."); 8222 Label skip_allocation;
8223 switch (mode_) {
8224 case OVERWRITE_LEFT:
8225 case OVERWRITE_RIGHT:
8226 // If the operand was an object, we skip the
8227 // allocation of a heap number.
8228 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ?
8229 1 * kPointerSize : 2 * kPointerSize));
8230 __ test(eax, Immediate(kSmiTagMask));
8231 __ j(not_zero, &skip_allocation, not_taken);
8232 // Fall through!
8233 case NO_OVERWRITE:
8234 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime);
8235 __ bind(&skip_allocation);
8236 break;
8237 default: UNREACHABLE();
8131 } 8238 }
8132 } else { 8239 // Store the result in the HeapNumber and return.
8133 FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx); 8240 if (CpuFeatures::IsSupported(SSE2)) {
8241 CpuFeatures::Scope use_sse2(SSE2);
8242 __ cvtsi2sd(xmm0, Operand(ebx));
8243 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
8244 } else {
8245 __ mov(Operand(esp, 1 * kPointerSize), ebx);
8246 __ fild_s(Operand(esp, 1 * kPointerSize));
8247 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
8248 }
8249 GenerateReturn(masm);
8134 } 8250 }
8135 FloatingPointHelper::LoadFloatOperands( 8251 break;
8136 masm,
8137 ecx,
8138 FloatingPointHelper::ARGS_IN_REGISTERS);
8139 switch (op_) {
8140 case Token::ADD: __ faddp(1); break;
8141 case Token::SUB: __ fsubp(1); break;
8142 case Token::MUL: __ fmulp(1); break;
8143 case Token::DIV: __ fdivp(1); break;
8144 default: UNREACHABLE();
8145 }
8146 Label after_alloc_failure;
8147 GenerateHeapResultAllocation(masm, &after_alloc_failure);
8148 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
8149 GenerateReturn(masm);
8150 __ bind(&after_alloc_failure);
8151 __ ffree();
8152 __ jmp(&call_runtime);
8153 } 8252 }
8253 default: UNREACHABLE(); break;
8154 } 8254 }
8155 case Token::MOD: {
8156 // For MOD we go directly to runtime in the non-smi case.
8157 break;
8158 }
8159 case Token::BIT_OR:
8160 case Token::BIT_AND:
8161 case Token::BIT_XOR:
8162 case Token::SAR:
8163 case Token::SHL:
8164 case Token::SHR: {
8165 Label non_smi_result;
8166 FloatingPointHelper::LoadAsIntegers(masm, use_sse3_, &call_runtime);
8167 switch (op_) {
8168 case Token::BIT_OR: __ or_(eax, Operand(ecx)); break;
8169 case Token::BIT_AND: __ and_(eax, Operand(ecx)); break;
8170 case Token::BIT_XOR: __ xor_(eax, Operand(ecx)); break;
8171 case Token::SAR: __ sar_cl(eax); break;
8172 case Token::SHL: __ shl_cl(eax); break;
8173 case Token::SHR: __ shr_cl(eax); break;
8174 default: UNREACHABLE();
8175 }
8176 if (op_ == Token::SHR) {
8177 // Check if result is non-negative and fits in a smi.
8178 __ test(eax, Immediate(0xc0000000));
8179 __ j(not_zero, &call_runtime);
8180 } else {
8181 // Check if result fits in a smi.
8182 __ cmp(eax, 0xc0000000);
8183 __ j(negative, &non_smi_result);
8184 }
8185 // Tag smi result and return.
8186 __ SmiTag(eax);
8187 GenerateReturn(masm);
8188
8189 // All ops except SHR return a signed int32 that we load in a HeapNumber.
8190 if (op_ != Token::SHR) {
8191 __ bind(&non_smi_result);
8192 // Allocate a heap number if needed.
8193 __ mov(ebx, Operand(eax)); // ebx: result
8194 Label skip_allocation;
8195 switch (mode_) {
8196 case OVERWRITE_LEFT:
8197 case OVERWRITE_RIGHT:
8198 // If the operand was an object, we skip the
8199 // allocation of a heap number.
8200 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ?
8201 1 * kPointerSize : 2 * kPointerSize));
8202 __ test(eax, Immediate(kSmiTagMask));
8203 __ j(not_zero, &skip_allocation, not_taken);
8204 // Fall through!
8205 case NO_OVERWRITE:
8206 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime);
8207 __ bind(&skip_allocation);
8208 break;
8209 default: UNREACHABLE();
8210 }
8211 // Store the result in the HeapNumber and return.
8212 if (CpuFeatures::IsSupported(SSE2)) {
8213 CpuFeatures::Scope use_sse2(SSE2);
8214 __ cvtsi2sd(xmm0, Operand(ebx));
8215 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
8216 } else {
8217 __ mov(Operand(esp, 1 * kPointerSize), ebx);
8218 __ fild_s(Operand(esp, 1 * kPointerSize));
8219 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
8220 }
8221 GenerateReturn(masm);
8222 }
8223 break;
8224 }
8225 default: UNREACHABLE(); break;
8226 } 8255 }
8227 8256
8228 // If all else fails, use the runtime system to get the correct 8257 // If all else fails, use the runtime system to get the correct
8229 // result. If arguments was passed in registers now place them on the 8258 // result. If arguments was passed in registers now place them on the
8230 // stack in the correct order below the return address. 8259 // stack in the correct order below the return address.
8231 __ bind(&call_runtime); 8260 __ bind(&call_runtime);
8232 if (HasArgsInRegisters()) { 8261 if (HasArgsInRegisters()) {
8233 __ pop(ecx); 8262 GenerateRegisterArgsPush(masm);
8234 if (HasArgsReversed()) {
8235 __ push(eax);
8236 __ push(edx);
8237 } else {
8238 __ push(edx);
8239 __ push(eax);
8240 }
8241 __ push(ecx);
8242 } 8263 }
8264
8243 switch (op_) { 8265 switch (op_) {
8244 case Token::ADD: { 8266 case Token::ADD: {
8245 // Test for string arguments before calling runtime. 8267 // Test for string arguments before calling runtime.
8246 Label not_strings, not_string1, string1, string1_smi2; 8268 Label not_strings, not_string1, string1, string1_smi2;
8247 Result answer; 8269
8270 // If this stub has already generated FP-specific code then the arguments
8271 // are already in edx, eax
8272 if (!ShouldGenerateFPCode() && !HasArgsInRegisters()) {
8273 GenerateLoadArguments(masm);
8274 }
8275
8248 __ test(edx, Immediate(kSmiTagMask)); 8276 __ test(edx, Immediate(kSmiTagMask));
8249 __ j(zero, &not_string1); 8277 __ j(zero, &not_string1);
8250 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, ecx); 8278 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, ecx);
8251 __ j(above_equal, &not_string1); 8279 __ j(above_equal, &not_string1);
8252 8280
8253 // First argument is a string, test second. 8281 // First argument is a string, test second.
8254 __ test(eax, Immediate(kSmiTagMask)); 8282 __ test(eax, Immediate(kSmiTagMask));
8255 __ j(zero, &string1_smi2); 8283 __ j(zero, &string1_smi2);
8256 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ecx); 8284 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, ecx);
8257 __ j(above_equal, &string1); 8285 __ j(above_equal, &string1);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
8326 break; 8354 break;
8327 case Token::SHL: 8355 case Token::SHL:
8328 __ InvokeBuiltin(Builtins::SHL, JUMP_FUNCTION); 8356 __ InvokeBuiltin(Builtins::SHL, JUMP_FUNCTION);
8329 break; 8357 break;
8330 case Token::SHR: 8358 case Token::SHR:
8331 __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION); 8359 __ InvokeBuiltin(Builtins::SHR, JUMP_FUNCTION);
8332 break; 8360 break;
8333 default: 8361 default:
8334 UNREACHABLE(); 8362 UNREACHABLE();
8335 } 8363 }
8364
8365 // Generate an unreachable reference to the DEFAULT stub so that it can be
8366 // found at the end of this stub when clearing ICs at GC.
8367 if (runtime_operands_type_ != BinaryOpIC::DEFAULT) {
8368 GenericBinaryOpStub uninit(MinorKey(), BinaryOpIC::DEFAULT);
8369 __ TailCallStub(&uninit);
8370 }
8336 } 8371 }
8337 8372
8338 8373
8339 void GenericBinaryOpStub::GenerateHeapResultAllocation(MacroAssembler* masm, 8374 void GenericBinaryOpStub::GenerateHeapResultAllocation(MacroAssembler* masm,
8340 Label* alloc_failure) { 8375 Label* alloc_failure) {
8341 Label skip_allocation; 8376 Label skip_allocation;
8342 OverwriteMode mode = mode_; 8377 OverwriteMode mode = mode_;
8343 if (HasArgsReversed()) { 8378 if (HasArgsReversed()) {
8344 if (mode == OVERWRITE_RIGHT) { 8379 if (mode == OVERWRITE_RIGHT) {
8345 mode = OVERWRITE_LEFT; 8380 mode = OVERWRITE_LEFT;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
8379 __ mov(eax, ebx); 8414 __ mov(eax, ebx);
8380 __ bind(&skip_allocation); 8415 __ bind(&skip_allocation);
8381 break; 8416 break;
8382 default: UNREACHABLE(); 8417 default: UNREACHABLE();
8383 } 8418 }
8384 } 8419 }
8385 8420
8386 8421
8387 void GenericBinaryOpStub::GenerateLoadArguments(MacroAssembler* masm) { 8422 void GenericBinaryOpStub::GenerateLoadArguments(MacroAssembler* masm) {
8388 // If arguments are not passed in registers read them from the stack. 8423 // If arguments are not passed in registers read them from the stack.
8389 if (!HasArgsInRegisters()) { 8424 ASSERT(!HasArgsInRegisters());
8390 __ mov(eax, Operand(esp, 1 * kPointerSize)); 8425 __ mov(eax, Operand(esp, 1 * kPointerSize));
8391 __ mov(edx, Operand(esp, 2 * kPointerSize)); 8426 __ mov(edx, Operand(esp, 2 * kPointerSize));
8392 }
8393 } 8427 }
8394 8428
8395 8429
8396 void GenericBinaryOpStub::GenerateReturn(MacroAssembler* masm) { 8430 void GenericBinaryOpStub::GenerateReturn(MacroAssembler* masm) {
8397 // If arguments are not passed in registers remove them from the stack before 8431 // If arguments are not passed in registers remove them from the stack before
8398 // returning. 8432 // returning.
8399 if (!HasArgsInRegisters()) { 8433 if (!HasArgsInRegisters()) {
8400 __ ret(2 * kPointerSize); // Remove both operands 8434 __ ret(2 * kPointerSize); // Remove both operands
8401 } else { 8435 } else {
8402 __ ret(0); 8436 __ ret(0);
8403 } 8437 }
8404 } 8438 }
8405 8439
8406 8440
8441 void GenericBinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
8442 ASSERT(HasArgsInRegisters());
8443 __ pop(ecx);
8444 if (HasArgsReversed()) {
8445 __ push(eax);
8446 __ push(edx);
8447 } else {
8448 __ push(edx);
8449 __ push(eax);
8450 }
8451 __ push(ecx);
8452 }
8453
8454
8455 void GenericBinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
8456 Label get_result;
8457
8458 // Keep a copy of operands on the stack and make sure they are also in
8459 // edx, eax.
8460 if (HasArgsInRegisters()) {
8461 GenerateRegisterArgsPush(masm);
8462 } else {
8463 GenerateLoadArguments(masm);
8464 }
8465
8466 // Internal frame is necessary to handle exceptions properly.
8467 __ EnterInternalFrame();
8468
8469 // Push arguments on stack if the stub expects them there.
8470 if (!HasArgsInRegisters()) {
8471 __ push(edx);
8472 __ push(eax);
8473 }
8474 // Call the stub proper to get the result in eax.
8475 __ call(&get_result);
8476 __ LeaveInternalFrame();
8477
8478 __ pop(ecx); // Return address.
8479 // Left and right arguments are now on top.
8480 // Push the operation result. The tail call to BinaryOp_Patch will
8481 // return it to the original caller.
8482 __ push(eax);
8483 // Push this stub's key. Although the operation and the type info are
8484 // encoded into the key, the encoding is opaque, so push them too.
8485 __ push(Immediate(Smi::FromInt(MinorKey())));
8486 __ push(Immediate(Smi::FromInt(op_)));
8487 __ push(Immediate(Smi::FromInt(runtime_operands_type_)));
8488
8489 __ push(ecx); // Return address.
8490
8491 // Patch the caller to an appropriate specialized stub
8492 // and return the operation result.
8493 __ TailCallExternalReference(
8494 ExternalReference(IC_Utility(IC::kBinaryOp_Patch)),
8495 6,
8496 1);
8497
8498 // The entry point for the result calculation is assumed to be immediately
8499 // after this sequence.
8500 __ bind(&get_result);
8501 }
8502
8503 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) {
8504 GenericBinaryOpStub stub(key, type_info);
8505 HandleScope scope;
8506 return stub.GetCode();
8507 }
8508
8509
8407 void TranscendentalCacheStub::Generate(MacroAssembler* masm) { 8510 void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
8408 // Input on stack: 8511 // Input on stack:
8409 // esp[4]: argument (should be number). 8512 // esp[4]: argument (should be number).
8410 // esp[0]: return address. 8513 // esp[0]: return address.
8411 // Test that eax is a number. 8514 // Test that eax is a number.
8412 Label runtime_call; 8515 Label runtime_call;
8413 Label runtime_call_clear_stack; 8516 Label runtime_call_clear_stack;
8414 Label input_not_smi; 8517 Label input_not_smi;
8415 Label loaded; 8518 Label loaded;
8416 __ mov(eax, Operand(esp, kPointerSize)); 8519 __ mov(eax, Operand(esp, kPointerSize));
(...skipping 2863 matching lines...) Expand 10 before | Expand all | Expand 10 after
11280 11383
11281 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 11384 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
11282 // tagged as a small integer. 11385 // tagged as a small integer.
11283 __ bind(&runtime); 11386 __ bind(&runtime);
11284 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 11387 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
11285 } 11388 }
11286 11389
11287 #undef __ 11390 #undef __
11288 11391
11289 } } // namespace v8::internal 11392 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/ic.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698