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

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

Issue 844006: Merge changes up to V8 version 2.1.3 into the partial snapshots (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/partial_snapshots/
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/arm/codegen-arm.h ('k') | src/arm/fast-codegen-arm.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 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 13 matching lines...) Expand all
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "bootstrapper.h" 30 #include "bootstrapper.h"
31 #include "codegen-inl.h" 31 #include "codegen-inl.h"
32 #include "compiler.h" 32 #include "compiler.h"
33 #include "debug.h" 33 #include "debug.h"
34 #include "ic-inl.h"
34 #include "parser.h" 35 #include "parser.h"
35 #include "register-allocator-inl.h" 36 #include "register-allocator-inl.h"
36 #include "runtime.h" 37 #include "runtime.h"
37 #include "scopes.h" 38 #include "scopes.h"
38 39 #include "virtual-frame-inl.h"
39 40
40 namespace v8 { 41 namespace v8 {
41 namespace internal { 42 namespace internal {
42 43
43 #define __ ACCESS_MASM(masm_) 44 #define __ ACCESS_MASM(masm_)
44 45
45 static void EmitIdenticalObjectComparison(MacroAssembler* masm, 46 static void EmitIdenticalObjectComparison(MacroAssembler* masm,
46 Label* slow, 47 Label* slow,
47 Condition cc, 48 Condition cc,
48 bool never_nan_nan); 49 bool never_nan_nan);
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 masm_(masm), 127 masm_(masm),
127 info_(NULL), 128 info_(NULL),
128 frame_(NULL), 129 frame_(NULL),
129 allocator_(NULL), 130 allocator_(NULL),
130 cc_reg_(al), 131 cc_reg_(al),
131 state_(NULL), 132 state_(NULL),
132 function_return_is_shadowed_(false) { 133 function_return_is_shadowed_(false) {
133 } 134 }
134 135
135 136
136 Scope* CodeGenerator::scope() { return info_->function()->scope(); }
137
138
139 // Calling conventions: 137 // Calling conventions:
140 // fp: caller's frame pointer 138 // fp: caller's frame pointer
141 // sp: stack pointer 139 // sp: stack pointer
142 // r1: called JS function 140 // r1: called JS function
143 // cp: callee's context 141 // cp: callee's context
144 142
145 void CodeGenerator::Generate(CompilationInfo* info) { 143 void CodeGenerator::Generate(CompilationInfo* info) {
146 // Record the position for debugging purposes. 144 // Record the position for debugging purposes.
147 CodeForFunctionPosition(info->function()); 145 CodeForFunctionPosition(info->function());
146 Comment cmnt(masm_, "[ function compiled by virtual frame code generator");
148 147
149 // Initialize state. 148 // Initialize state.
150 info_ = info; 149 info_ = info;
151 ASSERT(allocator_ == NULL); 150 ASSERT(allocator_ == NULL);
152 RegisterAllocator register_allocator(this); 151 RegisterAllocator register_allocator(this);
153 allocator_ = &register_allocator; 152 allocator_ = &register_allocator;
154 ASSERT(frame_ == NULL); 153 ASSERT(frame_ == NULL);
155 frame_ = new VirtualFrame(); 154 frame_ = new VirtualFrame();
156 cc_reg_ = al; 155 cc_reg_ = al;
157 { 156 {
(...skipping 3159 matching lines...) Expand 10 before | Expand all | Expand 10 after
3317 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { 3316 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
3318 VirtualFrame::SpilledScope spilled_scope; 3317 VirtualFrame::SpilledScope spilled_scope;
3319 ASSERT(args->length() == 1); 3318 ASSERT(args->length() == 1);
3320 LoadAndSpill(args->at(0)); 3319 LoadAndSpill(args->at(0));
3321 frame_->EmitPop(r0); 3320 frame_->EmitPop(r0);
3322 __ tst(r0, Operand(kSmiTagMask | 0x80000000u)); 3321 __ tst(r0, Operand(kSmiTagMask | 0x80000000u));
3323 cc_reg_ = eq; 3322 cc_reg_ = eq;
3324 } 3323 }
3325 3324
3326 3325
3326 // Generates the Math.pow method - currently just calls runtime.
3327 void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) {
3328 ASSERT(args->length() == 2);
3329 Load(args->at(0));
3330 Load(args->at(1));
3331 frame_->CallRuntime(Runtime::kMath_pow, 2);
3332 frame_->EmitPush(r0);
3333 }
3334
3335
3336 // Generates the Math.sqrt method - currently just calls runtime.
3337 void CodeGenerator::GenerateMathSqrt(ZoneList<Expression*>* args) {
3338 ASSERT(args->length() == 1);
3339 Load(args->at(0));
3340 frame_->CallRuntime(Runtime::kMath_sqrt, 1);
3341 frame_->EmitPush(r0);
3342 }
3343
3344
3327 // This should generate code that performs a charCodeAt() call or returns 3345 // This should generate code that performs a charCodeAt() call or returns
3328 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt. 3346 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt.
3329 // It is not yet implemented on ARM, so it always goes to the slow case. 3347 // It is not yet implemented on ARM, so it always goes to the slow case.
3330 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { 3348 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) {
3331 VirtualFrame::SpilledScope spilled_scope; 3349 VirtualFrame::SpilledScope spilled_scope;
3332 ASSERT(args->length() == 2); 3350 ASSERT(args->length() == 2);
3333 Comment(masm_, "[ GenerateFastCharCodeAt"); 3351 Comment(masm_, "[ GenerateFastCharCodeAt");
3334 3352
3335 LoadAndSpill(args->at(0)); 3353 LoadAndSpill(args->at(0));
3336 LoadAndSpill(args->at(1)); 3354 LoadAndSpill(args->at(1));
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
3400 __ jmp(&try_again_with_new_string); 3418 __ jmp(&try_again_with_new_string);
3401 3419
3402 __ bind(&slow); 3420 __ bind(&slow);
3403 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 3421 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
3404 3422
3405 __ bind(&end); 3423 __ bind(&end);
3406 frame_->EmitPush(r0); 3424 frame_->EmitPush(r0);
3407 } 3425 }
3408 3426
3409 3427
3428 void CodeGenerator::GenerateCharFromCode(ZoneList<Expression*>* args) {
3429 Comment(masm_, "[ GenerateCharFromCode");
3430 ASSERT(args->length() == 1);
3431
3432 LoadAndSpill(args->at(0));
3433 frame_->EmitPop(r0);
3434
3435 JumpTarget slow_case;
3436 JumpTarget exit;
3437
3438 // Fast case of Heap::LookupSingleCharacterStringFromCode.
3439 ASSERT(kSmiTag == 0);
3440 ASSERT(kSmiShiftSize == 0);
3441 ASSERT(IsPowerOf2(String::kMaxAsciiCharCode + 1));
3442 __ tst(r0, Operand(kSmiTagMask |
3443 ((~String::kMaxAsciiCharCode) << kSmiTagSize)));
3444 slow_case.Branch(nz);
3445
3446 ASSERT(kSmiTag == 0);
3447 __ mov(r1, Operand(Factory::single_character_string_cache()));
3448 __ add(r1, r1, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
3449 __ ldr(r1, MemOperand(r1, FixedArray::kHeaderSize - kHeapObjectTag));
3450 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
3451 __ cmp(r1, ip);
3452 slow_case.Branch(eq);
3453
3454 frame_->EmitPush(r1);
3455 exit.Jump();
3456
3457 slow_case.Bind();
3458 frame_->EmitPush(r0);
3459 frame_->CallRuntime(Runtime::kCharFromCode, 1);
3460 frame_->EmitPush(r0);
3461
3462 exit.Bind();
3463 }
3464
3465
3410 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { 3466 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
3411 VirtualFrame::SpilledScope spilled_scope; 3467 VirtualFrame::SpilledScope spilled_scope;
3412 ASSERT(args->length() == 1); 3468 ASSERT(args->length() == 1);
3413 LoadAndSpill(args->at(0)); 3469 LoadAndSpill(args->at(0));
3414 JumpTarget answer; 3470 JumpTarget answer;
3415 // We need the CC bits to come out as not_equal in the case where the 3471 // We need the CC bits to come out as not_equal in the case where the
3416 // object is a smi. This can't be done with the usual test opcode so 3472 // object is a smi. This can't be done with the usual test opcode so
3417 // we use XOR to get the right CC bits. 3473 // we use XOR to get the right CC bits.
3418 frame_->EmitPop(r0); 3474 frame_->EmitPop(r0);
3419 __ and_(r1, r0, Operand(kSmiTagMask)); 3475 __ and_(r1, r0, Operand(kSmiTagMask));
(...skipping 1083 matching lines...) Expand 10 before | Expand all | Expand 10 after
4503 } 4559 }
4504 } 4560 }
4505 4561
4506 // Return result. The argument boilerplate has been popped already. 4562 // Return result. The argument boilerplate has been popped already.
4507 __ Ret(); 4563 __ Ret();
4508 4564
4509 // Create a new closure through the slower runtime call. 4565 // Create a new closure through the slower runtime call.
4510 __ bind(&gc); 4566 __ bind(&gc);
4511 __ push(cp); 4567 __ push(cp);
4512 __ push(r3); 4568 __ push(r3);
4513 __ TailCallRuntime(ExternalReference(Runtime::kNewClosure), 2, 1); 4569 __ TailCallRuntime(Runtime::kNewClosure, 2, 1);
4514 } 4570 }
4515 4571
4516 4572
4517 void FastNewContextStub::Generate(MacroAssembler* masm) { 4573 void FastNewContextStub::Generate(MacroAssembler* masm) {
4518 // Try to allocate the context in new space. 4574 // Try to allocate the context in new space.
4519 Label gc; 4575 Label gc;
4520 int length = slots_ + Context::MIN_CONTEXT_SLOTS; 4576 int length = slots_ + Context::MIN_CONTEXT_SLOTS;
4521 4577
4522 // Attempt to allocate the context in new space. 4578 // Attempt to allocate the context in new space.
4523 __ AllocateInNewSpace(length + (FixedArray::kHeaderSize / kPointerSize), 4579 __ AllocateInNewSpace(length + (FixedArray::kHeaderSize / kPointerSize),
(...skipping 29 matching lines...) Expand all
4553 __ str(r1, MemOperand(r0, Context::SlotOffset(i))); 4609 __ str(r1, MemOperand(r0, Context::SlotOffset(i)));
4554 } 4610 }
4555 4611
4556 // Remove the on-stack argument and return. 4612 // Remove the on-stack argument and return.
4557 __ mov(cp, r0); 4613 __ mov(cp, r0);
4558 __ pop(); 4614 __ pop();
4559 __ Ret(); 4615 __ Ret();
4560 4616
4561 // Need to collect. Call into runtime system. 4617 // Need to collect. Call into runtime system.
4562 __ bind(&gc); 4618 __ bind(&gc);
4563 __ TailCallRuntime(ExternalReference(Runtime::kNewContext), 1, 1); 4619 __ TailCallRuntime(Runtime::kNewContext, 1, 1);
4564 } 4620 }
4565 4621
4566 4622
4567 void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) { 4623 void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) {
4568 // Stack layout on entry: 4624 // Stack layout on entry:
4569 // 4625 //
4570 // [sp]: constant elements. 4626 // [sp]: constant elements.
4571 // [sp + kPointerSize]: literal index. 4627 // [sp + kPointerSize]: literal index.
4572 // [sp + (2 * kPointerSize)]: literals array. 4628 // [sp + (2 * kPointerSize)]: literals array.
4573 4629
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
4615 __ ldr(r1, FieldMemOperand(r3, i)); 4671 __ ldr(r1, FieldMemOperand(r3, i));
4616 __ str(r1, FieldMemOperand(r2, i)); 4672 __ str(r1, FieldMemOperand(r2, i));
4617 } 4673 }
4618 } 4674 }
4619 4675
4620 // Return and remove the on-stack parameters. 4676 // Return and remove the on-stack parameters.
4621 __ add(sp, sp, Operand(3 * kPointerSize)); 4677 __ add(sp, sp, Operand(3 * kPointerSize));
4622 __ Ret(); 4678 __ Ret();
4623 4679
4624 __ bind(&slow_case); 4680 __ bind(&slow_case);
4625 ExternalReference runtime(Runtime::kCreateArrayLiteralShallow); 4681 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1);
4626 __ TailCallRuntime(runtime, 3, 1);
4627 } 4682 }
4628 4683
4629 4684
4630 // Count leading zeros in a 32 bit word. On ARM5 and later it uses the clz 4685 // Count leading zeros in a 32 bit word. On ARM5 and later it uses the clz
4631 // instruction. On pre-ARM5 hardware this routine gives the wrong answer for 0 4686 // instruction. On pre-ARM5 hardware this routine gives the wrong answer for 0
4632 // (31 instead of 32). 4687 // (31 instead of 32).
4633 static void CountLeadingZeros( 4688 static void CountLeadingZeros(
4634 MacroAssembler* masm, 4689 MacroAssembler* masm,
4635 Register source, 4690 Register source,
4636 Register scratch, 4691 Register scratch,
(...skipping 1547 matching lines...) Expand 10 before | Expand all | Expand 10 after
6184 break; 6239 break;
6185 } 6240 }
6186 6241
6187 default: UNREACHABLE(); 6242 default: UNREACHABLE();
6188 } 6243 }
6189 // This code should be unreachable. 6244 // This code should be unreachable.
6190 __ stop("Unreachable"); 6245 __ stop("Unreachable");
6191 } 6246 }
6192 6247
6193 6248
6249 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) {
6250 return Handle<Code>::null();
6251 }
6252
6253
6194 void StackCheckStub::Generate(MacroAssembler* masm) { 6254 void StackCheckStub::Generate(MacroAssembler* masm) {
6195 // Do tail-call to runtime routine. Runtime routines expect at least one 6255 // Do tail-call to runtime routine. Runtime routines expect at least one
6196 // argument, so give it a Smi. 6256 // argument, so give it a Smi.
6197 __ mov(r0, Operand(Smi::FromInt(0))); 6257 __ mov(r0, Operand(Smi::FromInt(0)));
6198 __ push(r0); 6258 __ push(r0);
6199 __ TailCallRuntime(ExternalReference(Runtime::kStackGuard), 1, 1); 6259 __ TailCallRuntime(Runtime::kStackGuard, 1, 1);
6200 6260
6201 __ StubReturn(1); 6261 __ StubReturn(1);
6202 } 6262 }
6203 6263
6204 6264
6205 void GenericUnaryOpStub::Generate(MacroAssembler* masm) { 6265 void GenericUnaryOpStub::Generate(MacroAssembler* masm) {
6206 Label slow, done; 6266 Label slow, done;
6207 6267
6208 if (op_ == Token::SUB) { 6268 if (op_ == Token::SUB) {
6209 // Check whether the value is a smi. 6269 // Check whether the value is a smi.
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after
6798 // Read the argument from the adaptor frame and return it. 6858 // Read the argument from the adaptor frame and return it.
6799 __ sub(r3, r0, r1); 6859 __ sub(r3, r0, r1);
6800 __ add(r3, r2, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize)); 6860 __ add(r3, r2, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize));
6801 __ ldr(r0, MemOperand(r3, kDisplacement)); 6861 __ ldr(r0, MemOperand(r3, kDisplacement));
6802 __ Jump(lr); 6862 __ Jump(lr);
6803 6863
6804 // Slow-case: Handle non-smi or out-of-bounds access to arguments 6864 // Slow-case: Handle non-smi or out-of-bounds access to arguments
6805 // by calling the runtime system. 6865 // by calling the runtime system.
6806 __ bind(&slow); 6866 __ bind(&slow);
6807 __ push(r1); 6867 __ push(r1);
6808 __ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1, 1); 6868 __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1);
6809 } 6869 }
6810 6870
6811 6871
6812 void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) { 6872 void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) {
6813 // sp[0] : number of parameters 6873 // sp[0] : number of parameters
6814 // sp[4] : receiver displacement 6874 // sp[4] : receiver displacement
6815 // sp[8] : function 6875 // sp[8] : function
6816 6876
6817 // Check if the calling frame is an arguments adaptor frame. 6877 // Check if the calling frame is an arguments adaptor frame.
6818 Label adaptor_frame, try_allocate, runtime; 6878 Label adaptor_frame, try_allocate, runtime;
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
6901 __ cmp(r1, Operand(0)); 6961 __ cmp(r1, Operand(0));
6902 __ b(ne, &loop); 6962 __ b(ne, &loop);
6903 6963
6904 // Return and remove the on-stack parameters. 6964 // Return and remove the on-stack parameters.
6905 __ bind(&done); 6965 __ bind(&done);
6906 __ add(sp, sp, Operand(3 * kPointerSize)); 6966 __ add(sp, sp, Operand(3 * kPointerSize));
6907 __ Ret(); 6967 __ Ret();
6908 6968
6909 // Do the runtime call to allocate the arguments object. 6969 // Do the runtime call to allocate the arguments object.
6910 __ bind(&runtime); 6970 __ bind(&runtime);
6911 __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3, 1); 6971 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1);
6912 } 6972 }
6913 6973
6914 6974
6915 void CallFunctionStub::Generate(MacroAssembler* masm) { 6975 void CallFunctionStub::Generate(MacroAssembler* masm) {
6916 Label slow; 6976 Label slow;
6917 6977
6918 // If the receiver might be a value (string, number or boolean) check for this 6978 // If the receiver might be a value (string, number or boolean) check for this
6919 // and box it if it is. 6979 // and box it if it is.
6920 if (ReceiverMightBeValue()) { 6980 if (ReceiverMightBeValue()) {
6921 // Get the receiver from the stack. 6981 // Get the receiver from the stack.
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after
7192 __ cmp(dest, Operand(limit)); 7252 __ cmp(dest, Operand(limit));
7193 __ ldrb(scratch1, MemOperand(src, 1, PostIndex), lt); 7253 __ ldrb(scratch1, MemOperand(src, 1, PostIndex), lt);
7194 __ b(ge, &done); 7254 __ b(ge, &done);
7195 __ strb(scratch1, MemOperand(dest, 1, PostIndex)); 7255 __ strb(scratch1, MemOperand(dest, 1, PostIndex));
7196 __ b(&byte_loop); 7256 __ b(&byte_loop);
7197 7257
7198 __ bind(&done); 7258 __ bind(&done);
7199 } 7259 }
7200 7260
7201 7261
7262 void StringStubBase::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
7263 Register c1,
7264 Register c2,
7265 Register scratch1,
7266 Register scratch2,
7267 Register scratch3,
7268 Register scratch4,
7269 Register scratch5,
7270 Label* not_found) {
7271 // Register scratch3 is the general scratch register in this function.
7272 Register scratch = scratch3;
7273
7274 // Make sure that both characters are not digits as such strings has a
7275 // different hash algorithm. Don't try to look for these in the symbol table.
7276 Label not_array_index;
7277 __ sub(scratch, c1, Operand(static_cast<int>('0')));
7278 __ cmp(scratch, Operand(static_cast<int>('9' - '0')));
7279 __ b(hi, &not_array_index);
7280 __ sub(scratch, c2, Operand(static_cast<int>('0')));
7281 __ cmp(scratch, Operand(static_cast<int>('9' - '0')));
7282
7283 // If check failed combine both characters into single halfword.
7284 // This is required by the contract of the method: code at the
7285 // not_found branch expects this combination in c1 register
7286 __ orr(c1, c1, Operand(c2, LSL, kBitsPerByte), LeaveCC, ls);
7287 __ b(ls, not_found);
7288
7289 __ bind(&not_array_index);
7290 // Calculate the two character string hash.
7291 Register hash = scratch1;
7292 GenerateHashInit(masm, hash, c1);
7293 GenerateHashAddCharacter(masm, hash, c2);
7294 GenerateHashGetHash(masm, hash);
7295
7296 // Collect the two characters in a register.
7297 Register chars = c1;
7298 __ orr(chars, chars, Operand(c2, LSL, kBitsPerByte));
7299
7300 // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
7301 // hash: hash of two character string.
7302
7303 // Load symbol table
7304 // Load address of first element of the symbol table.
7305 Register symbol_table = c2;
7306 __ LoadRoot(symbol_table, Heap::kSymbolTableRootIndex);
7307
7308 // Load undefined value
7309 Register undefined = scratch4;
7310 __ LoadRoot(undefined, Heap::kUndefinedValueRootIndex);
7311
7312 // Calculate capacity mask from the symbol table capacity.
7313 Register mask = scratch2;
7314 __ ldr(mask, FieldMemOperand(symbol_table, SymbolTable::kCapacityOffset));
7315 __ mov(mask, Operand(mask, ASR, 1));
7316 __ sub(mask, mask, Operand(1));
7317
7318 // Calculate untagged address of the first element of the symbol table.
7319 Register first_symbol_table_element = symbol_table;
7320 __ add(first_symbol_table_element, symbol_table,
7321 Operand(SymbolTable::kElementsStartOffset - kHeapObjectTag));
7322
7323 // Registers
7324 // chars: two character string, char 1 in byte 0 and char 2 in byte 1.
7325 // hash: hash of two character string
7326 // mask: capacity mask
7327 // first_symbol_table_element: address of the first element of
7328 // the symbol table
7329 // scratch: -
7330
7331 // Perform a number of probes in the symbol table.
7332 static const int kProbes = 4;
7333 Label found_in_symbol_table;
7334 Label next_probe[kProbes];
7335 for (int i = 0; i < kProbes; i++) {
7336 Register candidate = scratch5; // Scratch register contains candidate.
7337
7338 // Calculate entry in symbol table.
7339 if (i > 0) {
7340 __ add(candidate, hash, Operand(SymbolTable::GetProbeOffset(i)));
7341 } else {
7342 __ mov(candidate, hash);
7343 }
7344
7345 __ and_(candidate, candidate, Operand(mask));
7346
7347 // Load the entry from the symble table.
7348 ASSERT_EQ(1, SymbolTable::kEntrySize);
7349 __ ldr(candidate,
7350 MemOperand(first_symbol_table_element,
7351 candidate,
7352 LSL,
7353 kPointerSizeLog2));
7354
7355 // If entry is undefined no string with this hash can be found.
7356 __ cmp(candidate, undefined);
7357 __ b(eq, not_found);
7358
7359 // If length is not 2 the string is not a candidate.
7360 __ ldr(scratch, FieldMemOperand(candidate, String::kLengthOffset));
7361 __ cmp(scratch, Operand(2));
7362 __ b(ne, &next_probe[i]);
7363
7364 // Check that the candidate is a non-external ascii string.
7365 __ ldr(scratch, FieldMemOperand(candidate, HeapObject::kMapOffset));
7366 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
7367 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch,
7368 &next_probe[i]);
7369
7370 // Check if the two characters match.
7371 // Assumes that word load is little endian.
7372 __ ldrh(scratch, FieldMemOperand(candidate, SeqAsciiString::kHeaderSize));
7373 __ cmp(chars, scratch);
7374 __ b(eq, &found_in_symbol_table);
7375 __ bind(&next_probe[i]);
7376 }
7377
7378 // No matching 2 character string found by probing.
7379 __ jmp(not_found);
7380
7381 // Scratch register contains result when we fall through to here.
7382 Register result = scratch;
7383 __ bind(&found_in_symbol_table);
7384 if (!result.is(r0)) {
7385 __ mov(r0, result);
7386 }
7387 }
7388
7389
7390 void StringStubBase::GenerateHashInit(MacroAssembler* masm,
7391 Register hash,
7392 Register character) {
7393 // hash = character + (character << 10);
7394 __ add(hash, character, Operand(character, LSL, 10));
7395 // hash ^= hash >> 6;
7396 __ eor(hash, hash, Operand(hash, ASR, 6));
7397 }
7398
7399
7400 void StringStubBase::GenerateHashAddCharacter(MacroAssembler* masm,
7401 Register hash,
7402 Register character) {
7403 // hash += character;
7404 __ add(hash, hash, Operand(character));
7405 // hash += hash << 10;
7406 __ add(hash, hash, Operand(hash, LSL, 10));
7407 // hash ^= hash >> 6;
7408 __ eor(hash, hash, Operand(hash, ASR, 6));
7409 }
7410
7411
7412 void StringStubBase::GenerateHashGetHash(MacroAssembler* masm,
7413 Register hash) {
7414 // hash += hash << 3;
7415 __ add(hash, hash, Operand(hash, LSL, 3));
7416 // hash ^= hash >> 11;
7417 __ eor(hash, hash, Operand(hash, ASR, 11));
7418 // hash += hash << 15;
7419 __ add(hash, hash, Operand(hash, LSL, 15), SetCC);
7420
7421 // if (hash == 0) hash = 27;
7422 __ mov(hash, Operand(27), LeaveCC, nz);
7423 }
7424
7425
7202 void SubStringStub::Generate(MacroAssembler* masm) { 7426 void SubStringStub::Generate(MacroAssembler* masm) {
7203 Label runtime; 7427 Label runtime;
7204 7428
7205 // Stack frame on entry. 7429 // Stack frame on entry.
7206 // lr: return address 7430 // lr: return address
7207 // sp[0]: to 7431 // sp[0]: to
7208 // sp[4]: from 7432 // sp[4]: from
7209 // sp[8]: string 7433 // sp[8]: string
7210 7434
7211 // This stub is called from the native-call %_SubString(...), so 7435 // This stub is called from the native-call %_SubString(...), so
(...skipping 15 matching lines...) Expand all
7227 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); 7451 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
7228 // I.e., arithmetic shift right by one un-smi-tags. 7452 // I.e., arithmetic shift right by one un-smi-tags.
7229 __ mov(r2, Operand(r7, ASR, 1), SetCC); 7453 __ mov(r2, Operand(r7, ASR, 1), SetCC);
7230 __ mov(r3, Operand(r6, ASR, 1), SetCC, cc); 7454 __ mov(r3, Operand(r6, ASR, 1), SetCC, cc);
7231 // If either r2 or r6 had the smi tag bit set, then carry is set now. 7455 // If either r2 or r6 had the smi tag bit set, then carry is set now.
7232 __ b(cs, &runtime); // Either "from" or "to" is not a smi. 7456 __ b(cs, &runtime); // Either "from" or "to" is not a smi.
7233 __ b(mi, &runtime); // From is negative. 7457 __ b(mi, &runtime); // From is negative.
7234 7458
7235 __ sub(r2, r2, Operand(r3), SetCC); 7459 __ sub(r2, r2, Operand(r3), SetCC);
7236 __ b(mi, &runtime); // Fail if from > to. 7460 __ b(mi, &runtime); // Fail if from > to.
7237 // Handle sub-strings of length 2 and less in the runtime system. 7461 // Special handling of sub-strings of length 1 and 2. One character strings
7462 // are handled in the runtime system (looked up in the single character
7463 // cache). Two character strings are looked for in the symbol cache.
7238 __ cmp(r2, Operand(2)); 7464 __ cmp(r2, Operand(2));
7239 __ b(le, &runtime); 7465 __ b(lt, &runtime);
7240 7466
7241 // r2: length 7467 // r2: length
7468 // r3: from index (untaged smi)
7242 // r6: from (smi) 7469 // r6: from (smi)
7243 // r7: to (smi) 7470 // r7: to (smi)
7244 7471
7245 // Make sure first argument is a sequential (or flat) string. 7472 // Make sure first argument is a sequential (or flat) string.
7246 __ ldr(r5, MemOperand(sp, kStringOffset)); 7473 __ ldr(r5, MemOperand(sp, kStringOffset));
7247 ASSERT_EQ(0, kSmiTag); 7474 ASSERT_EQ(0, kSmiTag);
7248 __ tst(r5, Operand(kSmiTagMask)); 7475 __ tst(r5, Operand(kSmiTagMask));
7249 __ b(eq, &runtime); 7476 __ b(eq, &runtime);
7250 Condition is_string = masm->IsObjectStringType(r5, r1); 7477 Condition is_string = masm->IsObjectStringType(r5, r1);
7251 __ b(NegateCondition(is_string), &runtime); 7478 __ b(NegateCondition(is_string), &runtime);
7252 7479
7253 // r1: instance type 7480 // r1: instance type
7254 // r2: length 7481 // r2: length
7482 // r3: from index (untaged smi)
7255 // r5: string 7483 // r5: string
7256 // r6: from (smi) 7484 // r6: from (smi)
7257 // r7: to (smi) 7485 // r7: to (smi)
7258 Label seq_string; 7486 Label seq_string;
7259 __ and_(r4, r1, Operand(kStringRepresentationMask)); 7487 __ and_(r4, r1, Operand(kStringRepresentationMask));
7260 ASSERT(kSeqStringTag < kConsStringTag); 7488 ASSERT(kSeqStringTag < kConsStringTag);
7261 ASSERT(kExternalStringTag > kConsStringTag); 7489 ASSERT(kExternalStringTag > kConsStringTag);
7262 __ cmp(r4, Operand(kConsStringTag)); 7490 __ cmp(r4, Operand(kConsStringTag));
7263 __ b(gt, &runtime); // External strings go to runtime. 7491 __ b(gt, &runtime); // External strings go to runtime.
7264 __ b(lt, &seq_string); // Sequential strings are handled directly. 7492 __ b(lt, &seq_string); // Sequential strings are handled directly.
7265 7493
7266 // Cons string. Try to recurse (once) on the first substring. 7494 // Cons string. Try to recurse (once) on the first substring.
7267 // (This adds a little more generality than necessary to handle flattened 7495 // (This adds a little more generality than necessary to handle flattened
7268 // cons strings, but not much). 7496 // cons strings, but not much).
7269 __ ldr(r5, FieldMemOperand(r5, ConsString::kFirstOffset)); 7497 __ ldr(r5, FieldMemOperand(r5, ConsString::kFirstOffset));
7270 __ ldr(r4, FieldMemOperand(r5, HeapObject::kMapOffset)); 7498 __ ldr(r4, FieldMemOperand(r5, HeapObject::kMapOffset));
7271 __ ldrb(r1, FieldMemOperand(r4, Map::kInstanceTypeOffset)); 7499 __ ldrb(r1, FieldMemOperand(r4, Map::kInstanceTypeOffset));
7272 __ tst(r1, Operand(kStringRepresentationMask)); 7500 __ tst(r1, Operand(kStringRepresentationMask));
7273 ASSERT_EQ(0, kSeqStringTag); 7501 ASSERT_EQ(0, kSeqStringTag);
7274 __ b(ne, &runtime); // Cons and External strings go to runtime. 7502 __ b(ne, &runtime); // Cons and External strings go to runtime.
7275 7503
7276 // Definitly a sequential string. 7504 // Definitly a sequential string.
7277 __ bind(&seq_string); 7505 __ bind(&seq_string);
7278 7506
7279 // r1: instance type. 7507 // r1: instance type.
7280 // r2: length 7508 // r2: length
7509 // r3: from index (untaged smi)
7281 // r5: string 7510 // r5: string
7282 // r6: from (smi) 7511 // r6: from (smi)
7283 // r7: to (smi) 7512 // r7: to (smi)
7284 __ ldr(r4, FieldMemOperand(r5, String::kLengthOffset)); 7513 __ ldr(r4, FieldMemOperand(r5, String::kLengthOffset));
7285 __ cmp(r4, Operand(r7, ASR, 1)); 7514 __ cmp(r4, Operand(r7, ASR, 1));
7286 __ b(lt, &runtime); // Fail if to > length. 7515 __ b(lt, &runtime); // Fail if to > length.
7287 7516
7288 // r1: instance type. 7517 // r1: instance type.
7289 // r2: result string length. 7518 // r2: result string length.
7519 // r3: from index (untaged smi)
7290 // r5: string. 7520 // r5: string.
7291 // r6: from offset (smi) 7521 // r6: from offset (smi)
7292 // Check for flat ascii string. 7522 // Check for flat ascii string.
7293 Label non_ascii_flat; 7523 Label non_ascii_flat;
7294 __ tst(r1, Operand(kStringEncodingMask)); 7524 __ tst(r1, Operand(kStringEncodingMask));
7295 ASSERT_EQ(0, kTwoByteStringTag); 7525 ASSERT_EQ(0, kTwoByteStringTag);
7296 __ b(eq, &non_ascii_flat); 7526 __ b(eq, &non_ascii_flat);
7297 7527
7528 Label result_longer_than_two;
7529 __ cmp(r2, Operand(2));
7530 __ b(gt, &result_longer_than_two);
7531
7532 // Sub string of length 2 requested.
7533 // Get the two characters forming the sub string.
7534 __ add(r5, r5, Operand(r3));
7535 __ ldrb(r3, FieldMemOperand(r5, SeqAsciiString::kHeaderSize));
7536 __ ldrb(r4, FieldMemOperand(r5, SeqAsciiString::kHeaderSize + 1));
7537
7538 // Try to lookup two character string in symbol table.
7539 Label make_two_character_string;
7540 GenerateTwoCharacterSymbolTableProbe(masm, r3, r4, r1, r5, r6, r7, r9,
7541 &make_two_character_string);
7542 __ IncrementCounter(&Counters::sub_string_native, 1, r3, r4);
7543 __ add(sp, sp, Operand(3 * kPointerSize));
7544 __ Ret();
7545
7546 // r2: result string length.
7547 // r3: two characters combined into halfword in little endian byte order.
7548 __ bind(&make_two_character_string);
7549 __ AllocateAsciiString(r0, r2, r4, r5, r9, &runtime);
7550 __ strh(r3, FieldMemOperand(r0, SeqAsciiString::kHeaderSize));
7551 __ IncrementCounter(&Counters::sub_string_native, 1, r3, r4);
7552 __ add(sp, sp, Operand(3 * kPointerSize));
7553 __ Ret();
7554
7555 __ bind(&result_longer_than_two);
7556
7298 // Allocate the result. 7557 // Allocate the result.
7299 __ AllocateAsciiString(r0, r2, r3, r4, r1, &runtime); 7558 __ AllocateAsciiString(r0, r2, r3, r4, r1, &runtime);
7300 7559
7301 // r0: result string. 7560 // r0: result string.
7302 // r2: result string length. 7561 // r2: result string length.
7303 // r5: string. 7562 // r5: string.
7304 // r6: from offset (smi) 7563 // r6: from offset (smi)
7305 // Locate first character of result. 7564 // Locate first character of result.
7306 __ add(r1, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 7565 __ add(r1, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
7307 // Locate 'from' character of string. 7566 // Locate 'from' character of string.
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
7345 // r5: first character of string to copy. 7604 // r5: first character of string to copy.
7346 ASSERT_EQ(0, SeqTwoByteString::kHeaderSize & kObjectAlignmentMask); 7605 ASSERT_EQ(0, SeqTwoByteString::kHeaderSize & kObjectAlignmentMask);
7347 GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, r9, 7606 GenerateCopyCharactersLong(masm, r1, r5, r2, r3, r4, r6, r7, r9,
7348 DEST_ALWAYS_ALIGNED); 7607 DEST_ALWAYS_ALIGNED);
7349 __ IncrementCounter(&Counters::sub_string_native, 1, r3, r4); 7608 __ IncrementCounter(&Counters::sub_string_native, 1, r3, r4);
7350 __ add(sp, sp, Operand(3 * kPointerSize)); 7609 __ add(sp, sp, Operand(3 * kPointerSize));
7351 __ Ret(); 7610 __ Ret();
7352 7611
7353 // Just jump to runtime to create the sub string. 7612 // Just jump to runtime to create the sub string.
7354 __ bind(&runtime); 7613 __ bind(&runtime);
7355 __ TailCallRuntime(ExternalReference(Runtime::kSubString), 3, 1); 7614 __ TailCallRuntime(Runtime::kSubString, 3, 1);
7356 } 7615 }
7357 7616
7358 7617
7359 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, 7618 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
7360 Register left, 7619 Register left,
7361 Register right, 7620 Register right,
7362 Register scratch1, 7621 Register scratch1,
7363 Register scratch2, 7622 Register scratch2,
7364 Register scratch3, 7623 Register scratch3,
7365 Register scratch4) { 7624 Register scratch4) {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
7436 __ JumpIfNotBothSequentialAsciiStrings(r0, r1, r2, r3, &runtime); 7695 __ JumpIfNotBothSequentialAsciiStrings(r0, r1, r2, r3, &runtime);
7437 7696
7438 // Compare flat ascii strings natively. Remove arguments from stack first. 7697 // Compare flat ascii strings natively. Remove arguments from stack first.
7439 __ IncrementCounter(&Counters::string_compare_native, 1, r2, r3); 7698 __ IncrementCounter(&Counters::string_compare_native, 1, r2, r3);
7440 __ add(sp, sp, Operand(2 * kPointerSize)); 7699 __ add(sp, sp, Operand(2 * kPointerSize));
7441 GenerateCompareFlatAsciiStrings(masm, r0, r1, r2, r3, r4, r5); 7700 GenerateCompareFlatAsciiStrings(masm, r0, r1, r2, r3, r4, r5);
7442 7701
7443 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 7702 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
7444 // tagged as a small integer. 7703 // tagged as a small integer.
7445 __ bind(&runtime); 7704 __ bind(&runtime);
7446 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1); 7705 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
7447 } 7706 }
7448 7707
7449 7708
7450 void StringAddStub::Generate(MacroAssembler* masm) { 7709 void StringAddStub::Generate(MacroAssembler* masm) {
7451 Label string_add_runtime; 7710 Label string_add_runtime;
7452 // Stack on entry: 7711 // Stack on entry:
7453 // sp[0]: second argument. 7712 // sp[0]: second argument.
7454 // sp[4]: first argument. 7713 // sp[4]: first argument.
7455 7714
7456 // Load the two arguments. 7715 // Load the two arguments.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
7496 } 7755 }
7497 7756
7498 // Both strings are non-empty. 7757 // Both strings are non-empty.
7499 // r0: first string 7758 // r0: first string
7500 // r1: second string 7759 // r1: second string
7501 // r2: length of first string 7760 // r2: length of first string
7502 // r3: length of second string 7761 // r3: length of second string
7503 // r4: first string instance type (if string_check_) 7762 // r4: first string instance type (if string_check_)
7504 // r5: second string instance type (if string_check_) 7763 // r5: second string instance type (if string_check_)
7505 // Look at the length of the result of adding the two strings. 7764 // Look at the length of the result of adding the two strings.
7506 Label string_add_flat_result; 7765 Label string_add_flat_result, longer_than_two;
7507 // Adding two lengths can't overflow. 7766 // Adding two lengths can't overflow.
7508 ASSERT(String::kMaxLength * 2 > String::kMaxLength); 7767 ASSERT(String::kMaxLength * 2 > String::kMaxLength);
7509 __ add(r6, r2, Operand(r3)); 7768 __ add(r6, r2, Operand(r3));
7510 // Use the runtime system when adding two one character strings, as it 7769 // Use the runtime system when adding two one character strings, as it
7511 // contains optimizations for this specific case using the symbol table. 7770 // contains optimizations for this specific case using the symbol table.
7512 __ cmp(r6, Operand(2)); 7771 __ cmp(r6, Operand(2));
7513 __ b(eq, &string_add_runtime); 7772 __ b(ne, &longer_than_two);
7773
7774 // Check that both strings are non-external ascii strings.
7775 if (!string_check_) {
7776 __ ldr(r4, FieldMemOperand(r0, HeapObject::kMapOffset));
7777 __ ldr(r5, FieldMemOperand(r1, HeapObject::kMapOffset));
7778 __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset));
7779 __ ldrb(r5, FieldMemOperand(r5, Map::kInstanceTypeOffset));
7780 }
7781 __ JumpIfBothInstanceTypesAreNotSequentialAscii(r4, r5, r6, r7,
7782 &string_add_runtime);
7783
7784 // Get the two characters forming the sub string.
7785 __ ldrb(r2, FieldMemOperand(r0, SeqAsciiString::kHeaderSize));
7786 __ ldrb(r3, FieldMemOperand(r1, SeqAsciiString::kHeaderSize));
7787
7788 // Try to lookup two character string in symbol table. If it is not found
7789 // just allocate a new one.
7790 Label make_two_character_string;
7791 GenerateTwoCharacterSymbolTableProbe(masm, r2, r3, r6, r7, r4, r5, r9,
7792 &make_two_character_string);
7793 __ IncrementCounter(&Counters::string_add_native, 1, r2, r3);
7794 __ add(sp, sp, Operand(2 * kPointerSize));
7795 __ Ret();
7796
7797 __ bind(&make_two_character_string);
7798 // Resulting string has length 2 and first chars of two strings
7799 // are combined into single halfword in r2 register.
7800 // So we can fill resulting string without two loops by a single
7801 // halfword store instruction (which assumes that processor is
7802 // in a little endian mode)
7803 __ mov(r6, Operand(2));
7804 __ AllocateAsciiString(r0, r6, r4, r5, r9, &string_add_runtime);
7805 __ strh(r2, FieldMemOperand(r0, SeqAsciiString::kHeaderSize));
7806 __ IncrementCounter(&Counters::string_add_native, 1, r2, r3);
7807 __ add(sp, sp, Operand(2 * kPointerSize));
7808 __ Ret();
7809
7810 __ bind(&longer_than_two);
7514 // Check if resulting string will be flat. 7811 // Check if resulting string will be flat.
7515 __ cmp(r6, Operand(String::kMinNonFlatLength)); 7812 __ cmp(r6, Operand(String::kMinNonFlatLength));
7516 __ b(lt, &string_add_flat_result); 7813 __ b(lt, &string_add_flat_result);
7517 // Handle exceptionally long strings in the runtime system. 7814 // Handle exceptionally long strings in the runtime system.
7518 ASSERT((String::kMaxLength & 0x80000000) == 0); 7815 ASSERT((String::kMaxLength & 0x80000000) == 0);
7519 ASSERT(IsPowerOf2(String::kMaxLength + 1)); 7816 ASSERT(IsPowerOf2(String::kMaxLength + 1));
7520 // kMaxLength + 1 is representable as shifted literal, kMaxLength is not. 7817 // kMaxLength + 1 is representable as shifted literal, kMaxLength is not.
7521 __ cmp(r6, Operand(String::kMaxLength + 1)); 7818 __ cmp(r6, Operand(String::kMaxLength + 1));
7522 __ b(hs, &string_add_runtime); 7819 __ b(hs, &string_add_runtime);
7523 7820
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
7582 ASSERT(IsPowerOf2(kStringEncodingMask)); // Just one bit to test. 7879 ASSERT(IsPowerOf2(kStringEncodingMask)); // Just one bit to test.
7583 __ eor(r7, r4, Operand(r5)); 7880 __ eor(r7, r4, Operand(r5));
7584 __ tst(r7, Operand(kStringEncodingMask)); 7881 __ tst(r7, Operand(kStringEncodingMask));
7585 __ b(ne, &string_add_runtime); 7882 __ b(ne, &string_add_runtime);
7586 // And see if it's ASCII or two-byte. 7883 // And see if it's ASCII or two-byte.
7587 __ tst(r4, Operand(kStringEncodingMask)); 7884 __ tst(r4, Operand(kStringEncodingMask));
7588 __ b(eq, &non_ascii_string_add_flat_result); 7885 __ b(eq, &non_ascii_string_add_flat_result);
7589 7886
7590 // Both strings are sequential ASCII strings. We also know that they are 7887 // Both strings are sequential ASCII strings. We also know that they are
7591 // short (since the sum of the lengths is less than kMinNonFlatLength). 7888 // short (since the sum of the lengths is less than kMinNonFlatLength).
7889 // r6: length of resulting flat string
7592 __ AllocateAsciiString(r7, r6, r4, r5, r9, &string_add_runtime); 7890 __ AllocateAsciiString(r7, r6, r4, r5, r9, &string_add_runtime);
7593 // Locate first character of result. 7891 // Locate first character of result.
7594 __ add(r6, r7, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 7892 __ add(r6, r7, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
7595 // Locate first character of first argument. 7893 // Locate first character of first argument.
7596 __ add(r0, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 7894 __ add(r0, r0, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
7597 // r0: first character of first string. 7895 // r0: first character of first string.
7598 // r1: second string. 7896 // r1: second string.
7599 // r2: length of first string. 7897 // r2: length of first string.
7600 // r3: length of second string. 7898 // r3: length of second string.
7601 // r6: first character of result. 7899 // r6: first character of result.
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
7650 // r7: result string. 7948 // r7: result string.
7651 GenerateCopyCharacters(masm, r6, r1, r3, r4, false); 7949 GenerateCopyCharacters(masm, r6, r1, r3, r4, false);
7652 7950
7653 __ mov(r0, Operand(r7)); 7951 __ mov(r0, Operand(r7));
7654 __ IncrementCounter(&Counters::string_add_native, 1, r2, r3); 7952 __ IncrementCounter(&Counters::string_add_native, 1, r2, r3);
7655 __ add(sp, sp, Operand(2 * kPointerSize)); 7953 __ add(sp, sp, Operand(2 * kPointerSize));
7656 __ Ret(); 7954 __ Ret();
7657 7955
7658 // Just jump to runtime to add the two strings. 7956 // Just jump to runtime to add the two strings.
7659 __ bind(&string_add_runtime); 7957 __ bind(&string_add_runtime);
7660 __ TailCallRuntime(ExternalReference(Runtime::kStringAdd), 2, 1); 7958 __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
7661 } 7959 }
7662 7960
7663 7961
7664 #undef __ 7962 #undef __
7665 7963
7666 } } // namespace v8::internal 7964 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/codegen-arm.h ('k') | src/arm/fast-codegen-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698