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

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

Issue 435003: Patch for allowing several V8 instances in process:... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years 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/builtins-ia32.cc ('k') | src/ia32/disasm-ia32.cc » ('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 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 #ifdef DEBUG 147 #ifdef DEBUG
148 if (strlen(FLAG_stop_at) > 0 && 148 if (strlen(FLAG_stop_at) > 0 &&
149 fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { 149 fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
150 frame_->SpillAll(); 150 frame_->SpillAll();
151 __ int3(); 151 __ int3();
152 } 152 }
153 #endif 153 #endif
154 154
155 // New scope to get automatic timing calculation. 155 // New scope to get automatic timing calculation.
156 { // NOLINT 156 { // NOLINT
157 HistogramTimerScope codegen_timer(&Counters::code_generation); 157 HistogramTimerScope codegen_timer(&COUNTER(code_generation));
158 CodeGenState state(this); 158 CodeGenState state(this);
159 159
160 // Entry: 160 // Entry:
161 // Stack: receiver, arguments, return address. 161 // Stack: receiver, arguments, return address.
162 // ebp: caller's frame pointer 162 // ebp: caller's frame pointer
163 // esp: stack pointer 163 // esp: stack pointer
164 // edi: called JS function 164 // edi: called JS function
165 // esi: callee's context 165 // esi: callee's context
166 allocator_->Initialize(); 166 allocator_->Initialize();
167 frame_->Enter(); 167 frame_->Enter();
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 309
310 // Code generation state must be reset. 310 // Code generation state must be reset.
311 ASSERT(state_ == NULL); 311 ASSERT(state_ == NULL);
312 ASSERT(loop_nesting() == 0); 312 ASSERT(loop_nesting() == 0);
313 ASSERT(!function_return_is_shadowed_); 313 ASSERT(!function_return_is_shadowed_);
314 function_return_.Unuse(); 314 function_return_.Unuse();
315 DeleteFrame(); 315 DeleteFrame();
316 316
317 // Process any deferred code using the register allocator. 317 // Process any deferred code using the register allocator.
318 if (!HasStackOverflow()) { 318 if (!HasStackOverflow()) {
319 HistogramTimerScope deferred_timer(&Counters::deferred_code_generation); 319 HistogramTimerScope deferred_timer(&COUNTER(deferred_code_generation));
320 JumpTarget::set_compiling_deferred_code(true); 320 JumpTarget::set_compiling_deferred_code(true);
321 ProcessDeferred(); 321 ProcessDeferred();
322 JumpTarget::set_compiling_deferred_code(false); 322 JumpTarget::set_compiling_deferred_code(false);
323 } 323 }
324 324
325 // There is no need to delete the register allocator, it is a 325 // There is no need to delete the register allocator, it is a
326 // stack-allocated local. 326 // stack-allocated local.
327 allocator_ = NULL; 327 allocator_ = NULL;
328 scope_ = NULL; 328 scope_ = NULL;
329 } 329 }
(...skipping 5690 matching lines...) Expand 10 before | Expand all | Expand 10 after
6020 // The call must be followed by a test eax instruction to indicate 6020 // The call must be followed by a test eax instruction to indicate
6021 // that the inobject property case was inlined. 6021 // that the inobject property case was inlined.
6022 // 6022 //
6023 // Store the delta to the map check instruction here in the test 6023 // Store the delta to the map check instruction here in the test
6024 // instruction. Use masm_-> instead of the __ macro since the 6024 // instruction. Use masm_-> instead of the __ macro since the
6025 // latter can't return a value. 6025 // latter can't return a value.
6026 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); 6026 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site());
6027 // Here we use masm_-> instead of the __ macro because this is the 6027 // Here we use masm_-> instead of the __ macro because this is the
6028 // instruction that gets patched and coverage code gets in the way. 6028 // instruction that gets patched and coverage code gets in the way.
6029 masm_->test(eax, Immediate(-delta_to_patch_site)); 6029 masm_->test(eax, Immediate(-delta_to_patch_site));
6030 __ IncrementCounter(&Counters::named_load_inline_miss, 1); 6030 __ IncrementCounter(&COUNTER(named_load_inline_miss), 1);
6031 6031
6032 if (!dst_.is(eax)) __ mov(dst_, eax); 6032 if (!dst_.is(eax)) __ mov(dst_, eax);
6033 __ pop(receiver_); 6033 __ pop(receiver_);
6034 } 6034 }
6035 6035
6036 6036
6037 class DeferredReferenceGetKeyedValue: public DeferredCode { 6037 class DeferredReferenceGetKeyedValue: public DeferredCode {
6038 public: 6038 public:
6039 explicit DeferredReferenceGetKeyedValue(Register dst, 6039 explicit DeferredReferenceGetKeyedValue(Register dst,
6040 Register receiver, 6040 Register receiver,
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
6074 __ call(ic, mode); 6074 __ call(ic, mode);
6075 // The delta from the start of the map-compare instruction to the 6075 // The delta from the start of the map-compare instruction to the
6076 // test instruction. We use masm_-> directly here instead of the __ 6076 // test instruction. We use masm_-> directly here instead of the __
6077 // macro because the macro sometimes uses macro expansion to turn 6077 // macro because the macro sometimes uses macro expansion to turn
6078 // into something that can't return a value. This is encountered 6078 // into something that can't return a value. This is encountered
6079 // when doing generated code coverage tests. 6079 // when doing generated code coverage tests.
6080 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); 6080 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site());
6081 // Here we use masm_-> instead of the __ macro because this is the 6081 // Here we use masm_-> instead of the __ macro because this is the
6082 // instruction that gets patched and coverage code gets in the way. 6082 // instruction that gets patched and coverage code gets in the way.
6083 masm_->test(eax, Immediate(-delta_to_patch_site)); 6083 masm_->test(eax, Immediate(-delta_to_patch_site));
6084 __ IncrementCounter(&Counters::keyed_load_inline_miss, 1); 6084 __ IncrementCounter(&COUNTER(keyed_load_inline_miss), 1);
6085 6085
6086 if (!dst_.is(eax)) __ mov(dst_, eax); 6086 if (!dst_.is(eax)) __ mov(dst_, eax);
6087 __ pop(key_); 6087 __ pop(key_);
6088 __ pop(receiver_); 6088 __ pop(receiver_);
6089 } 6089 }
6090 6090
6091 6091
6092 class DeferredReferenceSetKeyedValue: public DeferredCode { 6092 class DeferredReferenceSetKeyedValue: public DeferredCode {
6093 public: 6093 public:
6094 DeferredReferenceSetKeyedValue(Register value, 6094 DeferredReferenceSetKeyedValue(Register value,
6095 Register key, 6095 Register key,
6096 Register receiver) 6096 Register receiver)
6097 : value_(value), key_(key), receiver_(receiver) { 6097 : value_(value), key_(key), receiver_(receiver) {
6098 set_comment("[ DeferredReferenceSetKeyedValue"); 6098 set_comment("[ DeferredReferenceSetKeyedValue");
6099 } 6099 }
6100 6100
6101 virtual void Generate(); 6101 virtual void Generate();
6102 6102
6103 Label* patch_site() { return &patch_site_; } 6103 Label* patch_site() { return &patch_site_; }
6104 6104
6105 private: 6105 private:
6106 Register value_; 6106 Register value_;
6107 Register key_; 6107 Register key_;
6108 Register receiver_; 6108 Register receiver_;
6109 Label patch_site_; 6109 Label patch_site_;
6110 }; 6110 };
6111 6111
6112 6112
6113 void DeferredReferenceSetKeyedValue::Generate() { 6113 void DeferredReferenceSetKeyedValue::Generate() {
6114 __ IncrementCounter(&Counters::keyed_store_inline_miss, 1); 6114 __ IncrementCounter(&COUNTER(keyed_store_inline_miss), 1);
6115 // Push receiver and key arguments on the stack. 6115 // Push receiver and key arguments on the stack.
6116 __ push(receiver_); 6116 __ push(receiver_);
6117 __ push(key_); 6117 __ push(key_);
6118 // Move value argument to eax as expected by the IC stub. 6118 // Move value argument to eax as expected by the IC stub.
6119 if (!value_.is(eax)) __ mov(eax, value_); 6119 if (!value_.is(eax)) __ mov(eax, value_);
6120 // Call the IC stub. 6120 // Call the IC stub.
6121 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 6121 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
6122 __ call(ic, RelocInfo::CODE_TARGET); 6122 __ call(ic, RelocInfo::CODE_TARGET);
6123 // The delta from the start of the map-compare instruction to the 6123 // The delta from the start of the map-compare instruction to the
6124 // test instruction. We use masm_-> directly here instead of the 6124 // test instruction. We use masm_-> directly here instead of the
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
6233 // The delta from the patch label to the load offset must be 6233 // The delta from the patch label to the load offset must be
6234 // statically known. 6234 // statically known.
6235 ASSERT(masm->SizeOfCodeGeneratedSince(deferred->patch_site()) == 6235 ASSERT(masm->SizeOfCodeGeneratedSince(deferred->patch_site()) ==
6236 LoadIC::kOffsetToLoadInstruction); 6236 LoadIC::kOffsetToLoadInstruction);
6237 // The initial (invalid) offset has to be large enough to force 6237 // The initial (invalid) offset has to be large enough to force
6238 // a 32-bit instruction encoding to allow patching with an 6238 // a 32-bit instruction encoding to allow patching with an
6239 // arbitrary offset. Use kMaxInt (minus kHeapObjectTag). 6239 // arbitrary offset. Use kMaxInt (minus kHeapObjectTag).
6240 int offset = kMaxInt; 6240 int offset = kMaxInt;
6241 masm->mov(value.reg(), FieldOperand(receiver.reg(), offset)); 6241 masm->mov(value.reg(), FieldOperand(receiver.reg(), offset));
6242 6242
6243 __ IncrementCounter(&Counters::named_load_inline, 1); 6243 __ IncrementCounter(&COUNTER(named_load_inline), 1);
6244 deferred->BindExit(); 6244 deferred->BindExit();
6245 cgen_->frame()->Push(&receiver); 6245 cgen_->frame()->Push(&receiver);
6246 cgen_->frame()->Push(&value); 6246 cgen_->frame()->Push(&value);
6247 } 6247 }
6248 break; 6248 break;
6249 } 6249 }
6250 6250
6251 case KEYED: { 6251 case KEYED: {
6252 Comment cmnt(masm, "[ Load from keyed Property"); 6252 Comment cmnt(masm, "[ Load from keyed Property");
6253 Variable* var = expression_->AsVariableProxy()->AsVariable(); 6253 Variable* var = expression_->AsVariableProxy()->AsVariable();
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
6328 // coming from the deferred code will be in eax. 6328 // coming from the deferred code will be in eax.
6329 Result value = index; 6329 Result value = index;
6330 __ mov(value.reg(), Operand(elements.reg(), 6330 __ mov(value.reg(), Operand(elements.reg(),
6331 index.reg(), 6331 index.reg(),
6332 times_4, 6332 times_4,
6333 FixedArray::kHeaderSize - kHeapObjectTag)); 6333 FixedArray::kHeaderSize - kHeapObjectTag));
6334 elements.Unuse(); 6334 elements.Unuse();
6335 index.Unuse(); 6335 index.Unuse();
6336 __ cmp(Operand(value.reg()), Immediate(Factory::the_hole_value())); 6336 __ cmp(Operand(value.reg()), Immediate(Factory::the_hole_value()));
6337 deferred->Branch(equal); 6337 deferred->Branch(equal);
6338 __ IncrementCounter(&Counters::keyed_load_inline, 1); 6338 __ IncrementCounter(&COUNTER(keyed_load_inline), 1);
6339 6339
6340 deferred->BindExit(); 6340 deferred->BindExit();
6341 // Restore the receiver and key to the frame and push the 6341 // Restore the receiver and key to the frame and push the
6342 // result on top of it. 6342 // result on top of it.
6343 cgen_->frame()->Push(&receiver); 6343 cgen_->frame()->Push(&receiver);
6344 cgen_->frame()->Push(&key); 6344 cgen_->frame()->Push(&key);
6345 cgen_->frame()->Push(&value); 6345 cgen_->frame()->Push(&value);
6346 6346
6347 } else { 6347 } else {
6348 Comment cmnt(masm, "[ Load from keyed Property"); 6348 Comment cmnt(masm, "[ Load from keyed Property");
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
6497 __ cmp(FieldOperand(tmp.reg(), HeapObject::kMapOffset), 6497 __ cmp(FieldOperand(tmp.reg(), HeapObject::kMapOffset),
6498 Immediate(Factory::fixed_array_map())); 6498 Immediate(Factory::fixed_array_map()));
6499 deferred->Branch(not_equal); 6499 deferred->Branch(not_equal);
6500 6500
6501 // Store the value. 6501 // Store the value.
6502 __ mov(Operand(tmp.reg(), 6502 __ mov(Operand(tmp.reg(),
6503 key.reg(), 6503 key.reg(),
6504 times_2, 6504 times_2,
6505 FixedArray::kHeaderSize - kHeapObjectTag), 6505 FixedArray::kHeaderSize - kHeapObjectTag),
6506 value.reg()); 6506 value.reg());
6507 __ IncrementCounter(&Counters::keyed_store_inline, 1); 6507 __ IncrementCounter(&COUNTER(keyed_store_inline), 1);
6508 6508
6509 deferred->BindExit(); 6509 deferred->BindExit();
6510 6510
6511 cgen_->frame()->Push(&receiver); 6511 cgen_->frame()->Push(&receiver);
6512 cgen_->frame()->Push(&key); 6512 cgen_->frame()->Push(&key);
6513 cgen_->frame()->Push(&value); 6513 cgen_->frame()->Push(&value);
6514 } else { 6514 } else {
6515 Result answer = cgen_->frame()->CallKeyedStoreIC(); 6515 Result answer = cgen_->frame()->CallKeyedStoreIC();
6516 // Make sure that we do not have a test instruction after the 6516 // Make sure that we do not have a test instruction after the
6517 // call. A test instruction after the call is used to 6517 // call. A test instruction after the call is used to
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
6622 __ mov(left_arg, left); 6622 __ mov(left_arg, left);
6623 } else { 6623 } else {
6624 // Order of moves is not important. 6624 // Order of moves is not important.
6625 __ mov(left_arg, left); 6625 __ mov(left_arg, left);
6626 __ mov(right_arg, right); 6626 __ mov(right_arg, right);
6627 } 6627 }
6628 } 6628 }
6629 6629
6630 // Update flags to indicate that arguments are in registers. 6630 // Update flags to indicate that arguments are in registers.
6631 SetArgsInRegisters(); 6631 SetArgsInRegisters();
6632 __ IncrementCounter(&Counters::generic_binary_stub_calls_regs, 1); 6632 __ IncrementCounter(&COUNTER(generic_binary_stub_calls_regs), 1);
6633 } 6633 }
6634 6634
6635 // Call the stub. 6635 // Call the stub.
6636 __ CallStub(this); 6636 __ CallStub(this);
6637 } 6637 }
6638 6638
6639 6639
6640 void GenericBinaryOpStub::GenerateCall( 6640 void GenericBinaryOpStub::GenerateCall(
6641 MacroAssembler* masm, 6641 MacroAssembler* masm,
6642 Register left, 6642 Register left,
(...skipping 11 matching lines...) Expand all
6654 } else if (left.is(right_arg) && IsOperationCommutative()) { 6654 } else if (left.is(right_arg) && IsOperationCommutative()) {
6655 __ mov(left_arg, Immediate(right)); 6655 __ mov(left_arg, Immediate(right));
6656 SetArgsReversed(); 6656 SetArgsReversed();
6657 } else { 6657 } else {
6658 __ mov(left_arg, left); 6658 __ mov(left_arg, left);
6659 __ mov(right_arg, Immediate(right)); 6659 __ mov(right_arg, Immediate(right));
6660 } 6660 }
6661 6661
6662 // Update flags to indicate that arguments are in registers. 6662 // Update flags to indicate that arguments are in registers.
6663 SetArgsInRegisters(); 6663 SetArgsInRegisters();
6664 __ IncrementCounter(&Counters::generic_binary_stub_calls_regs, 1); 6664 __ IncrementCounter(&COUNTER(generic_binary_stub_calls_regs), 1);
6665 } 6665 }
6666 6666
6667 // Call the stub. 6667 // Call the stub.
6668 __ CallStub(this); 6668 __ CallStub(this);
6669 } 6669 }
6670 6670
6671 6671
6672 void GenericBinaryOpStub::GenerateCall( 6672 void GenericBinaryOpStub::GenerateCall(
6673 MacroAssembler* masm, 6673 MacroAssembler* masm,
6674 Smi* left, 6674 Smi* left,
(...skipping 10 matching lines...) Expand all
6685 __ mov(left_arg, Immediate(left)); 6685 __ mov(left_arg, Immediate(left));
6686 } else if (right.is(left_arg) && IsOperationCommutative()) { 6686 } else if (right.is(left_arg) && IsOperationCommutative()) {
6687 __ mov(right_arg, Immediate(left)); 6687 __ mov(right_arg, Immediate(left));
6688 SetArgsReversed(); 6688 SetArgsReversed();
6689 } else { 6689 } else {
6690 __ mov(left_arg, Immediate(left)); 6690 __ mov(left_arg, Immediate(left));
6691 __ mov(right_arg, right); 6691 __ mov(right_arg, right);
6692 } 6692 }
6693 // Update flags to indicate that arguments are in registers. 6693 // Update flags to indicate that arguments are in registers.
6694 SetArgsInRegisters(); 6694 SetArgsInRegisters();
6695 __ IncrementCounter(&Counters::generic_binary_stub_calls_regs, 1); 6695 __ IncrementCounter(&COUNTER(generic_binary_stub_calls_regs), 1);
6696 } 6696 }
6697 6697
6698 // Call the stub. 6698 // Call the stub.
6699 __ CallStub(this); 6699 __ CallStub(this);
6700 } 6700 }
6701 6701
6702 6702
6703 void GenericBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, Label* slow) { 6703 void GenericBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, Label* slow) {
6704 // Perform fast-case smi code for the operation (eax <op> ebx) and 6704 // Perform fast-case smi code for the operation (eax <op> ebx) and
6705 // leave result in register eax. 6705 // leave result in register eax.
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
6840 default: 6840 default:
6841 UNREACHABLE(); 6841 UNREACHABLE();
6842 break; 6842 break;
6843 } 6843 }
6844 } 6844 }
6845 6845
6846 6846
6847 void GenericBinaryOpStub::Generate(MacroAssembler* masm) { 6847 void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
6848 Label call_runtime; 6848 Label call_runtime;
6849 6849
6850 __ IncrementCounter(&Counters::generic_binary_stub_calls, 1); 6850 __ IncrementCounter(&COUNTER(generic_binary_stub_calls), 1);
6851 6851
6852 // Generate fast case smi code if requested. This flag is set when the fast 6852 // Generate fast case smi code if requested. This flag is set when the fast
6853 // case smi code is not generated by the caller. Generating it here will speed 6853 // case smi code is not generated by the caller. Generating it here will speed
6854 // up common operations. 6854 // up common operations.
6855 if (HasSmiCodeInStub()) { 6855 if (HasSmiCodeInStub()) {
6856 Label slow; 6856 Label slow;
6857 __ mov(ebx, Operand(esp, 1 * kPointerSize)); 6857 __ mov(ebx, Operand(esp, 1 * kPointerSize));
6858 __ mov(eax, Operand(esp, 2 * kPointerSize)); 6858 __ mov(eax, Operand(esp, 2 * kPointerSize));
6859 GenerateSmiCode(masm, &slow); 6859 GenerateSmiCode(masm, &slow);
6860 GenerateReturn(masm); 6860 GenerateReturn(masm);
(...skipping 1398 matching lines...) Expand 10 before | Expand all | Expand 10 after
8259 8259
8260 // Both arguments are strings. 8260 // Both arguments are strings.
8261 // eax: first string 8261 // eax: first string
8262 // edx: second string 8262 // edx: second string
8263 // Check if either of the strings are empty. In that case return the other. 8263 // Check if either of the strings are empty. In that case return the other.
8264 Label second_not_zero_length, both_not_zero_length; 8264 Label second_not_zero_length, both_not_zero_length;
8265 __ mov(ecx, FieldOperand(edx, String::kLengthOffset)); 8265 __ mov(ecx, FieldOperand(edx, String::kLengthOffset));
8266 __ test(ecx, Operand(ecx)); 8266 __ test(ecx, Operand(ecx));
8267 __ j(not_zero, &second_not_zero_length); 8267 __ j(not_zero, &second_not_zero_length);
8268 // Second string is empty, result is first string which is already in eax. 8268 // Second string is empty, result is first string which is already in eax.
8269 __ IncrementCounter(&Counters::string_add_native, 1); 8269 __ IncrementCounter(&COUNTER(string_add_native), 1);
8270 __ ret(2 * kPointerSize); 8270 __ ret(2 * kPointerSize);
8271 __ bind(&second_not_zero_length); 8271 __ bind(&second_not_zero_length);
8272 __ mov(ebx, FieldOperand(eax, String::kLengthOffset)); 8272 __ mov(ebx, FieldOperand(eax, String::kLengthOffset));
8273 __ test(ebx, Operand(ebx)); 8273 __ test(ebx, Operand(ebx));
8274 __ j(not_zero, &both_not_zero_length); 8274 __ j(not_zero, &both_not_zero_length);
8275 // First string is empty, result is second string which is in edx. 8275 // First string is empty, result is second string which is in edx.
8276 __ mov(eax, edx); 8276 __ mov(eax, edx);
8277 __ IncrementCounter(&Counters::string_add_native, 1); 8277 __ IncrementCounter(&COUNTER(string_add_native), 1);
8278 __ ret(2 * kPointerSize); 8278 __ ret(2 * kPointerSize);
8279 8279
8280 // Both strings are non-empty. 8280 // Both strings are non-empty.
8281 // eax: first string 8281 // eax: first string
8282 // ebx: length of first string 8282 // ebx: length of first string
8283 // ecx: length of second string 8283 // ecx: length of second string
8284 // edx: second string 8284 // edx: second string
8285 // Look at the length of the result of adding the two strings. 8285 // Look at the length of the result of adding the two strings.
8286 Label string_add_flat_result; 8286 Label string_add_flat_result;
8287 __ bind(&both_not_zero_length); 8287 __ bind(&both_not_zero_length);
(...skipping 23 matching lines...) Expand all
8311 // Allocate an acsii cons string. 8311 // Allocate an acsii cons string.
8312 __ AllocateAsciiConsString(ecx, edi, no_reg, &string_add_runtime); 8312 __ AllocateAsciiConsString(ecx, edi, no_reg, &string_add_runtime);
8313 __ bind(&allocated); 8313 __ bind(&allocated);
8314 // Fill the fields of the cons string. 8314 // Fill the fields of the cons string.
8315 __ mov(FieldOperand(ecx, ConsString::kLengthOffset), ebx); 8315 __ mov(FieldOperand(ecx, ConsString::kLengthOffset), ebx);
8316 __ mov(FieldOperand(ecx, ConsString::kHashFieldOffset), 8316 __ mov(FieldOperand(ecx, ConsString::kHashFieldOffset),
8317 Immediate(String::kEmptyHashField)); 8317 Immediate(String::kEmptyHashField));
8318 __ mov(FieldOperand(ecx, ConsString::kFirstOffset), eax); 8318 __ mov(FieldOperand(ecx, ConsString::kFirstOffset), eax);
8319 __ mov(FieldOperand(ecx, ConsString::kSecondOffset), edx); 8319 __ mov(FieldOperand(ecx, ConsString::kSecondOffset), edx);
8320 __ mov(eax, ecx); 8320 __ mov(eax, ecx);
8321 __ IncrementCounter(&Counters::string_add_native, 1); 8321 __ IncrementCounter(&COUNTER(string_add_native), 1);
8322 __ ret(2 * kPointerSize); 8322 __ ret(2 * kPointerSize);
8323 __ bind(&non_ascii); 8323 __ bind(&non_ascii);
8324 // Allocate a two byte cons string. 8324 // Allocate a two byte cons string.
8325 __ AllocateConsString(ecx, edi, no_reg, &string_add_runtime); 8325 __ AllocateConsString(ecx, edi, no_reg, &string_add_runtime);
8326 __ jmp(&allocated); 8326 __ jmp(&allocated);
8327 8327
8328 // Handle creating a flat result. First check that both strings are not 8328 // Handle creating a flat result. First check that both strings are not
8329 // external strings. 8329 // external strings.
8330 // eax: first string 8330 // eax: first string
8331 // ebx: length of resulting flat string 8331 // ebx: length of resulting flat string
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
8372 GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true); 8372 GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true);
8373 // Load second argument and locate first character. 8373 // Load second argument and locate first character.
8374 __ mov(edx, Operand(esp, 1 * kPointerSize)); 8374 __ mov(edx, Operand(esp, 1 * kPointerSize));
8375 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); 8375 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
8376 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 8376 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
8377 // eax: result string 8377 // eax: result string
8378 // ecx: next character of result 8378 // ecx: next character of result
8379 // edx: first char of second argument 8379 // edx: first char of second argument
8380 // edi: length of second argument 8380 // edi: length of second argument
8381 GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true); 8381 GenerateCopyCharacters(masm, ecx, edx, edi, ebx, true);
8382 __ IncrementCounter(&Counters::string_add_native, 1); 8382 __ IncrementCounter(&COUNTER(string_add_native), 1);
8383 __ ret(2 * kPointerSize); 8383 __ ret(2 * kPointerSize);
8384 8384
8385 // Handle creating a flat two byte result. 8385 // Handle creating a flat two byte result.
8386 // eax: first string - known to be two byte 8386 // eax: first string - known to be two byte
8387 // ebx: length of resulting flat string 8387 // ebx: length of resulting flat string
8388 // edx: second string 8388 // edx: second string
8389 __ bind(&non_ascii_string_add_flat_result); 8389 __ bind(&non_ascii_string_add_flat_result);
8390 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 8390 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
8391 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); 8391 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
8392 __ and_(ecx, kAsciiStringTag); 8392 __ and_(ecx, kAsciiStringTag);
(...skipping 18 matching lines...) Expand all
8411 GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false); 8411 GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false);
8412 // Load second argument and locate first character. 8412 // Load second argument and locate first character.
8413 __ mov(edx, Operand(esp, 1 * kPointerSize)); 8413 __ mov(edx, Operand(esp, 1 * kPointerSize));
8414 __ mov(edi, FieldOperand(edx, String::kLengthOffset)); 8414 __ mov(edi, FieldOperand(edx, String::kLengthOffset));
8415 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 8415 __ add(Operand(edx), Immediate(SeqAsciiString::kHeaderSize - kHeapObjectTag));
8416 // eax: result string 8416 // eax: result string
8417 // ecx: next character of result 8417 // ecx: next character of result
8418 // edx: first char of second argument 8418 // edx: first char of second argument
8419 // edi: length of second argument 8419 // edi: length of second argument
8420 GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false); 8420 GenerateCopyCharacters(masm, ecx, edx, edi, ebx, false);
8421 __ IncrementCounter(&Counters::string_add_native, 1); 8421 __ IncrementCounter(&COUNTER(string_add_native), 1);
8422 __ ret(2 * kPointerSize); 8422 __ ret(2 * kPointerSize);
8423 8423
8424 // Just jump to runtime to add the two strings. 8424 // Just jump to runtime to add the two strings.
8425 __ bind(&string_add_runtime); 8425 __ bind(&string_add_runtime);
8426 __ TailCallRuntime(ExternalReference(Runtime::kStringAdd), 2, 1); 8426 __ TailCallRuntime(ExternalReference(Runtime::kStringAdd), 2, 1);
8427 } 8427 }
8428 8428
8429 8429
8430 void StringAddStub::GenerateCopyCharacters(MacroAssembler* masm, 8430 void StringAddStub::GenerateCopyCharacters(MacroAssembler* masm,
8431 Register dest, 8431 Register dest,
(...skipping 17 matching lines...) Expand all
8449 __ add(Operand(dest), Immediate(2)); 8449 __ add(Operand(dest), Immediate(2));
8450 } 8450 }
8451 __ sub(Operand(count), Immediate(1)); 8451 __ sub(Operand(count), Immediate(1));
8452 __ j(not_zero, &loop); 8452 __ j(not_zero, &loop);
8453 } 8453 }
8454 8454
8455 8455
8456 #undef __ 8456 #undef __
8457 8457
8458 } } // namespace v8::internal 8458 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/builtins-ia32.cc ('k') | src/ia32/disasm-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698