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

Side by Side Diff: src/sh4/full-codegen-sh4.cc

Issue 11275184: First draft of the sh4 port Base URL: http://github.com/v8/v8.git@master
Patch Set: Use GYP and fixe some typos Created 8 years, 1 month 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
« no previous file with comments | « src/sh4/frames-sh4.cc ('k') | src/sh4/ic-sh4.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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2011-2012 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
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
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 #if defined(V8_TARGET_ARCH_ARM) 30 #if defined(V8_TARGET_ARCH_SH4)
31 31
32 #include "code-stubs.h" 32 #include "code-stubs.h"
33 #include "codegen.h" 33 #include "codegen.h"
34 #include "compiler.h" 34 #include "compiler.h"
35 #include "debug.h" 35 #include "debug.h"
36 #include "full-codegen.h" 36 #include "full-codegen.h"
37 #include "isolate-inl.h" 37 #include "isolate-inl.h"
38 #include "parser.h" 38 #include "parser.h"
39 #include "scopes.h" 39 #include "scopes.h"
40 #include "stub-cache.h" 40 #include "stub-cache.h"
41 41
42 #include "arm/code-stubs-arm.h" 42 #include "sh4/code-stubs-sh4.h"
43 #include "arm/macro-assembler-arm.h" 43 #include "sh4/macro-assembler-sh4.h"
44 44
45 namespace v8 { 45 namespace v8 {
46 namespace internal { 46 namespace internal {
47 47
48 #define __ ACCESS_MASM(masm_) 48 #define __ ACCESS_MASM(masm_)
49 49
50 #include "map-sh4.h" // For ARM -> SH4 register mapping
51
50 52
51 // A patch site is a location in the code which it is possible to patch. This 53 // A patch site is a location in the code which it is possible to patch. This
52 // class has a number of methods to emit the code which is patchable and the 54 // class has a number of methods to emit the code which is patchable and the
53 // method EmitPatchInfo to record a marker back to the patchable code. This 55 // method EmitPatchInfo to record a marker back to the patchable code.
54 // marker is a cmp rx, #yyy instruction, and x * 0x00000fff + yyy (raw 12 bit 56 // On SH4 this marker is a cmp #ii, r0 operation, this limits the range
55 // immediate value is used) is the delta from the pc to the first instruction of 57 // of #ii to -128..+127 instructions for the distance betwen the patch and
56 // the patchable code. 58 // the label.
59 // The #ii (8 bits signed value) is the delta from the pc to
60 // the first instruction of the patchable code.
57 class JumpPatchSite BASE_EMBEDDED { 61 class JumpPatchSite BASE_EMBEDDED {
58 public: 62 public:
59 explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) { 63 explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) {
60 #ifdef DEBUG 64 #ifdef DEBUG
61 info_emitted_ = false; 65 info_emitted_ = false;
66 ASSERT(!patch_site_.is_bound());
62 #endif 67 #endif
63 } 68 }
64 69
65 ~JumpPatchSite() { 70 ~JumpPatchSite() {
66 ASSERT(patch_site_.is_bound() == info_emitted_); 71 ASSERT(patch_site_.is_bound() == info_emitted_);
67 } 72 }
68 73
69 // When initially emitting this ensure that a jump is always generated to skip 74 // When initially emitting this ensure that a jump is always generated to skip
70 // the inlined smi code. 75 // the inlined smi code.
71 void EmitJumpIfNotSmi(Register reg, Label* target) { 76 void EmitJumpIfNotSmi(Register reg, Label* target) {
72 ASSERT(!patch_site_.is_bound() && !info_emitted_); 77 ASSERT(!patch_site_.is_bound() && !info_emitted_);
73 Assembler::BlockConstPoolScope block_const_pool(masm_); 78 // For the current unbound branch sequence (in assembler_sh4.cc)
79 // to be simple to patch, we force the alignment now, such that the
80 // first instruction of the sequence after the cmp is a branch.
81 __ align();
82 __ mov(sh4_ip, Operand(kSmiTagMask));
74 __ bind(&patch_site_); 83 __ bind(&patch_site_);
75 __ cmp(reg, Operand(reg)); 84 __ cmp(reg, reg);
85 // Don't use b(al, ...) as that might emit the constant pool right after the
86 // branch. After patching when the branch is no longer unconditional
87 // execution can continue into the constant pool.
88 // Also for the later patch in PatchInlinedSmiCode, we require
89 // that the target is not bound yet.
90 ASSERT(!target->is_bound());
91 ASSERT(masm_->pc_offset() % 4 == 0);
76 __ b(eq, target); // Always taken before patched. 92 __ b(eq, target); // Always taken before patched.
77 } 93 }
78 94
79 // When initially emitting this ensure that a jump is never generated to skip 95 // When initially emitting this ensure that a jump is never generated to skip
80 // the inlined smi code. 96 // the inlined smi code.
81 void EmitJumpIfSmi(Register reg, Label* target) { 97 void EmitJumpIfSmi(Register reg, Label* target) {
82 ASSERT(!patch_site_.is_bound() && !info_emitted_); 98 ASSERT(!patch_site_.is_bound() && !info_emitted_);
83 Assembler::BlockConstPoolScope block_const_pool(masm_); 99 __ align();
100 __ mov(sh4_ip, Operand(kSmiTagMask));
84 __ bind(&patch_site_); 101 __ bind(&patch_site_);
85 __ cmp(reg, Operand(reg)); 102 __ cmp(reg, reg);
86 __ b(ne, target); // Never taken before patched. 103 ASSERT(!target->is_bound());
104 ASSERT(masm_->pc_offset() % 4 == 0);
105 __ bf(target); // Never taken before patched.
87 } 106 }
88 107
89 void EmitPatchInfo() { 108 void EmitPatchInfo() {
90 // Block literal pool emission whilst recording patch site information.
91 Assembler::BlockConstPoolScope block_const_pool(masm_);
92 if (patch_site_.is_bound()) { 109 if (patch_site_.is_bound()) {
93 int delta_to_patch_site = masm_->InstructionsGeneratedSince(&patch_site_); 110 int delta_to_patch_site = masm_->InstructionsGeneratedSince(&patch_site_);
94 Register reg; 111 ASSERT(delta_to_patch_site >= 0);
95 reg.set_code(delta_to_patch_site / kOff12Mask); 112 // Ensure that the delta fits into the raw immediate.
96 __ cmp_raw_immediate(reg, delta_to_patch_site % kOff12Mask); 113 ASSERT(masm_->fits_cmp_unsigned_imm(delta_to_patch_site));
114 __ cmpeq_r0_unsigned_imm(delta_to_patch_site);
97 #ifdef DEBUG 115 #ifdef DEBUG
98 info_emitted_ = true; 116 info_emitted_ = true;
99 #endif 117 #endif
100 } else { 118 } else {
101 __ nop(); // Signals no inlined code.
102 } 119 }
103 } 120 }
104 121
122 bool is_bound() const { return patch_site_.is_bound(); }
123
105 private: 124 private:
106 MacroAssembler* masm_; 125 MacroAssembler* masm_;
107 Label patch_site_; 126 Label patch_site_;
108 #ifdef DEBUG 127 #ifdef DEBUG
109 bool info_emitted_; 128 bool info_emitted_;
110 #endif 129 #endif
111 }; 130 };
112 131
113 132
114 // Generate code for a JS function. On entry to the function the receiver 133 // Generate code for a JS function. On entry to the function the receiver
115 // and arguments have been pushed on the stack left to right. The actual 134 // and arguments have been pushed on the stack left to right. The actual
116 // argument count matches the formal parameter count expected by the 135 // argument count matches the formal parameter count expected by the
117 // function. 136 // function.
118 // 137 //
119 // The live registers are: 138 // The live registers are:
120 // o r1: the JS function object being called (i.e., ourselves) 139 // o r1: the JS function object being called (i.e., ourselves)
121 // o cp: our context 140 // o cp: our context
122 // o fp: our caller's frame pointer 141 // o fp: our caller's frame pointer
123 // o sp: stack pointer 142 // o sp: stack pointer
124 // o lr: return address 143 // o pr: return address
125 // 144 //
126 // The function builds a JS frame. Please see JavaScriptFrameConstants in 145 // The function builds a JS frame. Please see JavaScriptFrameConstants in
127 // frames-arm.h for its layout. 146 // frames-arm.h for its layout.
128 void FullCodeGenerator::Generate() { 147 void FullCodeGenerator::Generate() {
129 CompilationInfo* info = info_; 148 CompilationInfo* info = info_;
130 handler_table_ = 149 handler_table_ =
131 isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED); 150 isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
132 profiling_counter_ = isolate()->factory()->NewJSGlobalPropertyCell( 151 profiling_counter_ = isolate()->factory()->NewJSGlobalPropertyCell(
133 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget))); 152 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget)));
134 SetFunctionPosition(function()); 153 SetFunctionPosition(function());
135 Comment cmnt(masm_, "[ function compiled by full code generator"); 154 Comment cmnt(masm_, "[ function compiled by full code generator");
136 155
137 ProfileEntryHookStub::MaybeCallEntryHook(masm_); 156 ProfileEntryHookStub::MaybeCallEntryHook(masm_);
138 157
139 #ifdef DEBUG 158 #ifdef DEBUG
140 if (strlen(FLAG_stop_at) > 0 && 159 if (strlen(FLAG_stop_at) > 0 &&
141 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) { 160 info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
142 __ stop("stop-at"); 161 __ stop("stop-at");
143 } 162 }
144 #endif 163 #endif
145 164
146 // Strict mode functions and builtins need to replace the receiver 165 // Strict mode functions and builtins need to replace the receiver
147 // with undefined when called as functions (without an explicit 166 // with undefined when called as functions (without an explicit
148 // receiver object). r5 is zero for method calls and non-zero for 167 // receiver object). r5 is zero for method calls and non-zero for
149 // function calls. 168 // function calls.
150 if (!info->is_classic_mode() || info->is_native()) { 169 if (!info->is_classic_mode() || info->is_native()) {
151 Label ok; 170 Label ok;
152 __ cmp(r5, Operand(0)); 171 __ cmp(r5, Operand(0));
153 __ b(eq, &ok); 172 __ b(eq, &ok, Label::kNear);
154 int receiver_offset = info->scope()->num_parameters() * kPointerSize; 173 int receiver_offset = info->scope()->num_parameters() * kPointerSize;
155 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); 174 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
156 __ str(r2, MemOperand(sp, receiver_offset)); 175 __ str(r2, MemOperand(sp, receiver_offset));
157 __ bind(&ok); 176 __ bind(&ok);
158 } 177 }
159 178
160 // Open a frame scope to indicate that there is a frame on the stack. The 179 // Open a frame scope to indicate that there is a frame on the stack. The
161 // MANUAL indicates that the scope shouldn't actually generate code to set up 180 // MANUAL indicates that the scope shouldn't actually generate code to set up
162 // the frame (that is done below). 181 // the frame (that is done below).
163 FrameScope frame_scope(masm_, StackFrame::MANUAL); 182 FrameScope frame_scope(masm_, StackFrame::MANUAL);
164 183
165 int locals_count = info->scope()->num_stack_slots(); 184 int locals_count = info->scope()->num_stack_slots();
166 185
167 __ Push(lr, fp, cp, r1); 186 __ Push(pr, fp, cp, r1);
168 if (locals_count > 0) { 187 if (locals_count > 0) {
169 // Load undefined value here, so the value is ready for the loop 188 // Load undefined value here, so the value is ready for the loop
170 // below. 189 // below.
171 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 190 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
172 } 191 }
173 // Adjust fp to point to caller's fp. 192 // Adjust fp to point to caller's fp.
174 __ add(fp, sp, Operand(2 * kPointerSize)); 193 __ add(fp, sp, Operand(2 * kPointerSize));
175 194
176 { Comment cmnt(masm_, "[ Allocate locals"); 195 { Comment cmnt(masm_, "[ Allocate locals");
177 for (int i = 0; i < locals_count; i++) { 196 for (int i = 0; i < locals_count; i++) {
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED); 297 ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED);
279 VisitVariableDeclaration(function); 298 VisitVariableDeclaration(function);
280 } 299 }
281 VisitDeclarations(scope()->declarations()); 300 VisitDeclarations(scope()->declarations());
282 } 301 }
283 302
284 { Comment cmnt(masm_, "[ Stack check"); 303 { Comment cmnt(masm_, "[ Stack check");
285 PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS); 304 PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
286 Label ok; 305 Label ok;
287 __ LoadRoot(ip, Heap::kStackLimitRootIndex); 306 __ LoadRoot(ip, Heap::kStackLimitRootIndex);
288 __ cmp(sp, Operand(ip)); 307 __ cmphs(sp, ip);
289 __ b(hs, &ok); 308 __ bt_near(&ok);
290 PredictableCodeSizeScope predictable(masm_);
291 StackCheckStub stub; 309 StackCheckStub stub;
292 __ CallStub(&stub); 310 __ CallStub(&stub);
293 __ bind(&ok); 311 __ bind(&ok);
294 } 312 }
295 313
296 { Comment cmnt(masm_, "[ Body"); 314 { Comment cmnt(masm_, "[ Body");
297 ASSERT(loop_depth() == 0); 315 ASSERT(loop_depth() == 0);
298 VisitStatements(function()->body()); 316 VisitStatements(function()->body());
299 ASSERT(loop_depth() == 0); 317 ASSERT(loop_depth() == 0);
300 } 318 }
301 } 319 }
302 320
303 // Always emit a 'return undefined' in case control fell off the end of 321 // Always emit a 'return undefined' in case control fell off the end of
304 // the body. 322 // the body.
305 { Comment cmnt(masm_, "[ return <undefined>;"); 323 { Comment cmnt(masm_, "[ return <undefined>;");
306 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 324 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
307 } 325 }
308 EmitReturnSequence(); 326 EmitReturnSequence();
309 327
328 // TODO(stm): implement this when const pool are active
310 // Force emit the constant pool, so it doesn't get emitted in the middle 329 // Force emit the constant pool, so it doesn't get emitted in the middle
311 // of the stack check table. 330 // of the stack check table.
312 masm()->CheckConstPool(true, false); 331 // masm()->CheckConstPool(true, false);
313 } 332 }
314 333
315 334
316 void FullCodeGenerator::ClearAccumulator() { 335 void FullCodeGenerator::ClearAccumulator() {
317 __ mov(r0, Operand(Smi::FromInt(0))); 336 __ mov(r0, Operand(Smi::FromInt(0)));
318 } 337 }
319 338
320 339
321 void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) { 340 void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
322 __ mov(r2, Operand(profiling_counter_)); 341 __ mov(r2, Operand(profiling_counter_));
323 __ ldr(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset)); 342 __ ldr(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
324 __ sub(r3, r3, Operand(Smi::FromInt(delta)), SetCC); 343 __ sub(r3, r3, Operand(Smi::FromInt(delta)));
344 __ cmpge(r3, Operand(0));
325 __ str(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset)); 345 __ str(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
326 } 346 }
327 347
328 348
329 void FullCodeGenerator::EmitProfilingCounterReset() { 349 void FullCodeGenerator::EmitProfilingCounterReset() {
330 int reset_value = FLAG_interrupt_budget; 350 int reset_value = FLAG_interrupt_budget;
331 if (info_->ShouldSelfOptimize() && !FLAG_retry_self_opt) { 351 if (info_->ShouldSelfOptimize() && !FLAG_retry_self_opt) {
332 // Self-optimization is a one-off thing: if it fails, don't try again. 352 // Self-optimization is a one-off thing: if it fails, don't try again.
333 reset_value = Smi::kMaxValue; 353 reset_value = Smi::kMaxValue;
334 } 354 }
335 if (isolate()->IsDebuggerActive()) { 355 if (isolate()->IsDebuggerActive()) {
336 // Detect debug break requests as soon as possible. 356 // Detect debug break requests as soon as possible.
337 reset_value = FLAG_interrupt_budget >> 4; 357 reset_value = FLAG_interrupt_budget >> 4;
338 } 358 }
339 __ mov(r2, Operand(profiling_counter_)); 359 __ mov(r2, Operand(profiling_counter_));
340 __ mov(r3, Operand(Smi::FromInt(reset_value))); 360 __ mov(r3, Operand(Smi::FromInt(reset_value)));
341 __ str(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset)); 361 __ str(r3, FieldMemOperand(r2, JSGlobalPropertyCell::kValueOffset));
342 } 362 }
343 363
344 364
345 void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt, 365 void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt,
346 Label* back_edge_target) { 366 Label* back_edge_target) {
347 Comment cmnt(masm_, "[ Stack check"); 367 Comment cmnt(masm_, "[ Stack check");
348 // Block literal pools whilst emitting stack check code.
349 Assembler::BlockConstPoolScope block_const_pool(masm_);
350 Label ok; 368 Label ok;
351 369
352 if (FLAG_count_based_interrupts) { 370 if (FLAG_count_based_interrupts) {
353 int weight = 1; 371 int weight = 1;
354 if (FLAG_weighted_back_edges) { 372 if (FLAG_weighted_back_edges) {
355 ASSERT(back_edge_target->is_bound()); 373 ASSERT(back_edge_target->is_bound());
356 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); 374 int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target);
357 weight = Min(kMaxBackEdgeWeight, 375 weight = Min(kMaxBackEdgeWeight,
358 Max(1, distance / kBackEdgeDistanceUnit)); 376 Max(1, distance / kBackEdgeDistanceUnit));
359 } 377 }
360 EmitProfilingCounterDecrement(weight); 378 EmitProfilingCounterDecrement(weight);
361 __ b(pl, &ok); 379 __ bt(&ok); // TODO(STM): ??
362 InterruptStub stub; 380 InterruptStub stub;
363 __ CallStub(&stub); 381 __ CallStub(&stub);
364 } else { 382 } else {
365 __ LoadRoot(ip, Heap::kStackLimitRootIndex); 383 __ LoadRoot(ip, Heap::kStackLimitRootIndex);
366 __ cmp(sp, Operand(ip)); 384 __ cmphs(sp, ip);
367 __ b(hs, &ok); 385 __ bt(&ok);
368 PredictableCodeSizeScope predictable(masm_);
369 StackCheckStub stub; 386 StackCheckStub stub;
370 __ CallStub(&stub); 387 __ CallStub(&stub);
371 } 388 }
372 389
373 // Record a mapping of this PC offset to the OSR id. This is used to find 390 // Record a mapping of this PC offset to the OSR id. This is used to find
374 // the AST id from the unoptimized code in order to use it as a key into 391 // the AST id from the unoptimized code in order to use it as a key into
375 // the deoptimization input data found in the optimized code. 392 // the deoptimization input data found in the optimized code.
376 RecordStackCheck(stmt->OsrEntryId()); 393 RecordStackCheck(stmt->OsrEntryId());
377 394
378 if (FLAG_count_based_interrupts) { 395 if (FLAG_count_based_interrupts) {
(...skipping 26 matching lines...) Expand all
405 int weight = 1; 422 int weight = 1;
406 if (info_->ShouldSelfOptimize()) { 423 if (info_->ShouldSelfOptimize()) {
407 weight = FLAG_interrupt_budget / FLAG_self_opt_count; 424 weight = FLAG_interrupt_budget / FLAG_self_opt_count;
408 } else if (FLAG_weighted_back_edges) { 425 } else if (FLAG_weighted_back_edges) {
409 int distance = masm_->pc_offset(); 426 int distance = masm_->pc_offset();
410 weight = Min(kMaxBackEdgeWeight, 427 weight = Min(kMaxBackEdgeWeight,
411 Max(1, distance / kBackEdgeDistanceUnit)); 428 Max(1, distance / kBackEdgeDistanceUnit));
412 } 429 }
413 EmitProfilingCounterDecrement(weight); 430 EmitProfilingCounterDecrement(weight);
414 Label ok; 431 Label ok;
415 __ b(pl, &ok); 432 __ bt(&ok); // TODO(STM): ??
416 __ push(r0); 433 __ push(r0);
417 if (info_->ShouldSelfOptimize() && FLAG_direct_self_opt) { 434 if (info_->ShouldSelfOptimize() && FLAG_direct_self_opt) {
418 __ ldr(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 435 __ ldr(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
419 __ push(r2); 436 __ push(r2);
420 __ CallRuntime(Runtime::kOptimizeFunctionOnNextCall, 1); 437 __ CallRuntime(Runtime::kOptimizeFunctionOnNextCall, 1);
421 } else { 438 } else {
422 InterruptStub stub; 439 InterruptStub stub;
423 __ CallStub(&stub); 440 __ CallStub(&stub);
424 } 441 }
425 __ pop(r0); 442 __ pop(r0);
426 EmitProfilingCounterReset(); 443 EmitProfilingCounterReset();
427 __ bind(&ok); 444 __ bind(&ok);
428 } 445 }
429 446
430 #ifdef DEBUG 447 #ifdef DEBUG
431 // Add a label for checking the size of the code used for returning. 448 // Add a label for checking the size of the code used for returning.
432 Label check_exit_codesize; 449 Label check_exit_codesize;
433 masm_->bind(&check_exit_codesize); 450 masm_->bind(&check_exit_codesize);
434 #endif 451 #endif
435 // Make sure that the constant pool is not emitted inside of the return 452 // Make sure that the constant pool is not emitted inside of the return
436 // sequence. 453 // sequence.
437 { Assembler::BlockConstPoolScope block_const_pool(masm_); 454 {
455 // SH4: removed
456 // Assembler::BlockConstPoolScope block_const_pool(masm_);
438 // Here we use masm_-> instead of the __ macro to avoid the code coverage 457 // Here we use masm_-> instead of the __ macro to avoid the code coverage
439 // tool from instrumenting as we rely on the code size here. 458 // tool from instrumenting as we rely on the code size here.
440 int32_t sp_delta = (info_->scope()->num_parameters() + 1) * kPointerSize; 459 int32_t sp_delta = (info_->scope()->num_parameters() + 1) * kPointerSize;
441 CodeGenerator::RecordPositions(masm_, function()->end_position() - 1); 460 CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
442 PredictableCodeSizeScope predictable(masm_);
443 __ RecordJSReturn(); 461 __ RecordJSReturn();
444 masm_->mov(sp, fp); 462 masm_->mov(sp, fp);
445 masm_->ldm(ia_w, sp, fp.bit() | lr.bit()); 463 masm_->Pop(lr, fp);
446 masm_->add(sp, sp, Operand(sp_delta)); 464 masm_->add(sp, sp, Operand(sp_delta));
447 masm_->Jump(lr); 465 masm_->Ret();
448 } 466 }
449 467
450 #ifdef DEBUG 468 // #ifdef DEBUG
451 // Check that the size of the code used for returning is large enough 469 // // Check that the size of the code used for returning is large enough
452 // for the debugger's requirements. 470 // // for the debugger's requirements.
453 ASSERT(Assembler::kJSReturnSequenceInstructions <= 471 // ASSERT(Assembler::kJSReturnSequenceInstructions <=
454 masm_->InstructionsGeneratedSince(&check_exit_codesize)); 472 // masm_->InstructionsGeneratedSince(&check_exit_codesize));
455 #endif 473 // #endif
456 } 474 }
457 } 475 }
458 476
459 477
460 void FullCodeGenerator::EffectContext::Plug(Variable* var) const { 478 void FullCodeGenerator::EffectContext::Plug(Variable* var) const {
461 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 479 ASSERT(var->IsStackAllocated() || var->IsContextSlot());
462 } 480 }
463 481
464 482
465 void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const { 483 void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const {
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
607 __ bind(materialize_true); 625 __ bind(materialize_true);
608 } 626 }
609 627
610 628
611 void FullCodeGenerator::AccumulatorValueContext::Plug( 629 void FullCodeGenerator::AccumulatorValueContext::Plug(
612 Label* materialize_true, 630 Label* materialize_true,
613 Label* materialize_false) const { 631 Label* materialize_false) const {
614 Label done; 632 Label done;
615 __ bind(materialize_true); 633 __ bind(materialize_true);
616 __ LoadRoot(result_register(), Heap::kTrueValueRootIndex); 634 __ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
617 __ jmp(&done); 635 __ jmp_near(&done);
618 __ bind(materialize_false); 636 __ bind(materialize_false);
619 __ LoadRoot(result_register(), Heap::kFalseValueRootIndex); 637 __ LoadRoot(result_register(), Heap::kFalseValueRootIndex);
620 __ bind(&done); 638 __ bind(&done);
621 } 639 }
622 640
623 641
624 void FullCodeGenerator::StackValueContext::Plug( 642 void FullCodeGenerator::StackValueContext::Plug(
625 Label* materialize_true, 643 Label* materialize_true,
626 Label* materialize_false) const { 644 Label* materialize_false) const {
627 Label done; 645 Label done;
628 __ bind(materialize_true); 646 __ bind(materialize_true);
629 __ LoadRoot(ip, Heap::kTrueValueRootIndex); 647 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
630 __ push(ip); 648 __ push(ip);
631 __ jmp(&done); 649 __ jmp_near(&done);
632 __ bind(materialize_false); 650 __ bind(materialize_false);
633 __ LoadRoot(ip, Heap::kFalseValueRootIndex); 651 __ LoadRoot(ip, Heap::kFalseValueRootIndex);
634 __ push(ip); 652 __ push(ip);
635 __ bind(&done); 653 __ bind(&done);
636 } 654 }
637 655
638 656
639 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, 657 void FullCodeGenerator::TestContext::Plug(Label* materialize_true,
640 Label* materialize_false) const { 658 Label* materialize_false) const {
641 ASSERT(materialize_true == true_label_); 659 ASSERT(materialize_true == true_label_);
(...skipping 30 matching lines...) Expand all
672 } else { 690 } else {
673 if (false_label_ != fall_through_) __ b(false_label_); 691 if (false_label_ != fall_through_) __ b(false_label_);
674 } 692 }
675 } 693 }
676 694
677 695
678 void FullCodeGenerator::DoTest(Expression* condition, 696 void FullCodeGenerator::DoTest(Expression* condition,
679 Label* if_true, 697 Label* if_true,
680 Label* if_false, 698 Label* if_false,
681 Label* fall_through) { 699 Label* fall_through) {
682 ToBooleanStub stub(result_register()); 700 // TODO(STM): can be removed !
683 __ CallStub(&stub); 701 if (CpuFeatures::IsSupported(FPU)) {
684 __ tst(result_register(), result_register()); 702 ToBooleanStub stub(result_register());
703 __ CallStub(&stub);
704 __ tst(result_register(), result_register());
705 } else {
706 // Call the runtime to find the boolean value of the source and then
707 // translate it into control flow to the pair of labels.
708 __ push(result_register());
709 __ CallRuntime(Runtime::kToBool, 1);
710 __ LoadRoot(ip, Heap::kFalseValueRootIndex);
711 __ cmp(r0, ip);
712 }
685 Split(ne, if_true, if_false, fall_through); 713 Split(ne, if_true, if_false, fall_through);
686 } 714 }
687 715
688 716
689 void FullCodeGenerator::Split(Condition cond, 717 void FullCodeGenerator::Split(Condition cond,
690 Label* if_true, 718 Label* if_true,
691 Label* if_false, 719 Label* if_false,
692 Label* fall_through) { 720 Label* fall_through) {
721 // We use ne for inverting conditions.
722 ASSERT(cond == ne || cond == eq);
693 if (if_false == fall_through) { 723 if (if_false == fall_through) {
694 __ b(cond, if_true); 724 __ b(cond, if_true);
695 } else if (if_true == fall_through) { 725 } else if (if_true == fall_through) {
696 __ b(NegateCondition(cond), if_false); 726 __ b(NegateCondition(cond), if_false);
697 } else { 727 } else {
728 // TODO(stm): add a special case for two jumps in a row
698 __ b(cond, if_true); 729 __ b(cond, if_true);
699 __ b(if_false); 730 __ b(if_false);
700 } 731 }
701 } 732 }
702 733
703 734
704 MemOperand FullCodeGenerator::StackOperand(Variable* var) { 735 MemOperand FullCodeGenerator::StackOperand(Variable* var) {
705 ASSERT(var->IsStackAllocated()); 736 ASSERT(var->IsStackAllocated());
706 // Offset is negative because higher indexes are at lower addresses. 737 // Offset is negative because higher indexes are at lower addresses.
707 int offset = -var->index() * kPointerSize; 738 int offset = -var->index() * kPointerSize;
(...skipping 29 matching lines...) Expand all
737 void FullCodeGenerator::SetVar(Variable* var, 768 void FullCodeGenerator::SetVar(Variable* var,
738 Register src, 769 Register src,
739 Register scratch0, 770 Register scratch0,
740 Register scratch1) { 771 Register scratch1) {
741 ASSERT(var->IsContextSlot() || var->IsStackAllocated()); 772 ASSERT(var->IsContextSlot() || var->IsStackAllocated());
742 ASSERT(!scratch0.is(src)); 773 ASSERT(!scratch0.is(src));
743 ASSERT(!scratch0.is(scratch1)); 774 ASSERT(!scratch0.is(scratch1));
744 ASSERT(!scratch1.is(src)); 775 ASSERT(!scratch1.is(src));
745 MemOperand location = VarOperand(var, scratch0); 776 MemOperand location = VarOperand(var, scratch0);
746 __ str(src, location); 777 __ str(src, location);
747
748 // Emit the write barrier code if the location is in the heap. 778 // Emit the write barrier code if the location is in the heap.
749 if (var->IsContextSlot()) { 779 if (var->IsContextSlot()) {
750 __ RecordWriteContextSlot(scratch0, 780 __ RecordWriteContextSlot(scratch0,
751 location.offset(), 781 location.offset(),
752 src, 782 src,
753 scratch1, 783 scratch1,
754 kLRHasBeenSaved, 784 kLRHasBeenSaved,
755 kDontSaveFPRegs); 785 kDontSaveFPRegs);
756 } 786 }
757 } 787 }
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
1083 __ cmp(r0, ip); 1113 __ cmp(r0, ip);
1084 __ b(eq, &exit); 1114 __ b(eq, &exit);
1085 Register null_value = r5; 1115 Register null_value = r5;
1086 __ LoadRoot(null_value, Heap::kNullValueRootIndex); 1116 __ LoadRoot(null_value, Heap::kNullValueRootIndex);
1087 __ cmp(r0, null_value); 1117 __ cmp(r0, null_value);
1088 __ b(eq, &exit); 1118 __ b(eq, &exit);
1089 1119
1090 PrepareForBailoutForId(stmt->PrepareId(), TOS_REG); 1120 PrepareForBailoutForId(stmt->PrepareId(), TOS_REG);
1091 1121
1092 // Convert the object to a JS object. 1122 // Convert the object to a JS object.
1093 Label convert, done_convert; 1123 Label convert;
1094 __ JumpIfSmi(r0, &convert); 1124 Label done_convert;
1095 __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE); 1125 __ JumpIfSmi(r0, &convert, Label::kNear);
1096 __ b(ge, &done_convert); 1126 __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE, ge);
1127 __ bt_near(&done_convert);
1097 __ bind(&convert); 1128 __ bind(&convert);
1098 __ push(r0); 1129 __ push(r0);
1099 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 1130 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
1100 __ bind(&done_convert); 1131 __ bind(&done_convert);
1101 __ push(r0); 1132 __ push(r0);
1102 1133
1103 // Check for proxies. 1134 // Check for proxies.
1104 Label call_runtime; 1135 Label call_runtime;
1105 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 1136 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
1106 __ CompareObjectType(r0, r1, r1, LAST_JS_PROXY_TYPE); 1137 __ CompareObjectType(r0, r1, r1, LAST_JS_PROXY_TYPE, gt);
1107 __ b(le, &call_runtime); 1138 __ bf(&call_runtime);
1108 1139
1109 // Check cache validity in generated code. This is a fast case for 1140 // Check cache validity in generated code. This is a fast case for
1110 // the JSObject::IsSimpleEnum cache validity checks. If we cannot 1141 // the JSObject::IsSimpleEnum cache validity checks. If we cannot
1111 // guarantee cache validity, call the runtime system to check cache 1142 // guarantee cache validity, call the runtime system to check cache
1112 // validity or get the property names in a fixed array. 1143 // validity or get the property names in a fixed array.
1113 __ CheckEnumCache(null_value, &call_runtime); 1144 __ CheckEnumCache(null_value, &call_runtime);
1114 1145
1115 // The enum cache is valid. Load the map of the object being 1146 // The enum cache is valid. Load the map of the object being
1116 // iterated over and use the cache for the iteration. 1147 // iterated over and use the cache for the iteration.
1117 Label use_cache; 1148 Label use_cache;
1118 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); 1149 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
1119 __ b(&use_cache); 1150 __ b_near(&use_cache);
1120 1151
1121 // Get the set of properties to enumerate. 1152 // Get the set of properties to enumerate.
1122 __ bind(&call_runtime); 1153 __ bind(&call_runtime);
1123 __ push(r0); // Duplicate the enumerable object on the stack. 1154 __ push(r0); // Duplicate the enumerable object on the stack.
1124 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); 1155 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
1125 1156
1126 // If we got a map from the runtime call, we can do a fast 1157 // If we got a map from the runtime call, we can do a fast
1127 // modification check. Otherwise, we got a fixed array, and we have 1158 // modification check. Otherwise, we got a fixed array, and we have
1128 // to do a slow check. 1159 // to do a slow check.
1129 Label fixed_array; 1160 Label fixed_array;
1130 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); 1161 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
1131 __ LoadRoot(ip, Heap::kMetaMapRootIndex); 1162 __ LoadRoot(ip, Heap::kMetaMapRootIndex);
1132 __ cmp(r2, ip); 1163 __ cmpeq(r2, ip);
1133 __ b(ne, &fixed_array); 1164 __ bf_near(&fixed_array);
1134 1165
1135 // We got a map in register r0. Get the enumeration cache from it. 1166 // We got a map in register r0. Get the enumeration cache from it.
1136 Label no_descriptors; 1167 Label no_descriptors;
1137 __ bind(&use_cache); 1168 __ bind(&use_cache);
1138 1169
1139 __ EnumLength(r1, r0); 1170 __ EnumLength(r1, r0);
1140 __ cmp(r1, Operand(Smi::FromInt(0))); 1171 __ cmp(r1, Operand(Smi::FromInt(0)));
1141 __ b(eq, &no_descriptors); 1172 __ b(eq, &no_descriptors);
1142 1173
1143 __ LoadInstanceDescriptors(r0, r2); 1174 __ LoadInstanceDescriptors(r0, r2, r4);
1144 __ ldr(r2, FieldMemOperand(r2, DescriptorArray::kEnumCacheOffset)); 1175 __ ldr(r2, FieldMemOperand(r2, DescriptorArray::kEnumCacheOffset));
1145 __ ldr(r2, FieldMemOperand(r2, DescriptorArray::kEnumCacheBridgeCacheOffset)); 1176 __ ldr(r2, FieldMemOperand(r2, DescriptorArray::kEnumCacheBridgeCacheOffset));
1146 1177
1147 // Set up the four remaining stack slots. 1178 // Set up the four remaining stack slots.
1148 __ push(r0); // Map. 1179 __ push(r0); // Map.
1149 __ mov(r0, Operand(Smi::FromInt(0))); 1180 __ mov(r0, Operand(Smi::FromInt(0)));
1150 // Push enumeration cache, enumeration cache length (as smi) and zero. 1181 // Push enumeration cache, enumeration cache length (as smi) and zero.
1151 __ Push(r2, r1, r0); 1182 __ Push(r2, r1, r0);
1152 __ jmp(&loop); 1183 __ jmp_near(&loop);
1153 1184
1154 __ bind(&no_descriptors); 1185 __ bind(&no_descriptors);
1155 __ Drop(1); 1186 __ Drop(1);
1156 __ jmp(&exit); 1187 __ jmp(&exit);
1157 1188
1158 // We got a fixed array in register r0. Iterate through that. 1189 // We got a fixed array in register r0. Iterate through that.
1159 Label non_proxy; 1190 Label non_proxy;
1160 __ bind(&fixed_array); 1191 __ bind(&fixed_array);
1161 1192
1162 Handle<JSGlobalPropertyCell> cell = 1193 Handle<JSGlobalPropertyCell> cell =
1163 isolate()->factory()->NewJSGlobalPropertyCell( 1194 isolate()->factory()->NewJSGlobalPropertyCell(
1164 Handle<Object>( 1195 Handle<Object>(
1165 Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker))); 1196 Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker)));
1166 RecordTypeFeedbackCell(stmt->ForInFeedbackId(), cell); 1197 RecordTypeFeedbackCell(stmt->ForInFeedbackId(), cell);
1167 __ LoadHeapObject(r1, cell); 1198 __ LoadHeapObject(r1, cell);
1168 __ mov(r2, Operand(Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker))); 1199 __ mov(r2, Operand(Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker)));
1169 __ str(r2, FieldMemOperand(r1, JSGlobalPropertyCell::kValueOffset)); 1200 __ str(r2, FieldMemOperand(r1, JSGlobalPropertyCell::kValueOffset));
1170 1201
1171 __ mov(r1, Operand(Smi::FromInt(1))); // Smi indicates slow check 1202 __ mov(r1, Operand(Smi::FromInt(1))); // Smi indicates slow check
1172 __ ldr(r2, MemOperand(sp, 0 * kPointerSize)); // Get enumerated object 1203 __ ldr(r2, MemOperand(sp, 0 * kPointerSize)); // Get enumerated object
1173 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 1204 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
1174 __ CompareObjectType(r2, r3, r3, LAST_JS_PROXY_TYPE); 1205 __ CompareObjectType(r2, r3, r3, LAST_JS_PROXY_TYPE, gt);
1175 __ b(gt, &non_proxy); 1206 __ bt(&non_proxy);
1176 __ mov(r1, Operand(Smi::FromInt(0))); // Zero indicates proxy 1207 __ mov(r1, Operand(Smi::FromInt(0))); // Zero indicates proxy
1177 __ bind(&non_proxy); 1208 __ bind(&non_proxy);
1178 __ Push(r1, r0); // Smi and array 1209 __ Push(r1, r0); // Smi and array
1179 __ ldr(r1, FieldMemOperand(r0, FixedArray::kLengthOffset)); 1210 __ ldr(r1, FieldMemOperand(r0, FixedArray::kLengthOffset));
1180 __ mov(r0, Operand(Smi::FromInt(0))); 1211 __ mov(r0, Operand(Smi::FromInt(0)));
1181 __ Push(r1, r0); // Fixed array length (as smi) and initial index. 1212 __ Push(r1, r0); // Fixed array length (as smi) and initial index.
1182 1213
1183 // Generate code for doing the condition check. 1214 // Generate code for doing the condition check.
1184 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); 1215 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
1185 __ bind(&loop); 1216 __ bind(&loop);
1186 // Load the current count to r0, load the length to r1. 1217 // Load the current count to r0, load the length to r1.
1187 __ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize)); 1218 __ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize));
1188 __ cmp(r0, r1); // Compare to the array length. 1219 __ cmphs(r0, r1); // Compare to the array length.
1189 __ b(hs, loop_statement.break_label()); 1220 __ bt(loop_statement.break_label());
1190 1221
1191 // Get the current entry of the array into register r3. 1222 // Get the current entry of the array into register r3.
1192 __ ldr(r2, MemOperand(sp, 2 * kPointerSize)); 1223 __ ldr(r2, MemOperand(sp, 2 * kPointerSize));
1193 __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 1224 __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
1194 __ ldr(r3, MemOperand(r2, r0, LSL, kPointerSizeLog2 - kSmiTagSize)); 1225 __ lsl(r3, r0, Operand(kPointerSizeLog2 - kSmiTagSize));
1226 __ ldr(r3, MemOperand(r2, r3));
1195 1227
1196 // Get the expected map from the stack or a smi in the 1228 // Get the expected map from the stack or a zero map in the
1197 // permanent slow case into register r2. 1229 // permanent slow case into register r2.
1198 __ ldr(r2, MemOperand(sp, 3 * kPointerSize)); 1230 __ ldr(r2, MemOperand(sp, 3 * kPointerSize));
1199 1231
1200 // Check if the expected map still matches that of the enumerable. 1232 // Check if the expected map still matches that of the enumerable.
1201 // If not, we may have to filter the key. 1233 // If not, we may have to filter the key.
1202 Label update_each; 1234 Label update_each;
1203 __ ldr(r1, MemOperand(sp, 4 * kPointerSize)); 1235 __ ldr(r1, MemOperand(sp, 4 * kPointerSize));
1204 __ ldr(r4, FieldMemOperand(r1, HeapObject::kMapOffset)); 1236 __ ldr(r4, FieldMemOperand(r1, HeapObject::kMapOffset));
1205 __ cmp(r4, Operand(r2)); 1237 __ cmpeq(r4, r2);
1206 __ b(eq, &update_each); 1238 __ bt_near(&update_each);
1207 1239
1208 // For proxies, no filtering is done. 1240 // For proxies, no filtering is done.
1209 // TODO(rossberg): What if only a prototype is a proxy? Not specified yet. 1241 // TODO(rossberg): What if only a prototype is a proxy? Not specified yet.
1210 __ cmp(r2, Operand(Smi::FromInt(0))); 1242 __ cmp(r2, Operand(Smi::FromInt(0)));
1211 __ b(eq, &update_each); 1243 __ b(eq, &update_each);
1212 1244
1213 // Convert the entry to a string or (smi) 0 if it isn't a property 1245 // Convert the entry to a string or (smi) 0 if it isn't a property
1214 // any more. If the property has been removed while iterating, we 1246 // any more. If the property has been removed while iterating, we
1215 // just skip it. 1247 // just skip it.
1216 __ push(r1); // Enumerable. 1248 __ push(r1); // Enumerable.
1217 __ push(r3); // Current entry. 1249 __ push(r3); // Current entry.
1218 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); 1250 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
1219 __ mov(r3, Operand(r0), SetCC); 1251 __ mov(r3, r0);
1252 __ tst(r3, r3);
1220 __ b(eq, loop_statement.continue_label()); 1253 __ b(eq, loop_statement.continue_label());
1221 1254
1222 // Update the 'each' property or variable from the possibly filtered 1255 // Update the 'each' property or variable from the possibly filtered
1223 // entry in register r3. 1256 // entry in register r3.
1224 __ bind(&update_each); 1257 __ bind(&update_each);
1225 __ mov(result_register(), r3); 1258 __ mov(result_register(), r3);
1226 // Perform the assignment as if via '='. 1259 // Perform the assignment as if via '='.
1227 { EffectContext context(this); 1260 { EffectContext context(this);
1228 EmitAssignment(stmt->each()); 1261 EmitAssignment(stmt->each());
1229 } 1262 }
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1316 if (s->is_eval_scope()) { 1349 if (s->is_eval_scope()) {
1317 Label loop, fast; 1350 Label loop, fast;
1318 if (!current.is(next)) { 1351 if (!current.is(next)) {
1319 __ Move(next, current); 1352 __ Move(next, current);
1320 } 1353 }
1321 __ bind(&loop); 1354 __ bind(&loop);
1322 // Terminate at native context. 1355 // Terminate at native context.
1323 __ ldr(temp, FieldMemOperand(next, HeapObject::kMapOffset)); 1356 __ ldr(temp, FieldMemOperand(next, HeapObject::kMapOffset));
1324 __ LoadRoot(ip, Heap::kNativeContextMapRootIndex); 1357 __ LoadRoot(ip, Heap::kNativeContextMapRootIndex);
1325 __ cmp(temp, ip); 1358 __ cmp(temp, ip);
1326 __ b(eq, &fast); 1359 __ b(eq, &fast, Label::kNear);
1327 // Check that extension is NULL. 1360 // Check that extension is NULL.
1328 __ ldr(temp, ContextOperand(next, Context::EXTENSION_INDEX)); 1361 __ ldr(temp, ContextOperand(next, Context::EXTENSION_INDEX));
1329 __ tst(temp, temp); 1362 __ tst(temp, temp);
1330 __ b(ne, slow); 1363 __ b(ne, slow);
1331 // Load next context in chain. 1364 // Load next context in chain.
1332 __ ldr(next, ContextOperand(next, Context::PREVIOUS_INDEX)); 1365 __ ldr(next, ContextOperand(next, Context::PREVIOUS_INDEX));
1333 __ b(&loop); 1366 __ b(&loop);
1334 __ bind(&fast); 1367 __ bind(&fast);
1335 } 1368 }
1336 1369
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1389 EmitLoadGlobalCheckExtensions(var, typeof_state, slow); 1422 EmitLoadGlobalCheckExtensions(var, typeof_state, slow);
1390 __ jmp(done); 1423 __ jmp(done);
1391 } else if (var->mode() == DYNAMIC_LOCAL) { 1424 } else if (var->mode() == DYNAMIC_LOCAL) {
1392 Variable* local = var->local_if_not_shadowed(); 1425 Variable* local = var->local_if_not_shadowed();
1393 __ ldr(r0, ContextSlotOperandCheckExtensions(local, slow)); 1426 __ ldr(r0, ContextSlotOperandCheckExtensions(local, slow));
1394 if (local->mode() == CONST || 1427 if (local->mode() == CONST ||
1395 local->mode() == CONST_HARMONY || 1428 local->mode() == CONST_HARMONY ||
1396 local->mode() == LET) { 1429 local->mode() == LET) {
1397 __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); 1430 __ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
1398 if (local->mode() == CONST) { 1431 if (local->mode() == CONST) {
1399 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); 1432 Label skip;
1433 __ bf_near(&skip);
1434 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
1435 __ bind(&skip);
1400 } else { // LET || CONST_HARMONY 1436 } else { // LET || CONST_HARMONY
1401 __ b(ne, done); 1437 __ b(ne, done);
1402 __ mov(r0, Operand(var->name())); 1438 __ mov(r0, Operand(var->name()));
1403 __ push(r0); 1439 __ push(r0);
1404 __ CallRuntime(Runtime::kThrowReferenceError, 1); 1440 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1405 } 1441 }
1406 } 1442 }
1407 __ jmp(done); 1443 __ jmp(done);
1408 } 1444 }
1409 } 1445 }
1410 1446
1411 1447
1448 // clobbers: r0, r1, r3
1449 // live-in: fp, sp, cp
1450 // live-out: fp, sp, cp
1412 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { 1451 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
1413 // Record position before possible IC call. 1452 // Record position before possible IC call.
1414 SetSourcePosition(proxy->position()); 1453 SetSourcePosition(proxy->position());
1415 Variable* var = proxy->var(); 1454 Variable* var = proxy->var();
1416 1455
1417 // Three cases: global variables, lookup variables, and all other types of 1456 // Three cases: global variables, lookup variables, and all other types of
1418 // variables. 1457 // variables.
1419 switch (var->location()) { 1458 switch (var->location()) {
1420 case Variable::UNALLOCATED: { 1459 case Variable::UNALLOCATED: {
1421 Comment cmnt(masm_, "Global variable"); 1460 Comment cmnt(masm_, "Global variable");
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1479 // binding in harmony mode. 1518 // binding in harmony mode.
1480 Label done; 1519 Label done;
1481 __ b(ne, &done); 1520 __ b(ne, &done);
1482 __ mov(r0, Operand(var->name())); 1521 __ mov(r0, Operand(var->name()));
1483 __ push(r0); 1522 __ push(r0);
1484 __ CallRuntime(Runtime::kThrowReferenceError, 1); 1523 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1485 __ bind(&done); 1524 __ bind(&done);
1486 } else { 1525 } else {
1487 // Uninitalized const bindings outside of harmony mode are unholed. 1526 // Uninitalized const bindings outside of harmony mode are unholed.
1488 ASSERT(var->mode() == CONST); 1527 ASSERT(var->mode() == CONST);
1489 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); 1528 Label skip;
1529 __ bf(&skip);
1530 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
1531 __ bind(&skip);
1490 } 1532 }
1491 context()->Plug(r0); 1533 context()->Plug(r0);
1492 break; 1534 break;
1493 } 1535 }
1494 } 1536 }
1495 context()->Plug(var); 1537 context()->Plug(var);
1496 break; 1538 break;
1497 } 1539 }
1498 1540
1499 case Variable::LOOKUP: { 1541 case Variable::LOOKUP: {
(...skipping 22 matching lines...) Expand all
1522 // r3 = literal index 1564 // r3 = literal index
1523 // r2 = RegExp pattern 1565 // r2 = RegExp pattern
1524 // r1 = RegExp flags 1566 // r1 = RegExp flags
1525 // r0 = RegExp literal clone 1567 // r0 = RegExp literal clone
1526 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 1568 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
1527 __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); 1569 __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset));
1528 int literal_offset = 1570 int literal_offset =
1529 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; 1571 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
1530 __ ldr(r5, FieldMemOperand(r4, literal_offset)); 1572 __ ldr(r5, FieldMemOperand(r4, literal_offset));
1531 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 1573 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
1532 __ cmp(r5, ip); 1574 __ cmpeq(r5, ip);
1533 __ b(ne, &materialized); 1575 __ bf_near(&materialized);
1534 1576
1535 // Create regexp literal using runtime function. 1577 // Create regexp literal using runtime function.
1536 // Result will be in r0. 1578 // Result will be in r0.
1537 __ mov(r3, Operand(Smi::FromInt(expr->literal_index()))); 1579 __ mov(r3, Operand(Smi::FromInt(expr->literal_index())));
1538 __ mov(r2, Operand(expr->pattern())); 1580 __ mov(r2, Operand(expr->pattern()));
1539 __ mov(r1, Operand(expr->flags())); 1581 __ mov(r1, Operand(expr->flags()));
1540 __ Push(r4, r3, r2, r1); 1582 __ Push(r4, r3, r2, r1);
1541 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 1583 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
1542 __ mov(r5, r0); 1584 __ mov(r5, r0);
1543 1585
1544 __ bind(&materialized); 1586 __ bind(&materialized);
1545 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; 1587 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
1546 Label allocated, runtime_allocate; 1588 Label allocated, runtime_allocate;
1547 __ AllocateInNewSpace(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT); 1589 __ AllocateInNewSpace(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT);
1548 __ jmp(&allocated); 1590 __ jmp_near(&allocated);
1549 1591
1550 __ bind(&runtime_allocate); 1592 __ bind(&runtime_allocate);
1551 __ push(r5); 1593 __ push(r5);
1552 __ mov(r0, Operand(Smi::FromInt(size))); 1594 __ mov(r0, Operand(Smi::FromInt(size)));
1553 __ push(r0); 1595 __ push(r0);
1554 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); 1596 __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
1555 __ pop(r5); 1597 __ pop(r5);
1556 1598
1557 __ bind(&allocated); 1599 __ bind(&allocated);
1558 // After this, registers are used as follows: 1600 // After this, registers are used as follows:
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after
1923 1965
1924 Register scratch1 = r2; 1966 Register scratch1 = r2;
1925 Register scratch2 = r3; 1967 Register scratch2 = r3;
1926 1968
1927 // Get the arguments. 1969 // Get the arguments.
1928 Register left = r1; 1970 Register left = r1;
1929 Register right = r0; 1971 Register right = r0;
1930 __ pop(left); 1972 __ pop(left);
1931 1973
1932 // Perform combined smi check on both operands. 1974 // Perform combined smi check on both operands.
1933 __ orr(scratch1, left, Operand(right)); 1975 __ orr(scratch1, left, right);
1934 STATIC_ASSERT(kSmiTag == 0); 1976 STATIC_ASSERT(kSmiTag == 0);
1935 JumpPatchSite patch_site(masm_); 1977 JumpPatchSite patch_site(masm_);
1936 patch_site.EmitJumpIfSmi(scratch1, &smi_case); 1978 patch_site.EmitJumpIfSmi(scratch1, &smi_case);
1937 1979
1938 __ bind(&stub_call); 1980 __ bind(&stub_call);
1939 BinaryOpStub stub(op, mode); 1981 BinaryOpStub stub(op, mode);
1940 CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, 1982 CallIC(stub.GetCode(), RelocInfo::CODE_TARGET,
1941 expr->BinaryOperationFeedbackId()); 1983 expr->BinaryOperationFeedbackId());
1942 patch_site.EmitPatchInfo(); 1984 patch_site.EmitPatchInfo();
1943 __ jmp(&done); 1985 __ jmp(&done);
1944 1986
1945 __ bind(&smi_case); 1987 __ bind(&smi_case);
1946 // Smi case. This code works the same way as the smi-smi case in the type 1988 // Smi case. This code works the same way as the smi-smi case in the type
1947 // recording binary operation stub, see 1989 // recording binary operation stub, see
1948 // BinaryOpStub::GenerateSmiSmiOperation for comments. 1990 // BinaryOpStub::GenerateSmiSmiOperation for comments.
1949 switch (op) { 1991 switch (op) {
1950 case Token::SAR: 1992 case Token::SAR:
1951 __ b(&stub_call); 1993 __ b(&stub_call);
1952 __ GetLeastBitsFromSmi(scratch1, right, 5); 1994 __ GetLeastBitsFromSmi(scratch1, right, 5);
1953 __ mov(right, Operand(left, ASR, scratch1)); 1995 __ asr(right, left, scratch1);
1954 __ bic(right, right, Operand(kSmiTagMask)); 1996 __ bic(right, right, Operand(kSmiTagMask));
1955 break; 1997 break;
1956 case Token::SHL: { 1998 case Token::SHL: {
1957 __ b(&stub_call); 1999 __ b(&stub_call);
1958 __ SmiUntag(scratch1, left); 2000 __ SmiUntag(scratch1, left);
1959 __ GetLeastBitsFromSmi(scratch2, right, 5); 2001 __ GetLeastBitsFromSmi(scratch2, right, 5);
1960 __ mov(scratch1, Operand(scratch1, LSL, scratch2)); 2002 __ lsl(scratch1, scratch1, scratch2);
1961 __ add(scratch2, scratch1, Operand(0x40000000), SetCC); 2003 __ add(scratch2, scratch1, Operand(0x40000000));
1962 __ b(mi, &stub_call); 2004 __ cmpge(scratch2, Operand(0));
2005 __ b(f, &stub_call);
1963 __ SmiTag(right, scratch1); 2006 __ SmiTag(right, scratch1);
1964 break; 2007 break;
1965 } 2008 }
1966 case Token::SHR: { 2009 case Token::SHR: {
1967 __ b(&stub_call); 2010 __ b(&stub_call);
1968 __ SmiUntag(scratch1, left); 2011 __ SmiUntag(scratch1, left);
1969 __ GetLeastBitsFromSmi(scratch2, right, 5); 2012 __ GetLeastBitsFromSmi(scratch2, right, 5);
1970 __ mov(scratch1, Operand(scratch1, LSR, scratch2)); 2013 __ lsr(scratch1, scratch1, scratch2);
1971 __ tst(scratch1, Operand(0xc0000000)); 2014 __ tst(scratch1, Operand(0xc0000000));
1972 __ b(ne, &stub_call); 2015 __ b(ne, &stub_call);
1973 __ SmiTag(right, scratch1); 2016 __ SmiTag(right, scratch1);
1974 break; 2017 break;
1975 } 2018 }
1976 case Token::ADD: 2019 case Token::ADD:
1977 __ add(scratch1, left, Operand(right), SetCC); 2020 __ addv(scratch1, left, right);
1978 __ b(vs, &stub_call); 2021 __ b(t, &stub_call);
1979 __ mov(right, scratch1); 2022 __ mov(right, scratch1);
1980 break; 2023 break;
1981 case Token::SUB: 2024 case Token::SUB:
1982 __ sub(scratch1, left, Operand(right), SetCC); 2025 __ subv(scratch1, left, right);
1983 __ b(vs, &stub_call); 2026 __ b(t, &stub_call);
1984 __ mov(right, scratch1); 2027 __ mov(right, scratch1);
1985 break; 2028 break;
1986 case Token::MUL: { 2029 case Token::MUL: {
1987 __ SmiUntag(ip, right); 2030 __ SmiUntag(ip, right);
1988 __ smull(scratch1, scratch2, left, ip); 2031 __ dmuls(scratch1, scratch2, left, ip);
1989 __ mov(ip, Operand(scratch1, ASR, 31)); 2032 __ asr(ip, scratch1, Operand(31));
1990 __ cmp(ip, Operand(scratch2)); 2033 __ cmp(ip, scratch2);
1991 __ b(ne, &stub_call); 2034 __ b(ne, &stub_call);
1992 __ cmp(scratch1, Operand(0)); 2035 __ tst(scratch1, scratch1);
1993 __ mov(right, Operand(scratch1), LeaveCC, ne); 2036 __ mov(right, scratch1, ne);
1994 __ b(ne, &done); 2037 __ b(ne, &done);
1995 __ add(scratch2, right, Operand(left), SetCC); 2038 __ add(scratch2, right, left);
1996 __ mov(right, Operand(Smi::FromInt(0)), LeaveCC, pl); 2039 __ cmpge(scratch2, Operand(0));
1997 __ b(mi, &stub_call); 2040 __ mov(right, Operand(Smi::FromInt(0)), t);
2041 __ bf(&stub_call);
1998 break; 2042 break;
1999 } 2043 }
2000 case Token::BIT_OR: 2044 case Token::BIT_OR:
2001 __ orr(right, left, Operand(right)); 2045 __ orr(right, left, right);
2002 break; 2046 break;
2003 case Token::BIT_AND: 2047 case Token::BIT_AND:
2004 __ and_(right, left, Operand(right)); 2048 __ land(right, left, right);
2005 break; 2049 break;
2006 case Token::BIT_XOR: 2050 case Token::BIT_XOR:
2007 __ eor(right, left, Operand(right)); 2051 __ eor(right, left, right);
2008 break; 2052 break;
2009 default: 2053 default:
2010 UNREACHABLE(); 2054 UNREACHABLE();
2011 } 2055 }
2012 2056
2013 __ bind(&done); 2057 __ bind(&done);
2014 context()->Plug(r0); 2058 context()->Plug(r0);
2015 } 2059 }
2016 2060
2017 2061
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
2095 : isolate()->builtins()->StoreIC_Initialize_Strict(); 2139 : isolate()->builtins()->StoreIC_Initialize_Strict();
2096 CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); 2140 CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
2097 2141
2098 } else if (op == Token::INIT_CONST) { 2142 } else if (op == Token::INIT_CONST) {
2099 // Const initializers need a write barrier. 2143 // Const initializers need a write barrier.
2100 ASSERT(!var->IsParameter()); // No const parameters. 2144 ASSERT(!var->IsParameter()); // No const parameters.
2101 if (var->IsStackLocal()) { 2145 if (var->IsStackLocal()) {
2102 Label skip; 2146 Label skip;
2103 __ ldr(r1, StackOperand(var)); 2147 __ ldr(r1, StackOperand(var));
2104 __ CompareRoot(r1, Heap::kTheHoleValueRootIndex); 2148 __ CompareRoot(r1, Heap::kTheHoleValueRootIndex);
2105 __ b(ne, &skip); 2149 __ b(ne, &skip, Label::kNear);
2106 __ str(result_register(), StackOperand(var)); 2150 __ str(result_register(), StackOperand(var));
2107 __ bind(&skip); 2151 __ bind(&skip);
2108 } else { 2152 } else {
2109 ASSERT(var->IsContextSlot() || var->IsLookupSlot()); 2153 ASSERT(var->IsContextSlot() || var->IsLookupSlot());
2110 // Like var declarations, const declarations are hoisted to function 2154 // Like var declarations, const declarations are hoisted to function
2111 // scope. However, unlike var initializers, const initializers are 2155 // scope. However, unlike var initializers, const initializers are
2112 // able to drill a hole to that function context, even from inside a 2156 // able to drill a hole to that function context, even from inside a
2113 // 'with' context. We thus bypass the normal static scope lookup for 2157 // 'with' context. We thus bypass the normal static scope lookup for
2114 // var->IsContextSlot(). 2158 // var->IsContextSlot().
2115 __ push(r0); 2159 __ push(r0);
2116 __ mov(r0, Operand(var->name())); 2160 __ mov(r0, Operand(var->name()));
2117 __ Push(cp, r0); // Context and name. 2161 __ Push(cp, r0); // Context and name.
2118 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); 2162 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
2119 } 2163 }
2120 2164
2121 } else if (var->mode() == LET && op != Token::INIT_LET) { 2165 } else if (var->mode() == LET && op != Token::INIT_LET) {
2122 // Non-initializing assignment to let variable needs a write barrier. 2166 // Non-initializing assignment to let variable needs a write barrier.
2123 if (var->IsLookupSlot()) { 2167 if (var->IsLookupSlot()) {
2124 __ push(r0); // Value. 2168 __ push(r0); // Value.
2125 __ mov(r1, Operand(var->name())); 2169 __ mov(r1, Operand(var->name()));
2126 __ mov(r0, Operand(Smi::FromInt(language_mode()))); 2170 __ mov(r0, Operand(Smi::FromInt(language_mode())));
2127 __ Push(cp, r1, r0); // Context, name, strict mode. 2171 __ Push(cp, r1, r0); // Context, name, strict mode.
2128 __ CallRuntime(Runtime::kStoreContextSlot, 4); 2172 __ CallRuntime(Runtime::kStoreContextSlot, 4);
2129 } else { 2173 } else {
2130 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 2174 ASSERT(var->IsStackAllocated() || var->IsContextSlot());
2131 Label assign; 2175 Label assign;
2132 MemOperand location = VarOperand(var, r1); 2176 MemOperand location = VarOperand(var, r1);
2133 __ ldr(r3, location); 2177 __ ldr(r3, location);
2134 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); 2178 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex);
2135 __ b(ne, &assign); 2179 __ b(ne, &assign, Label::kNear);
2136 __ mov(r3, Operand(var->name())); 2180 __ mov(r3, Operand(var->name()));
2137 __ push(r3); 2181 __ push(r3);
2138 __ CallRuntime(Runtime::kThrowReferenceError, 1); 2182 __ CallRuntime(Runtime::kThrowReferenceError, 1);
2139 // Perform the assignment. 2183 // Perform the assignment.
2140 __ bind(&assign); 2184 __ bind(&assign);
2141 __ str(result_register(), location); 2185 __ str(result_register(), location);
2142 if (var->IsContextSlot()) { 2186 if (var->IsContextSlot()) {
2143 // RecordWrite may destroy all its register arguments. 2187 // RecordWrite may destroy all its register arguments.
2144 __ mov(r3, result_register()); 2188 __ mov(r3, result_register());
2145 int offset = Context::SlotOffset(var->index()); 2189 int offset = Context::SlotOffset(var->index());
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
2235 EmitKeyedPropertyLoad(expr); 2279 EmitKeyedPropertyLoad(expr);
2236 context()->Plug(r0); 2280 context()->Plug(r0);
2237 } 2281 }
2238 } 2282 }
2239 2283
2240 2284
2241 void FullCodeGenerator::CallIC(Handle<Code> code, 2285 void FullCodeGenerator::CallIC(Handle<Code> code,
2242 RelocInfo::Mode rmode, 2286 RelocInfo::Mode rmode,
2243 TypeFeedbackId ast_id) { 2287 TypeFeedbackId ast_id) {
2244 ic_total_count_++; 2288 ic_total_count_++;
2245 // All calls must have a predictable size in full-codegen code to ensure that 2289 __ Call(code, rmode, ast_id);
2246 // the debugger can patch them correctly.
2247 __ Call(code, rmode, ast_id, al, NEVER_INLINE_TARGET_ADDRESS);
2248 } 2290 }
2249 2291
2250 void FullCodeGenerator::EmitCallWithIC(Call* expr, 2292 void FullCodeGenerator::EmitCallWithIC(Call* expr,
2251 Handle<Object> name, 2293 Handle<Object> name,
2252 RelocInfo::Mode mode) { 2294 RelocInfo::Mode mode) {
2253 // Code common for calls using the IC. 2295 // Code common for calls using the IC.
2254 ZoneList<Expression*>* args = expr->arguments(); 2296 ZoneList<Expression*>* args = expr->arguments();
2255 int arg_count = args->length(); 2297 int arg_count = args->length();
2256 { PreservePositionScope scope(masm()->positions_recorder()); 2298 { PreservePositionScope scope(masm()->positions_recorder());
2257 for (int i = 0; i < arg_count; i++) { 2299 for (int i = 0; i < arg_count; i++) {
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
2435 __ mov(r2, Operand(proxy->name())); 2477 __ mov(r2, Operand(proxy->name()));
2436 __ push(r2); 2478 __ push(r2);
2437 __ CallRuntime(Runtime::kLoadContextSlot, 2); 2479 __ CallRuntime(Runtime::kLoadContextSlot, 2);
2438 __ Push(r0, r1); // Function, receiver. 2480 __ Push(r0, r1); // Function, receiver.
2439 2481
2440 // If fast case code has been generated, emit code to push the 2482 // If fast case code has been generated, emit code to push the
2441 // function and receiver and have the slow path jump around this 2483 // function and receiver and have the slow path jump around this
2442 // code. 2484 // code.
2443 if (done.is_linked()) { 2485 if (done.is_linked()) {
2444 Label call; 2486 Label call;
2445 __ b(&call); 2487 __ b_near(&call);
2446 __ bind(&done); 2488 __ bind(&done);
2447 // Push function. 2489 // Push function.
2448 __ push(r0); 2490 __ push(r0);
2449 // The receiver is implicitly the global receiver. Indicate this 2491 // The receiver is implicitly the global receiver. Indicate this
2450 // by passing the hole to the call function stub. 2492 // by passing the hole to the call function stub.
2451 __ LoadRoot(r1, Heap::kTheHoleValueRootIndex); 2493 __ LoadRoot(r1, Heap::kTheHoleValueRootIndex);
2452 __ push(r1); 2494 __ push(r1);
2453 __ bind(&call); 2495 __ bind(&call);
2454 } 2496 }
2455 2497
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
2587 __ JumpIfSmi(r0, if_false); 2629 __ JumpIfSmi(r0, if_false);
2588 __ LoadRoot(ip, Heap::kNullValueRootIndex); 2630 __ LoadRoot(ip, Heap::kNullValueRootIndex);
2589 __ cmp(r0, ip); 2631 __ cmp(r0, ip);
2590 __ b(eq, if_true); 2632 __ b(eq, if_true);
2591 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); 2633 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
2592 // Undetectable objects behave like undefined when tested with typeof. 2634 // Undetectable objects behave like undefined when tested with typeof.
2593 __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset)); 2635 __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset));
2594 __ tst(r1, Operand(1 << Map::kIsUndetectable)); 2636 __ tst(r1, Operand(1 << Map::kIsUndetectable));
2595 __ b(ne, if_false); 2637 __ b(ne, if_false);
2596 __ ldrb(r1, FieldMemOperand(r2, Map::kInstanceTypeOffset)); 2638 __ ldrb(r1, FieldMemOperand(r2, Map::kInstanceTypeOffset));
2597 __ cmp(r1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); 2639 __ cmpge(r1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2598 __ b(lt, if_false); 2640 __ bf(if_false);
2599 __ cmp(r1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); 2641 __ cmpgt(r1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE));
2600 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2642 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2601 Split(le, if_true, if_false, fall_through); 2643 Split(ne, if_true, if_false, fall_through);
2602 2644
2603 context()->Plug(if_true, if_false); 2645 context()->Plug(if_true, if_false);
2604 } 2646 }
2605 2647
2606 2648
2607 void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) { 2649 void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
2608 ZoneList<Expression*>* args = expr->arguments(); 2650 ZoneList<Expression*>* args = expr->arguments();
2609 ASSERT(args->length() == 1); 2651 ASSERT(args->length() == 1);
2610 2652
2611 VisitForAccumulatorValue(args->at(0)); 2653 VisitForAccumulatorValue(args->at(0));
2612 2654
2613 Label materialize_true, materialize_false; 2655 Label materialize_true, materialize_false;
2614 Label* if_true = NULL; 2656 Label* if_true = NULL;
2615 Label* if_false = NULL; 2657 Label* if_false = NULL;
2616 Label* fall_through = NULL; 2658 Label* fall_through = NULL;
2617 context()->PrepareTest(&materialize_true, &materialize_false, 2659 context()->PrepareTest(&materialize_true, &materialize_false,
2618 &if_true, &if_false, &fall_through); 2660 &if_true, &if_false, &fall_through);
2619 2661
2620 __ JumpIfSmi(r0, if_false); 2662 __ JumpIfSmi(r0, if_false);
2621 __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE); 2663 __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE, ge);
2622 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2664 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2623 Split(ge, if_true, if_false, fall_through); 2665 Split(t, if_true, if_false, fall_through);
2624 2666
2625 context()->Plug(if_true, if_false); 2667 context()->Plug(if_true, if_false);
2626 } 2668 }
2627 2669
2628 2670
2629 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) { 2671 void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
2630 ZoneList<Expression*>* args = expr->arguments(); 2672 ZoneList<Expression*>* args = expr->arguments();
2631 ASSERT(args->length() == 1); 2673 ASSERT(args->length() == 1);
2632 2674
2633 VisitForAccumulatorValue(args->at(0)); 2675 VisitForAccumulatorValue(args->at(0));
(...skipping 23 matching lines...) Expand all
2657 2699
2658 VisitForAccumulatorValue(args->at(0)); 2700 VisitForAccumulatorValue(args->at(0));
2659 2701
2660 Label materialize_true, materialize_false; 2702 Label materialize_true, materialize_false;
2661 Label* if_true = NULL; 2703 Label* if_true = NULL;
2662 Label* if_false = NULL; 2704 Label* if_false = NULL;
2663 Label* fall_through = NULL; 2705 Label* fall_through = NULL;
2664 context()->PrepareTest(&materialize_true, &materialize_false, 2706 context()->PrepareTest(&materialize_true, &materialize_false,
2665 &if_true, &if_false, &fall_through); 2707 &if_true, &if_false, &fall_through);
2666 2708
2667 __ AssertNotSmi(r0); 2709 if (generate_debug_code_) __ AbortIfSmi(r0);
2668 2710
2669 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 2711 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
2670 __ ldrb(ip, FieldMemOperand(r1, Map::kBitField2Offset)); 2712 __ ldrb(ip, FieldMemOperand(r1, Map::kBitField2Offset));
2671 __ tst(ip, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf)); 2713 __ tst(ip, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
2672 __ b(ne, if_true); 2714 __ b(ne, if_true);
2673 2715
2674 // Check for fast case object. Generate false result for slow case object. 2716 // Check for fast case object. Generate false result for slow case object.
2675 __ ldr(r2, FieldMemOperand(r0, JSObject::kPropertiesOffset)); 2717 __ ldr(r2, FieldMemOperand(r0, JSObject::kPropertiesOffset));
2676 __ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset)); 2718 __ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset));
2677 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); 2719 __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
2678 __ cmp(r2, ip); 2720 __ cmp(r2, ip);
2679 __ b(eq, if_false); 2721 __ b(eq, if_false);
2680 2722
2681 // Look for valueOf symbol in the descriptor array, and indicate false if 2723 // Look for valueOf symbol in the descriptor array, and indicate false if
2682 // found. Since we omit an enumeration index check, if it is added via a 2724 // found. Since we omit an enumeration index check, if it is added via a
2683 // transition that shares its descriptor array, this is a false positive. 2725 // transition that shares its descriptor array, this is a false positive.
2684 Label entry, loop, done; 2726 Label entry, loop, done;
2685 2727
2686 // Skip loop if no descriptors are valid. 2728 // Skip loop if no descriptors are valid.
2687 __ NumberOfOwnDescriptors(r3, r1); 2729 __ NumberOfOwnDescriptors(r3, r1);
2688 __ cmp(r3, Operand(0)); 2730 __ cmp(r3, Operand(0));
2689 __ b(eq, &done); 2731 __ b(eq, &done);
2690 2732
2691 __ LoadInstanceDescriptors(r1, r4); 2733 __ LoadInstanceDescriptors(r1, r4, r2);
2692 // r4: descriptor array. 2734 // r4: descriptor array.
2693 // r3: valid entries in the descriptor array. 2735 // r3: valid entries in the descriptor array.
2694 STATIC_ASSERT(kSmiTag == 0); 2736 STATIC_ASSERT(kSmiTag == 0);
2695 STATIC_ASSERT(kSmiTagSize == 1); 2737 STATIC_ASSERT(kSmiTagSize == 1);
2696 STATIC_ASSERT(kPointerSize == 4); 2738 STATIC_ASSERT(kPointerSize == 4);
2697 __ mov(ip, Operand(DescriptorArray::kDescriptorSize)); 2739 __ mov(ip, Operand(DescriptorArray::kDescriptorSize));
2698 __ mul(r3, r3, ip); 2740 __ mul(r3, r3, ip);
2699 // Calculate location of the first key name. 2741 // Calculate location of the first key name.
2700 __ add(r4, r4, Operand(DescriptorArray::kFirstOffset - kHeapObjectTag)); 2742 __ add(r4,
2701 // Calculate the end of the descriptor array. 2743 r4,
2702 __ mov(r2, r4); 2744 Operand(FixedArray::kHeaderSize - kHeapObjectTag +
2703 __ add(r2, r2, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize)); 2745 DescriptorArray::kFirstIndex * kPointerSize));
2704
2705 // Loop through all the keys in the descriptor array. If one of these is the 2746 // Loop through all the keys in the descriptor array. If one of these is the
2706 // symbol valueOf the result is false. 2747 // symbol valueOf the result is false.
2707 // The use of ip to store the valueOf symbol asumes that it is not otherwise 2748 // The use of ip to store the valueOf symbol asumes that it is not otherwise
2708 // used in the loop below. 2749 // used in the loop below.
2709 __ mov(ip, Operand(FACTORY->value_of_symbol())); 2750 __ mov(ip, Operand(FACTORY->value_of_symbol()));
2710 __ jmp(&entry); 2751 __ jmp_near(&entry);
2711 __ bind(&loop); 2752 __ bind(&loop);
2712 __ ldr(r3, MemOperand(r4, 0)); 2753 __ ldr(r3, MemOperand(r4, 0));
2713 __ cmp(r3, ip); 2754 __ cmp(r3, ip);
2714 __ b(eq, if_false); 2755 __ b(eq, if_false);
2715 __ add(r4, r4, Operand(DescriptorArray::kDescriptorSize * kPointerSize)); 2756 __ add(r4, r4, Operand(DescriptorArray::kDescriptorSize * kPointerSize));
2716 __ bind(&entry); 2757 __ bind(&entry);
2717 __ cmp(r4, Operand(r2)); 2758 __ cmp(r4, r2);
2718 __ b(ne, &loop); 2759 __ b(ne, &loop);
2719 2760
2720 __ bind(&done); 2761 __ bind(&done);
2721 // If a valueOf property is not found on the object check that its 2762 // If a valueOf property is not found on the object check that its
2722 // prototype is the un-modified String prototype. If not result is false. 2763 // prototype is the un-modified String prototype. If not result is false.
2723 __ ldr(r2, FieldMemOperand(r1, Map::kPrototypeOffset)); 2764 __ ldr(r2, FieldMemOperand(r1, Map::kPrototypeOffset));
2724 __ JumpIfSmi(r2, if_false); 2765 __ JumpIfSmi(r2, if_false);
2725 __ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset)); 2766 __ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset));
2726 __ ldr(r3, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); 2767 __ ldr(r3, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
2727 __ ldr(r3, FieldMemOperand(r3, GlobalObject::kNativeContextOffset)); 2768 __ ldr(r3, FieldMemOperand(r3, GlobalObject::kNativeContextOffset));
(...skipping 20 matching lines...) Expand all
2748 VisitForAccumulatorValue(args->at(0)); 2789 VisitForAccumulatorValue(args->at(0));
2749 2790
2750 Label materialize_true, materialize_false; 2791 Label materialize_true, materialize_false;
2751 Label* if_true = NULL; 2792 Label* if_true = NULL;
2752 Label* if_false = NULL; 2793 Label* if_false = NULL;
2753 Label* fall_through = NULL; 2794 Label* fall_through = NULL;
2754 context()->PrepareTest(&materialize_true, &materialize_false, 2795 context()->PrepareTest(&materialize_true, &materialize_false,
2755 &if_true, &if_false, &fall_through); 2796 &if_true, &if_false, &fall_through);
2756 2797
2757 __ JumpIfSmi(r0, if_false); 2798 __ JumpIfSmi(r0, if_false);
2758 __ CompareObjectType(r0, r1, r2, JS_FUNCTION_TYPE); 2799 __ CompareObjectType(r0, r1, r2, JS_FUNCTION_TYPE, eq);
2759 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2800 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2760 Split(eq, if_true, if_false, fall_through); 2801 Split(eq, if_true, if_false, fall_through);
2761 2802
2762 context()->Plug(if_true, if_false); 2803 context()->Plug(if_true, if_false);
2763 } 2804 }
2764 2805
2765 2806
2766 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) { 2807 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
2767 ZoneList<Expression*>* args = expr->arguments(); 2808 ZoneList<Expression*>* args = expr->arguments();
2768 ASSERT(args->length() == 1); 2809 ASSERT(args->length() == 1);
2769 2810
2770 VisitForAccumulatorValue(args->at(0)); 2811 VisitForAccumulatorValue(args->at(0));
2771 2812
2772 Label materialize_true, materialize_false; 2813 Label materialize_true, materialize_false;
2773 Label* if_true = NULL; 2814 Label* if_true = NULL;
2774 Label* if_false = NULL; 2815 Label* if_false = NULL;
2775 Label* fall_through = NULL; 2816 Label* fall_through = NULL;
2776 context()->PrepareTest(&materialize_true, &materialize_false, 2817 context()->PrepareTest(&materialize_true, &materialize_false,
2777 &if_true, &if_false, &fall_through); 2818 &if_true, &if_false, &fall_through);
2778 2819
2779 __ JumpIfSmi(r0, if_false); 2820 __ JumpIfSmi(r0, if_false);
2780 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); 2821 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE, eq);
2781 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2822 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2782 Split(eq, if_true, if_false, fall_through); 2823 Split(eq, if_true, if_false, fall_through);
2783 2824
2784 context()->Plug(if_true, if_false); 2825 context()->Plug(if_true, if_false);
2785 } 2826 }
2786 2827
2787 2828
2788 void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) { 2829 void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
2789 ZoneList<Expression*>* args = expr->arguments(); 2830 ZoneList<Expression*>* args = expr->arguments();
2790 ASSERT(args->length() == 1); 2831 ASSERT(args->length() == 1);
2791 2832
2792 VisitForAccumulatorValue(args->at(0)); 2833 VisitForAccumulatorValue(args->at(0));
2793 2834
2794 Label materialize_true, materialize_false; 2835 Label materialize_true, materialize_false;
2795 Label* if_true = NULL; 2836 Label* if_true = NULL;
2796 Label* if_false = NULL; 2837 Label* if_false = NULL;
2797 Label* fall_through = NULL; 2838 Label* fall_through = NULL;
2798 context()->PrepareTest(&materialize_true, &materialize_false, 2839 context()->PrepareTest(&materialize_true, &materialize_false,
2799 &if_true, &if_false, &fall_through); 2840 &if_true, &if_false, &fall_through);
2800 2841
2801 __ JumpIfSmi(r0, if_false); 2842 __ JumpIfSmi(r0, if_false);
2802 __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); 2843 __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE, eq);
2803 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2844 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2804 Split(eq, if_true, if_false, fall_through); 2845 Split(eq, if_true, if_false, fall_through);
2805 2846
2806 context()->Plug(if_true, if_false); 2847 context()->Plug(if_true, if_false);
2807 } 2848 }
2808 2849
2809 2850
2810 2851
2811 void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) { 2852 void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
2812 ASSERT(expr->arguments()->length() == 0); 2853 ASSERT(expr->arguments()->length() == 0);
2813 2854
2814 Label materialize_true, materialize_false; 2855 Label materialize_true, materialize_false;
2815 Label* if_true = NULL; 2856 Label* if_true = NULL;
2816 Label* if_false = NULL; 2857 Label* if_false = NULL;
2817 Label* fall_through = NULL; 2858 Label* fall_through = NULL;
2818 context()->PrepareTest(&materialize_true, &materialize_false, 2859 context()->PrepareTest(&materialize_true, &materialize_false,
2819 &if_true, &if_false, &fall_through); 2860 &if_true, &if_false, &fall_through);
2820 2861
2821 // Get the frame pointer for the calling frame. 2862 // Get the frame pointer for the calling frame.
2822 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 2863 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
2823 2864
2824 // Skip the arguments adaptor frame if it exists. 2865 // Skip the arguments adaptor frame if it exists.
2825 Label check_frame_marker; 2866 Label check_frame_marker;
2826 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kContextOffset)); 2867 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kContextOffset));
2827 __ cmp(r1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2868 __ cmp(r1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2828 __ b(ne, &check_frame_marker); 2869 __ b(ne, &check_frame_marker, Label::kNear);
2829 __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset)); 2870 __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset));
2830 2871
2831 // Check the marker in the calling frame. 2872 // Check the marker in the calling frame.
2832 __ bind(&check_frame_marker); 2873 __ bind(&check_frame_marker);
2833 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset)); 2874 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset));
2834 __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT))); 2875 __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)));
2835 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2876 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2836 Split(eq, if_true, if_false, fall_through); 2877 Split(eq, if_true, if_false, fall_through);
2837 2878
2838 context()->Plug(if_true, if_false); 2879 context()->Plug(if_true, if_false);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
2881 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { 2922 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
2882 ASSERT(expr->arguments()->length() == 0); 2923 ASSERT(expr->arguments()->length() == 0);
2883 Label exit; 2924 Label exit;
2884 // Get the number of formal parameters. 2925 // Get the number of formal parameters.
2885 __ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); 2926 __ mov(r0, Operand(Smi::FromInt(info_->scope()->num_parameters())));
2886 2927
2887 // Check if the calling frame is an arguments adaptor frame. 2928 // Check if the calling frame is an arguments adaptor frame.
2888 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 2929 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
2889 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); 2930 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset));
2890 __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 2931 __ cmp(r3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
2891 __ b(ne, &exit); 2932 __ b(ne, &exit, Label::kNear);
2892 2933
2893 // Arguments adaptor case: Read the arguments length from the 2934 // Arguments adaptor case: Read the arguments length from the
2894 // adaptor frame. 2935 // adaptor frame.
2895 __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); 2936 __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset));
2896 2937
2897 __ bind(&exit); 2938 __ bind(&exit);
2898 context()->Plug(r0); 2939 context()->Plug(r0);
2899 } 2940 }
2900 2941
2901 2942
2902 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { 2943 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
2903 ZoneList<Expression*>* args = expr->arguments(); 2944 ZoneList<Expression*>* args = expr->arguments();
2904 ASSERT(args->length() == 1); 2945 ASSERT(args->length() == 1);
2905 Label done, null, function, non_function_constructor; 2946 Label done, null, function, non_function_constructor;
2906 2947
2907 VisitForAccumulatorValue(args->at(0)); 2948 VisitForAccumulatorValue(args->at(0));
2908 2949
2909 // If the object is a smi, we return null. 2950 // If the object is a smi, we return null.
2910 __ JumpIfSmi(r0, &null); 2951 __ JumpIfSmi(r0, &null, Label::kNear);
2911 2952
2912 // Check that the object is a JS object but take special care of JS 2953 // Check that the object is a JS object but take special care of JS
2913 // functions to make sure they have 'Function' as their class. 2954 // functions to make sure they have 'Function' as their class.
2914 // Assume that there are only two callable types, and one of them is at 2955 // Assume that there are only two callable types, and one of them is at
2915 // either end of the type range for JS object types. Saves extra comparisons. 2956 // either end of the type range for JS object types. Saves extra comparisons.
2916 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); 2957 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
2917 __ CompareObjectType(r0, r0, r1, FIRST_SPEC_OBJECT_TYPE); 2958 __ CompareObjectType(r0, r0, r1, FIRST_SPEC_OBJECT_TYPE, ge);
2918 // Map is now in r0. 2959 // Map is now in r0.
2919 __ b(lt, &null); 2960 __ bf_near(&null);
2920 STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE == 2961 STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
2921 FIRST_SPEC_OBJECT_TYPE + 1); 2962 FIRST_SPEC_OBJECT_TYPE + 1);
2922 __ b(eq, &function); 2963 __ b(eq, &function);
2923 2964
2924 __ cmp(r1, Operand(LAST_SPEC_OBJECT_TYPE)); 2965 __ cmp(r1, Operand(LAST_SPEC_OBJECT_TYPE));
2925 STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == 2966 STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
2926 LAST_SPEC_OBJECT_TYPE - 1); 2967 LAST_SPEC_OBJECT_TYPE - 1);
2927 __ b(eq, &function); 2968 __ b(eq, &function);
2928 // Assume that there is no larger type. 2969 // Assume that there is no larger type.
2929 STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1); 2970 STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1);
2930 2971
2931 // Check if the constructor in the map is a JS function. 2972 // Check if the constructor in the map is a JS function.
2932 __ ldr(r0, FieldMemOperand(r0, Map::kConstructorOffset)); 2973 __ ldr(r0, FieldMemOperand(r0, Map::kConstructorOffset));
2933 __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE); 2974 __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE, eq);
2934 __ b(ne, &non_function_constructor); 2975 __ b(ne, &non_function_constructor, Label::kNear);
2935 2976
2936 // r0 now contains the constructor function. Grab the 2977 // r0 now contains the constructor function. Grab the
2937 // instance class name from there. 2978 // instance class name from there.
2938 __ ldr(r0, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset)); 2979 __ ldr(r0, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset));
2939 __ ldr(r0, FieldMemOperand(r0, SharedFunctionInfo::kInstanceClassNameOffset)); 2980 __ ldr(r0, FieldMemOperand(r0, SharedFunctionInfo::kInstanceClassNameOffset));
2940 __ b(&done); 2981 __ b_near(&done);
2941 2982
2942 // Functions have class 'Function'. 2983 // Functions have class 'Function'.
2943 __ bind(&function); 2984 __ bind(&function);
2944 __ LoadRoot(r0, Heap::kfunction_class_symbolRootIndex); 2985 __ LoadRoot(r0, Heap::kfunction_class_symbolRootIndex);
2945 __ jmp(&done); 2986 __ jmp_near(&done);
2946 2987
2947 // Objects with a non-function constructor have class 'Object'. 2988 // Objects with a non-function constructor have class 'Object'.
2948 __ bind(&non_function_constructor); 2989 __ bind(&non_function_constructor);
2949 __ LoadRoot(r0, Heap::kObject_symbolRootIndex); 2990 __ LoadRoot(r0, Heap::kObject_symbolRootIndex);
2950 __ jmp(&done); 2991 __ jmp_near(&done);
2951 2992
2952 // Non-JS objects have class null. 2993 // Non-JS objects have class null.
2953 __ bind(&null); 2994 __ bind(&null);
2954 __ LoadRoot(r0, Heap::kNullValueRootIndex); 2995 __ LoadRoot(r0, Heap::kNullValueRootIndex);
2955 2996
2956 // All done. 2997 // All done.
2957 __ bind(&done); 2998 __ bind(&done);
2958 2999
2959 context()->Plug(r0); 3000 context()->Plug(r0);
2960 } 3001 }
(...skipping 21 matching lines...) Expand all
2982 } 3023 }
2983 3024
2984 3025
2985 void FullCodeGenerator::EmitRandomHeapNumber(CallRuntime* expr) { 3026 void FullCodeGenerator::EmitRandomHeapNumber(CallRuntime* expr) {
2986 ASSERT(expr->arguments()->length() == 0); 3027 ASSERT(expr->arguments()->length() == 0);
2987 Label slow_allocate_heapnumber; 3028 Label slow_allocate_heapnumber;
2988 Label heapnumber_allocated; 3029 Label heapnumber_allocated;
2989 3030
2990 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); 3031 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
2991 __ AllocateHeapNumber(r4, r1, r2, r6, &slow_allocate_heapnumber); 3032 __ AllocateHeapNumber(r4, r1, r2, r6, &slow_allocate_heapnumber);
2992 __ jmp(&heapnumber_allocated); 3033 __ jmp_near(&heapnumber_allocated);
2993 3034
2994 __ bind(&slow_allocate_heapnumber); 3035 __ bind(&slow_allocate_heapnumber);
2995 // Allocate a heap number. 3036 // Allocate a heap number.
2996 __ CallRuntime(Runtime::kNumberAlloc, 0); 3037 __ CallRuntime(Runtime::kNumberAlloc, 0);
2997 __ mov(r4, Operand(r0)); 3038 __ mov(r4, r0);
2998 3039
2999 __ bind(&heapnumber_allocated); 3040 __ bind(&heapnumber_allocated);
3000 3041
3001 // Convert 32 random bits in r0 to 0.(32 random bits) in a double 3042 // Convert 32 random bits in r0 to 0.(32 random bits) in a double
3002 // by computing: 3043 // by computing:
3003 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). 3044 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
3004 if (CpuFeatures::IsSupported(VFP2)) { 3045 if (CpuFeatures::IsSupported(FPU)) {
3046 __ push(r4);
3005 __ PrepareCallCFunction(1, r0); 3047 __ PrepareCallCFunction(1, r0);
3006 __ ldr(r0, 3048 __ ldr(r4,
3007 ContextOperand(context_register(), Context::GLOBAL_OBJECT_INDEX)); 3049 ContextOperand(context_register(), Context::GLOBAL_OBJECT_INDEX));
3008 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kNativeContextOffset)); 3050 __ ldr(r4, FieldMemOperand(r4, GlobalObject::kNativeContextOffset));
3009 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); 3051 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
3052 __ pop(r4);
3010 3053
3011 CpuFeatures::Scope scope(VFP2);
3012 // 0x41300000 is the top half of 1.0 x 2^20 as a double. 3054 // 0x41300000 is the top half of 1.0 x 2^20 as a double.
3013 // Create this constant using mov/orr to avoid PC relative load. 3055 // Create this constant using mov/orr to avoid PC relative load.
3014 __ mov(r1, Operand(0x41000000)); 3056 __ mov(r1, Operand(0x41000000));
3015 __ orr(r1, r1, Operand(0x300000)); 3057 __ orr(r1, r1, Operand(0x300000));
3016 // Move 0x41300000xxxxxxxx (x = random bits) to VFP. 3058 // Move 0x41300000xxxxxxxx (x = random bits) to VFP.
3017 __ vmov(d7, r0, r1); 3059 __ movd(dr2, r0, r1);
3018 // Move 0x4130000000000000 to VFP. 3060 // Move 0x4130000000000000 to VFP.
3019 __ mov(r0, Operand(0, RelocInfo::NONE)); 3061 __ mov(r0, Operand(0, RelocInfo::NONE));
3020 __ vmov(d8, r0, r1); 3062 __ movd(dr4, r0, r1);
3021 // Subtract and store the result in the heap number. 3063 // Subtract and store the result in the heap number.
3022 __ vsub(d7, d7, d8); 3064 __ fsub(dr2, dr4);
3023 __ sub(r0, r4, Operand(kHeapObjectTag)); 3065 __ sub(r0, r4, Operand(kHeapObjectTag));
3024 __ vstr(d7, r0, HeapNumber::kValueOffset); 3066 __ dstr(dr2, MemOperand(r0, HeapNumber::kValueOffset));
3025 __ mov(r0, r4); 3067 __ mov(r0, r4);
3026 } else { 3068 } else {
3027 __ PrepareCallCFunction(2, r0); 3069 __ PrepareCallCFunction(2, r0);
3028 __ ldr(r1, 3070 __ ldr(r5,
3029 ContextOperand(context_register(), Context::GLOBAL_OBJECT_INDEX)); 3071 ContextOperand(context_register(), Context::GLOBAL_OBJECT_INDEX));
3030 __ mov(r0, Operand(r4)); 3072 __ ldr(r5, FieldMemOperand(r5, GlobalObject::kNativeContextOffset));
3031 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kNativeContextOffset));
3032 __ CallCFunction( 3073 __ CallCFunction(
3033 ExternalReference::fill_heap_number_with_random_function(isolate()), 2); 3074 ExternalReference::fill_heap_number_with_random_function(isolate()), 2);
3034 } 3075 }
3035 3076
3036 context()->Plug(r0); 3077 context()->Plug(r0);
3037 } 3078 }
3038 3079
3039 3080
3040 void FullCodeGenerator::EmitSubString(CallRuntime* expr) { 3081 void FullCodeGenerator::EmitSubString(CallRuntime* expr) {
3041 // Load the arguments on the stack and call the stub. 3082 // Load the arguments on the stack and call the stub.
(...skipping 22 matching lines...) Expand all
3064 } 3105 }
3065 3106
3066 3107
3067 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) { 3108 void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
3068 ZoneList<Expression*>* args = expr->arguments(); 3109 ZoneList<Expression*>* args = expr->arguments();
3069 ASSERT(args->length() == 1); 3110 ASSERT(args->length() == 1);
3070 VisitForAccumulatorValue(args->at(0)); // Load the object. 3111 VisitForAccumulatorValue(args->at(0)); // Load the object.
3071 3112
3072 Label done; 3113 Label done;
3073 // If the object is a smi return the object. 3114 // If the object is a smi return the object.
3074 __ JumpIfSmi(r0, &done); 3115 __ JumpIfSmi(r0, &done, Label::kNear);
3075 // If the object is not a value type, return the object. 3116 // If the object is not a value type, return the object.
3076 __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE); 3117 __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE, eq);
3077 __ b(ne, &done); 3118 __ bf_near(&done);
3078 __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset)); 3119 __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset));
3079 3120
3080 __ bind(&done); 3121 __ bind(&done);
3081 context()->Plug(r0); 3122 context()->Plug(r0);
3082 } 3123 }
3083 3124
3084 3125
3085 void FullCodeGenerator::EmitDateField(CallRuntime* expr) { 3126 void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
3086 ZoneList<Expression*>* args = expr->arguments(); 3127 ZoneList<Expression*>* args = expr->arguments();
3087 ASSERT(args->length() == 2); 3128 ASSERT(args->length() == 2);
3088 ASSERT_NE(NULL, args->at(1)->AsLiteral()); 3129 ASSERT_NE(NULL, args->at(1)->AsLiteral());
3089 Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->handle())); 3130 Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->handle()));
3090 3131
3091 VisitForAccumulatorValue(args->at(0)); // Load the object. 3132 VisitForAccumulatorValue(args->at(0)); // Load the object.
3092 3133
3093 Label runtime, done, not_date_object; 3134 Label runtime, done, not_date_object;
3094 Register object = r0; 3135 Register object = r0;
3095 Register result = r0; 3136 Register result = r0;
3096 Register scratch0 = r9; 3137 Register scratch0 = r9;
3097 Register scratch1 = r1; 3138 Register scratch1 = r1;
3098 3139
3099 __ JumpIfSmi(object, &not_date_object); 3140 __ JumpIfSmi(object, &not_date_object);
3100 __ CompareObjectType(object, scratch1, scratch1, JS_DATE_TYPE); 3141 __ CompareObjectType(object, scratch1, scratch1, JS_DATE_TYPE, eq);
3101 __ b(ne, &not_date_object); 3142 __ bf(&not_date_object);
3102 3143
3103 if (index->value() == 0) { 3144 if (index->value() == 0) {
3104 __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset)); 3145 __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset));
3105 __ jmp(&done); 3146 __ jmp(&done);
3106 } else { 3147 } else {
3107 if (index->value() < JSDate::kFirstUncachedField) { 3148 if (index->value() < JSDate::kFirstUncachedField) {
3108 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); 3149 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
3109 __ mov(scratch1, Operand(stamp)); 3150 __ mov(scratch1, Operand(stamp));
3110 __ ldr(scratch1, MemOperand(scratch1)); 3151 __ ldr(scratch1, MemOperand(scratch1));
3111 __ ldr(scratch0, FieldMemOperand(object, JSDate::kCacheStampOffset)); 3152 __ ldr(scratch0, FieldMemOperand(object, JSDate::kCacheStampOffset));
3112 __ cmp(scratch1, scratch0); 3153 __ cmp(scratch1, scratch0);
3113 __ b(ne, &runtime); 3154 __ b(ne, &runtime);
3114 __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset + 3155 __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset +
3115 kPointerSize * index->value())); 3156 kPointerSize * index->value()));
3116 __ jmp(&done); 3157 __ jmp(&done);
3117 } 3158 }
3118 __ bind(&runtime); 3159 __ bind(&runtime);
3160 // TODO(STM): take care of the ABI
3119 __ PrepareCallCFunction(2, scratch1); 3161 __ PrepareCallCFunction(2, scratch1);
3120 __ mov(r1, Operand(index)); 3162 __ mov(r5, Operand(index));
3163 __ mov(r4, r0);
3121 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); 3164 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
3122 __ jmp(&done); 3165 __ jmp(&done);
3123 } 3166 }
3124 3167
3125 __ bind(&not_date_object); 3168 __ bind(&not_date_object);
3126 __ CallRuntime(Runtime::kThrowNotDateError, 0); 3169 __ CallRuntime(Runtime::kThrowNotDateError, 0);
3127 __ bind(&done); 3170 __ bind(&done);
3128 context()->Plug(r0); 3171 context()->Plug(r0);
3129 } 3172 }
3130 3173
3131 3174
3132 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { 3175 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
3133 // Load the arguments on the stack and call the runtime function. 3176 // Load the arguments on the stack and call the runtime function.
3134 ZoneList<Expression*>* args = expr->arguments(); 3177 ZoneList<Expression*>* args = expr->arguments();
3135 ASSERT(args->length() == 2); 3178 ASSERT(args->length() == 2);
3136 VisitForStackValue(args->at(0)); 3179 VisitForStackValue(args->at(0));
3137 VisitForStackValue(args->at(1)); 3180 VisitForStackValue(args->at(1));
3138 if (CpuFeatures::IsSupported(VFP2)) { 3181 if (CpuFeatures::IsSupported(FPU)) {
3139 MathPowStub stub(MathPowStub::ON_STACK); 3182 MathPowStub stub(MathPowStub::ON_STACK);
3140 __ CallStub(&stub); 3183 __ CallStub(&stub);
3141 } else { 3184 } else {
3142 __ CallRuntime(Runtime::kMath_pow, 2); 3185 __ CallRuntime(Runtime::kMath_pow, 2);
3143 } 3186 }
3144 context()->Plug(r0); 3187 context()->Plug(r0);
3145 } 3188 }
3146 3189
3147 3190
3148 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { 3191 void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
3149 ZoneList<Expression*>* args = expr->arguments(); 3192 ZoneList<Expression*>* args = expr->arguments();
3150 ASSERT(args->length() == 2); 3193 ASSERT(args->length() == 2);
3151 VisitForStackValue(args->at(0)); // Load the object. 3194 VisitForStackValue(args->at(0)); // Load the object.
3152 VisitForAccumulatorValue(args->at(1)); // Load the value. 3195 VisitForAccumulatorValue(args->at(1)); // Load the value.
3153 __ pop(r1); // r0 = value. r1 = object. 3196 __ pop(r1); // r0 = value. r1 = object.
3154 3197
3155 Label done; 3198 Label done;
3156 // If the object is a smi, return the value. 3199 // If the object is a smi, return the value.
3157 __ JumpIfSmi(r1, &done); 3200 __ JumpIfSmi(r1, &done);
3158 3201
3159 // If the object is not a value type, return the value. 3202 // If the object is not a value type, return the value.
3160 __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE); 3203 __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE, eq);
3161 __ b(ne, &done); 3204 __ b(ne, &done);
3162 3205
3163 // Store the value. 3206 // Store the value.
3164 __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset)); 3207 __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset));
3165 // Update the write barrier. Save the value as it will be 3208 // Update the write barrier. Save the value as it will be
3166 // overwritten by the write barrier code and is needed afterward. 3209 // overwritten by the write barrier code and is needed afterward.
3167 __ mov(r2, r0); 3210 __ mov(r2, r0);
3168 __ RecordWriteField( 3211 __ RecordWriteField(
3169 r1, JSValue::kValueOffset, r2, r3, kLRHasBeenSaved, kDontSaveFPRegs); 3212 r1, JSValue::kValueOffset, r2, r3, kLRHasBeenSaved, kDontSaveFPRegs);
3170 3213
(...skipping 10 matching lines...) Expand all
3181 3224
3182 NumberToStringStub stub; 3225 NumberToStringStub stub;
3183 __ CallStub(&stub); 3226 __ CallStub(&stub);
3184 context()->Plug(r0); 3227 context()->Plug(r0);
3185 } 3228 }
3186 3229
3187 3230
3188 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { 3231 void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
3189 ZoneList<Expression*>* args = expr->arguments(); 3232 ZoneList<Expression*>* args = expr->arguments();
3190 ASSERT(args->length() == 1); 3233 ASSERT(args->length() == 1);
3234
3191 VisitForAccumulatorValue(args->at(0)); 3235 VisitForAccumulatorValue(args->at(0));
3192 3236
3193 Label done; 3237 Label done;
3194 StringCharFromCodeGenerator generator(r0, r1); 3238 StringCharFromCodeGenerator generator(r0, r1);
3195 generator.GenerateFast(masm_); 3239 generator.GenerateFast(masm_);
3196 __ jmp(&done); 3240 __ jmp(&done);
3197 3241
3198 NopRuntimeCallHelper call_helper; 3242 NopRuntimeCallHelper call_helper;
3199 generator.GenerateSlow(masm_, call_helper); 3243 generator.GenerateSlow(masm_, call_helper);
3200 3244
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
3383 3427
3384 int arg_count = args->length() - 2; // 2 ~ receiver and function. 3428 int arg_count = args->length() - 2; // 2 ~ receiver and function.
3385 for (int i = 0; i < arg_count + 1; i++) { 3429 for (int i = 0; i < arg_count + 1; i++) {
3386 VisitForStackValue(args->at(i)); 3430 VisitForStackValue(args->at(i));
3387 } 3431 }
3388 VisitForAccumulatorValue(args->last()); // Function. 3432 VisitForAccumulatorValue(args->last()); // Function.
3389 3433
3390 Label runtime, done; 3434 Label runtime, done;
3391 // Check for non-function argument (including proxy). 3435 // Check for non-function argument (including proxy).
3392 __ JumpIfSmi(r0, &runtime); 3436 __ JumpIfSmi(r0, &runtime);
3393 __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE); 3437 __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE, eq);
3394 __ b(ne, &runtime); 3438 __ bf(&runtime);
3395 3439
3396 // InvokeFunction requires the function in r1. Move it in there. 3440 // InvokeFunction requires the function in r1. Move it in there.
3397 __ mov(r1, result_register()); 3441 __ mov(r1, result_register());
3398 ParameterCount count(arg_count); 3442 ParameterCount count(arg_count);
3399 __ InvokeFunction(r1, count, CALL_FUNCTION, 3443 __ InvokeFunction(r1, count, CALL_FUNCTION,
3400 NullCallWrapper(), CALL_AS_METHOD); 3444 NullCallWrapper(), CALL_AS_METHOD);
3401 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 3445 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
3402 __ jmp(&done); 3446 __ jmp(&done);
3403 3447
3404 __ bind(&runtime); 3448 __ bind(&runtime);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
3448 FieldMemOperand(cache, FixedArray::OffsetOfElementAt(cache_id))); 3492 FieldMemOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
3449 3493
3450 3494
3451 Label done, not_found; 3495 Label done, not_found;
3452 // tmp now holds finger offset as a smi. 3496 // tmp now holds finger offset as a smi.
3453 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 3497 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
3454 __ ldr(r2, FieldMemOperand(cache, JSFunctionResultCache::kFingerOffset)); 3498 __ ldr(r2, FieldMemOperand(cache, JSFunctionResultCache::kFingerOffset));
3455 // r2 now holds finger offset as a smi. 3499 // r2 now holds finger offset as a smi.
3456 __ add(r3, cache, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 3500 __ add(r3, cache, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
3457 // r3 now points to the start of fixed array elements. 3501 // r3 now points to the start of fixed array elements.
3458 __ ldr(r2, MemOperand(r3, r2, LSL, kPointerSizeLog2 - kSmiTagSize, PreIndex)); 3502 __ lsl(r2, r2, Operand(kPointerSizeLog2 - kSmiTagSize));
3503 __ add(r3, r3, r2);
3504 __ ldr(r2, MemOperand(r3));
3459 // Note side effect of PreIndex: r3 now points to the key of the pair. 3505 // Note side effect of PreIndex: r3 now points to the key of the pair.
3460 __ cmp(key, r2); 3506 __ cmp(key, r2);
3461 __ b(ne, &not_found); 3507 __ b(ne, &not_found, Label::kNear);
3462 3508
3463 __ ldr(r0, MemOperand(r3, kPointerSize)); 3509 __ ldr(r0, MemOperand(r3, kPointerSize));
3464 __ b(&done); 3510 __ b_near(&done);
3465 3511
3466 __ bind(&not_found); 3512 __ bind(&not_found);
3467 // Call runtime to perform the lookup. 3513 // Call runtime to perform the lookup.
3468 __ Push(cache, key); 3514 __ Push(cache, key);
3469 __ CallRuntime(Runtime::kGetFromCache, 2); 3515 __ CallRuntime(Runtime::kGetFromCache, 2);
3470 3516
3471 __ bind(&done); 3517 __ bind(&done);
3472 context()->Plug(r0); 3518 context()->Plug(r0);
3473 } 3519 }
3474 3520
3475 3521
3476 void FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) { 3522 void FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) {
3477 ZoneList<Expression*>* args = expr->arguments(); 3523 ZoneList<Expression*>* args = expr->arguments();
3478 ASSERT_EQ(2, args->length()); 3524 ASSERT_EQ(2, args->length());
3479 3525
3480 Register right = r0; 3526 Register right = r0;
3481 Register left = r1; 3527 Register left = r1;
3482 Register tmp = r2; 3528 Register tmp = r2;
3483 Register tmp2 = r3; 3529 Register tmp2 = r3;
3484 3530
3485 VisitForStackValue(args->at(0)); 3531 VisitForStackValue(args->at(0));
3486 VisitForAccumulatorValue(args->at(1)); 3532 VisitForAccumulatorValue(args->at(1));
3487 __ pop(left); 3533 __ pop(left);
3488 3534
3489 Label done, fail, ok; 3535 Label done, fail, ok;
3490 __ cmp(left, Operand(right)); 3536 __ cmp(left, right);
3491 __ b(eq, &ok); 3537 __ b(eq, &ok, Label::kNear);
3492 // Fail if either is a non-HeapObject. 3538 // Fail if either is a non-HeapObject.
3493 __ and_(tmp, left, Operand(right)); 3539 __ land(tmp, left, right);
3494 __ JumpIfSmi(tmp, &fail); 3540 __ JumpIfSmi(tmp, &fail, Label::kNear);
3495 __ ldr(tmp, FieldMemOperand(left, HeapObject::kMapOffset)); 3541 __ ldr(tmp, FieldMemOperand(left, HeapObject::kMapOffset));
3496 __ ldrb(tmp2, FieldMemOperand(tmp, Map::kInstanceTypeOffset)); 3542 __ ldrb(tmp2, FieldMemOperand(tmp, Map::kInstanceTypeOffset));
3497 __ cmp(tmp2, Operand(JS_REGEXP_TYPE)); 3543 __ cmp(tmp2, Operand(JS_REGEXP_TYPE));
3498 __ b(ne, &fail); 3544 __ b(ne, &fail, Label::kNear);
3499 __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset)); 3545 __ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
3500 __ cmp(tmp, Operand(tmp2)); 3546 __ cmp(tmp, tmp2);
3501 __ b(ne, &fail); 3547 __ b(ne, &fail, Label::kNear);
3502 __ ldr(tmp, FieldMemOperand(left, JSRegExp::kDataOffset)); 3548 __ ldr(tmp, FieldMemOperand(left, JSRegExp::kDataOffset));
3503 __ ldr(tmp2, FieldMemOperand(right, JSRegExp::kDataOffset)); 3549 __ ldr(tmp2, FieldMemOperand(right, JSRegExp::kDataOffset));
3504 __ cmp(tmp, tmp2); 3550 __ cmp(tmp, tmp2);
3505 __ b(eq, &ok); 3551 __ b(eq, &ok, Label::kNear);
3506 __ bind(&fail); 3552 __ bind(&fail);
3507 __ LoadRoot(r0, Heap::kFalseValueRootIndex); 3553 __ LoadRoot(r0, Heap::kFalseValueRootIndex);
3508 __ jmp(&done); 3554 __ jmp_near(&done);
3509 __ bind(&ok); 3555 __ bind(&ok);
3510 __ LoadRoot(r0, Heap::kTrueValueRootIndex); 3556 __ LoadRoot(r0, Heap::kTrueValueRootIndex);
3511 __ bind(&done); 3557 __ bind(&done);
3512 3558
3513 context()->Plug(r0); 3559 context()->Plug(r0);
3514 } 3560 }
3515 3561
3516 3562
3517 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { 3563 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
3518 ZoneList<Expression*>* args = expr->arguments(); 3564 ZoneList<Expression*>* args = expr->arguments();
(...skipping 13 matching lines...) Expand all
3532 3578
3533 context()->Plug(if_true, if_false); 3579 context()->Plug(if_true, if_false);
3534 } 3580 }
3535 3581
3536 3582
3537 void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) { 3583 void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
3538 ZoneList<Expression*>* args = expr->arguments(); 3584 ZoneList<Expression*>* args = expr->arguments();
3539 ASSERT(args->length() == 1); 3585 ASSERT(args->length() == 1);
3540 VisitForAccumulatorValue(args->at(0)); 3586 VisitForAccumulatorValue(args->at(0));
3541 3587
3542 __ AssertString(r0); 3588 __ AbortIfNotString(r0);
3589
3543 3590
3544 __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset)); 3591 __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset));
3545 __ IndexFromHash(r0, r0); 3592 __ IndexFromHash(r0, r0);
3546 3593
3547 context()->Plug(r0); 3594 context()->Plug(r0);
3548 } 3595 }
3549 3596
3550 3597
3551 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { 3598 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
3552 Label bailout, done, one_char_separator, long_separator, 3599 Label bailout, done, one_char_separator, long_separator,
(...skipping 17 matching lines...) Expand all
3570 Register element = r5; 3617 Register element = r5;
3571 Register elements_end = r6; 3618 Register elements_end = r6;
3572 Register scratch1 = r7; 3619 Register scratch1 = r7;
3573 Register scratch2 = r9; 3620 Register scratch2 = r9;
3574 3621
3575 // Separator operand is on the stack. 3622 // Separator operand is on the stack.
3576 __ pop(separator); 3623 __ pop(separator);
3577 3624
3578 // Check that the array is a JSArray. 3625 // Check that the array is a JSArray.
3579 __ JumpIfSmi(array, &bailout); 3626 __ JumpIfSmi(array, &bailout);
3580 __ CompareObjectType(array, scratch1, scratch2, JS_ARRAY_TYPE); 3627 __ CompareObjectType(array, scratch1, scratch2, JS_ARRAY_TYPE, eq);
3581 __ b(ne, &bailout); 3628 __ b(ne, &bailout);
3582 3629
3583 // Check that the array has fast elements. 3630 // Check that the array has fast elements.
3584 __ CheckFastElements(scratch1, scratch2, &bailout); 3631 __ CheckFastElements(scratch1, scratch2, &bailout);
3585 3632
3586 // If the array has length zero, return the empty string. 3633 // If the array has length zero, return the empty string.
3587 __ ldr(array_length, FieldMemOperand(array, JSArray::kLengthOffset)); 3634 __ ldr(array_length, FieldMemOperand(array, JSArray::kLengthOffset));
3588 __ SmiUntag(array_length, SetCC); 3635 __ SmiUntag(array_length);
3589 __ b(ne, &non_trivial_array); 3636 __ tst(array_length, array_length);
3637 __ b(ne, &non_trivial_array, Label::kNear);
3590 __ LoadRoot(r0, Heap::kEmptyStringRootIndex); 3638 __ LoadRoot(r0, Heap::kEmptyStringRootIndex);
3591 __ b(&done); 3639 __ b(&done);
3592 3640
3593 __ bind(&non_trivial_array); 3641 __ bind(&non_trivial_array);
3594 3642
3595 // Get the FixedArray containing array's elements. 3643 // Get the FixedArray containing array's elements.
3596 elements = array; 3644 elements = array;
3597 __ ldr(elements, FieldMemOperand(array, JSArray::kElementsOffset)); 3645 __ ldr(elements, FieldMemOperand(array, JSArray::kElementsOffset));
3598 array = no_reg; // End of array's live range. 3646 array = no_reg; // End of array's live range.
3599 3647
3600 // Check that all array elements are sequential ASCII strings, and 3648 // Check that all array elements are sequential ASCII strings, and
3601 // accumulate the sum of their lengths, as a smi-encoded value. 3649 // accumulate the sum of their lengths, as a smi-encoded value.
3602 __ mov(string_length, Operand(0)); 3650 __ mov(string_length, Operand(0));
3603 __ add(element, 3651 __ add(element,
3604 elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 3652 elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
3605 __ add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2)); 3653 __ lsl(elements_end, array_length, Operand(kPointerSizeLog2));
3654 __ add(elements_end, element, elements_end);
3606 // Loop condition: while (element < elements_end). 3655 // Loop condition: while (element < elements_end).
3607 // Live values in registers: 3656 // Live values in registers:
3608 // elements: Fixed array of strings. 3657 // elements: Fixed array of strings.
3609 // array_length: Length of the fixed array of strings (not smi) 3658 // array_length: Length of the fixed array of strings (not smi)
3610 // separator: Separator string 3659 // separator: Separator string
3611 // string_length: Accumulated sum of string lengths (smi). 3660 // string_length: Accumulated sum of string lengths (smi).
3612 // element: Current array element. 3661 // element: Current array element.
3613 // elements_end: Array end. 3662 // elements_end: Array end.
3614 if (generate_debug_code_) { 3663 if (generate_debug_code_) {
3615 __ cmp(array_length, Operand(0)); 3664 __ cmpgt(array_length, Operand(0));
3616 __ Assert(gt, "No empty arrays here in EmitFastAsciiArrayJoin"); 3665 __ Assert(eq, "No empty arrays here in EmitFastAsciiArrayJoin");
3617 } 3666 }
3618 __ bind(&loop); 3667 __ bind(&loop);
3619 __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); 3668 __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
3620 __ JumpIfSmi(string, &bailout); 3669 __ JumpIfSmi(string, &bailout);
3621 __ ldr(scratch1, FieldMemOperand(string, HeapObject::kMapOffset)); 3670 __ ldr(scratch1, FieldMemOperand(string, HeapObject::kMapOffset));
3622 __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); 3671 __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
3623 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout); 3672 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout);
3624 __ ldr(scratch1, FieldMemOperand(string, SeqAsciiString::kLengthOffset)); 3673 __ ldr(scratch1, FieldMemOperand(string, SeqAsciiString::kLengthOffset));
3625 __ add(string_length, string_length, Operand(scratch1), SetCC); 3674 __ addv(string_length, string_length, scratch1);
3626 __ b(vs, &bailout); 3675 __ b(t, &bailout);
3627 __ cmp(element, elements_end); 3676 __ cmpge(element, elements_end);
3628 __ b(lt, &loop); 3677 __ bf(&loop);
3629 3678
3630 // If array_length is 1, return elements[0], a string. 3679 // If array_length is 1, return elements[0], a string.
3631 __ cmp(array_length, Operand(1)); 3680 __ cmp(array_length, Operand(1));
3632 __ b(ne, &not_size_one_array); 3681 __ b(ne, &not_size_one_array, Label::kNear);
3633 __ ldr(r0, FieldMemOperand(elements, FixedArray::kHeaderSize)); 3682 __ ldr(r0, FieldMemOperand(elements, FixedArray::kHeaderSize));
3634 __ b(&done); 3683 __ b(&done);
3635 3684
3636 __ bind(&not_size_one_array); 3685 __ bind(&not_size_one_array);
3637 3686
3638 // Live values in registers: 3687 // Live values in registers:
3639 // separator: Separator string 3688 // separator: Separator string
3640 // array_length: Length of the array. 3689 // array_length: Length of the array.
3641 // string_length: Sum of string lengths (smi). 3690 // string_length: Sum of string lengths (smi).
3642 // elements: FixedArray of strings. 3691 // elements: FixedArray of strings.
3643 3692
3644 // Check that the separator is a flat ASCII string. 3693 // Check that the separator is a flat ASCII string.
3645 __ JumpIfSmi(separator, &bailout); 3694 __ JumpIfSmi(separator, &bailout);
3646 __ ldr(scratch1, FieldMemOperand(separator, HeapObject::kMapOffset)); 3695 __ ldr(scratch1, FieldMemOperand(separator, HeapObject::kMapOffset));
3647 __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); 3696 __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
3648 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout); 3697 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout);
3649 3698
3650 // Add (separator length times array_length) - separator length to the 3699 // Add (separator length times array_length) - separator length to the
3651 // string_length to get the length of the result string. array_length is not 3700 // string_length to get the length of the result string. array_length is not
3652 // smi but the other values are, so the result is a smi 3701 // smi but the other values are, so the result is a smi
3653 __ ldr(scratch1, FieldMemOperand(separator, SeqAsciiString::kLengthOffset)); 3702 __ ldr(scratch1, FieldMemOperand(separator, SeqAsciiString::kLengthOffset));
3654 __ sub(string_length, string_length, Operand(scratch1)); 3703 __ sub(string_length, string_length, scratch1);
3655 __ smull(scratch2, ip, array_length, scratch1); 3704 __ dmuls(scratch2, ip, array_length, scratch1);
3656 // Check for smi overflow. No overflow if higher 33 bits of 64-bit result are 3705 // Check for smi overflow. No overflow if higher 33 bits of 64-bit result are
3657 // zero. 3706 // zero.
3658 __ cmp(ip, Operand(0)); 3707 __ cmp(ip, Operand(0));
3659 __ b(ne, &bailout); 3708 __ b(ne, &bailout);
3660 __ tst(scratch2, Operand(0x80000000)); 3709 __ tst(scratch2, Operand(0x80000000));
3661 __ b(ne, &bailout); 3710 __ b(ne, &bailout);
3662 __ add(string_length, string_length, Operand(scratch2), SetCC); 3711 __ addv(string_length, string_length, scratch2);
3663 __ b(vs, &bailout); 3712 __ b(t, &bailout);
3664 __ SmiUntag(string_length); 3713 __ SmiUntag(string_length);
3665 3714
3666 // Get first element in the array to free up the elements register to be used 3715 // Get first element in the array to free up the elements register to be used
3667 // for the result. 3716 // for the result.
3668 __ add(element, 3717 __ add(element,
3669 elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 3718 elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
3670 result = elements; // End of live range for elements. 3719 result = elements; // End of live range for elements.
3671 elements = no_reg; 3720 elements = no_reg;
3672 // Live values in registers: 3721 // Live values in registers:
3673 // element: First array element 3722 // element: First array element
3674 // separator: Separator string 3723 // separator: Separator string
3675 // string_length: Length of result string (not smi) 3724 // string_length: Length of result string (not smi)
3676 // array_length: Length of the array. 3725 // array_length: Length of the array.
3677 __ AllocateAsciiString(result, 3726 __ AllocateAsciiString(result,
3678 string_length, 3727 string_length,
3679 scratch1, 3728 scratch1,
3680 scratch2, 3729 scratch2,
3681 elements_end, 3730 elements_end,
3682 &bailout); 3731 &bailout);
3683 // Prepare for looping. Set up elements_end to end of the array. Set 3732 // Prepare for looping. Set up elements_end to end of the array. Set
3684 // result_pos to the position of the result where to write the first 3733 // result_pos to the position of the result where to write the first
3685 // character. 3734 // character.
3686 __ add(elements_end, element, Operand(array_length, LSL, kPointerSizeLog2)); 3735 __ lsl(elements_end, array_length, Operand(kPointerSizeLog2));
3736 __ add(elements_end, element, elements_end);
3687 result_pos = array_length; // End of live range for array_length. 3737 result_pos = array_length; // End of live range for array_length.
3688 array_length = no_reg; 3738 array_length = no_reg;
3689 __ add(result_pos, 3739 __ add(result_pos,
3690 result, 3740 result,
3691 Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 3741 Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
3692 3742
3693 // Check the length of the separator. 3743 // Check the length of the separator.
3694 __ ldr(scratch1, FieldMemOperand(separator, SeqAsciiString::kLengthOffset)); 3744 __ ldr(scratch1, FieldMemOperand(separator, SeqAsciiString::kLengthOffset));
3695 __ cmp(scratch1, Operand(Smi::FromInt(1))); 3745 __ cmpeq(scratch1, Operand(Smi::FromInt(1)));
3696 __ b(eq, &one_char_separator); 3746 __ bt_near(&one_char_separator);
3697 __ b(gt, &long_separator); 3747 __ cmpgt(scratch1, Operand(Smi::FromInt(1)));
3748 __ bt(&long_separator);
3698 3749
3699 // Empty separator case 3750 // Empty separator case
3700 __ bind(&empty_separator_loop); 3751 __ bind(&empty_separator_loop);
3701 // Live values in registers: 3752 // Live values in registers:
3702 // result_pos: the position to which we are currently copying characters. 3753 // result_pos: the position to which we are currently copying characters.
3703 // element: Current array element. 3754 // element: Current array element.
3704 // elements_end: Array end. 3755 // elements_end: Array end.
3705 3756
3706 // Copy next array element to the result. 3757 // Copy next array element to the result.
3707 __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); 3758 __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
3708 __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset)); 3759 __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset));
3709 __ SmiUntag(string_length); 3760 __ SmiUntag(string_length);
3710 __ add(string, string, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 3761 __ add(string, string, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
3711 __ CopyBytes(string, result_pos, string_length, scratch1); 3762 __ CopyBytes(string, result_pos, string_length, scratch1);
3712 __ cmp(element, elements_end); 3763 __ cmpge(element, elements_end);
3713 __ b(lt, &empty_separator_loop); // End while (element < elements_end). 3764 __ bf(&empty_separator_loop); // End while (element < elements_end).
3714 ASSERT(result.is(r0)); 3765 ASSERT(result.is(r0));
3715 __ b(&done); 3766 __ b(&done);
3716 3767
3717 // One-character separator case 3768 // One-character separator case
3718 __ bind(&one_char_separator); 3769 __ bind(&one_char_separator);
3719 // Replace separator with its ASCII character value. 3770 // Replace separator with its ASCII character value.
3720 __ ldrb(separator, FieldMemOperand(separator, SeqAsciiString::kHeaderSize)); 3771 __ ldrb(separator, FieldMemOperand(separator, SeqAsciiString::kHeaderSize));
3721 // Jump into the loop after the code that copies the separator, so the first 3772 // Jump into the loop after the code that copies the separator, so the first
3722 // element is not preceded by a separator 3773 // element is not preceded by a separator
3723 __ jmp(&one_char_separator_loop_entry); 3774 __ jmp_near(&one_char_separator_loop_entry);
3724 3775
3725 __ bind(&one_char_separator_loop); 3776 __ bind(&one_char_separator_loop);
3726 // Live values in registers: 3777 // Live values in registers:
3727 // result_pos: the position to which we are currently copying characters. 3778 // result_pos: the position to which we are currently copying characters.
3728 // element: Current array element. 3779 // element: Current array element.
3729 // elements_end: Array end. 3780 // elements_end: Array end.
3730 // separator: Single separator ASCII char (in lower byte). 3781 // separator: Single separator ASCII char (in lower byte).
3731 3782
3732 // Copy the separator character to the result. 3783 // Copy the separator character to the result.
3733 __ strb(separator, MemOperand(result_pos, 1, PostIndex)); 3784 __ strb(separator, MemOperand(result_pos));
3785 __ add(result_pos, result_pos, Operand(1));
3734 3786
3735 // Copy next array element to the result. 3787 // Copy next array element to the result.
3736 __ bind(&one_char_separator_loop_entry); 3788 __ bind(&one_char_separator_loop_entry);
3737 __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); 3789 __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
3738 __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset)); 3790 __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset));
3739 __ SmiUntag(string_length); 3791 __ SmiUntag(string_length);
3740 __ add(string, string, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 3792 __ add(string, string, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
3741 __ CopyBytes(string, result_pos, string_length, scratch1); 3793 __ CopyBytes(string, result_pos, string_length, scratch1);
3742 __ cmp(element, elements_end); 3794 __ cmpge(element, elements_end);
3743 __ b(lt, &one_char_separator_loop); // End while (element < elements_end). 3795 __ bf(&one_char_separator_loop); // End while (element < elements_end).
3744 ASSERT(result.is(r0)); 3796 ASSERT(result.is(r0));
3745 __ b(&done); 3797 __ b(&done);
3746 3798
3747 // Long separator case (separator is more than one character). Entry is at the 3799 // Long separator case (separator is more than one character). Entry is at the
3748 // label long_separator below. 3800 // label long_separator below.
3749 __ bind(&long_separator_loop); 3801 __ bind(&long_separator_loop);
3750 // Live values in registers: 3802 // Live values in registers:
3751 // result_pos: the position to which we are currently copying characters. 3803 // result_pos: the position to which we are currently copying characters.
3752 // element: Current array element. 3804 // element: Current array element.
3753 // elements_end: Array end. 3805 // elements_end: Array end.
3754 // separator: Separator string. 3806 // separator: Separator string.
3755 3807
3756 // Copy the separator to the result. 3808 // Copy the separator to the result.
3757 __ ldr(string_length, FieldMemOperand(separator, String::kLengthOffset)); 3809 __ ldr(string_length, FieldMemOperand(separator, String::kLengthOffset));
3758 __ SmiUntag(string_length); 3810 __ SmiUntag(string_length);
3759 __ add(string, 3811 __ add(string,
3760 separator, 3812 separator,
3761 Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 3813 Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
3762 __ CopyBytes(string, result_pos, string_length, scratch1); 3814 __ CopyBytes(string, result_pos, string_length, scratch1);
3763 3815
3764 __ bind(&long_separator); 3816 __ bind(&long_separator);
3765 __ ldr(string, MemOperand(element, kPointerSize, PostIndex)); 3817 __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
3766 __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset)); 3818 __ ldr(string_length, FieldMemOperand(string, String::kLengthOffset));
3767 __ SmiUntag(string_length); 3819 __ SmiUntag(string_length);
3768 __ add(string, string, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag)); 3820 __ add(string, string, Operand(SeqAsciiString::kHeaderSize - kHeapObjectTag));
3769 __ CopyBytes(string, result_pos, string_length, scratch1); 3821 __ CopyBytes(string, result_pos, string_length, scratch1);
3770 __ cmp(element, elements_end); 3822 __ cmpge(element, elements_end);
3771 __ b(lt, &long_separator_loop); // End while (element < elements_end). 3823 __ bf(&long_separator_loop); // End while (element < elements_end).
3772 ASSERT(result.is(r0)); 3824 ASSERT(result.is(r0));
3773 __ b(&done); 3825 __ b(&done);
3774 3826
3775 __ bind(&bailout); 3827 __ bind(&bailout);
3776 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 3828 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
3777 __ bind(&done); 3829 __ bind(&done);
3778 context()->Plug(r0); 3830 context()->Plug(r0);
3779 } 3831 }
3780 3832
3781 3833
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
4053 } 4105 }
4054 } 4106 }
4055 4107
4056 4108
4057 // Inline smi case if we are in a loop. 4109 // Inline smi case if we are in a loop.
4058 Label stub_call, done; 4110 Label stub_call, done;
4059 JumpPatchSite patch_site(masm_); 4111 JumpPatchSite patch_site(masm_);
4060 4112
4061 int count_value = expr->op() == Token::INC ? 1 : -1; 4113 int count_value = expr->op() == Token::INC ? 1 : -1;
4062 if (ShouldInlineSmiCase(expr->op())) { 4114 if (ShouldInlineSmiCase(expr->op())) {
4063 __ add(r0, r0, Operand(Smi::FromInt(count_value)), SetCC); 4115 __ addv(r0, r0, Operand(Smi::FromInt(count_value)));
4064 __ b(vs, &stub_call); 4116 __ b(t, &stub_call);
4065 // We could eliminate this smi check if we split the code at 4117 // We could eliminate this smi check if we split the code at
4066 // the first smi check before calling ToNumber. 4118 // the first smi check before calling ToNumber.
4067 patch_site.EmitJumpIfSmi(r0, &done); 4119 patch_site.EmitJumpIfSmi(r0, &done);
4068 4120
4069 __ bind(&stub_call); 4121 __ bind(&stub_call);
4070 // Call stub. Undo operation first. 4122 // Call stub. Undo operation first.
4071 __ sub(r0, r0, Operand(Smi::FromInt(count_value))); 4123 __ sub(r0, r0, Operand(Smi::FromInt(count_value)));
4072 } 4124 }
4073 __ mov(r1, Operand(Smi::FromInt(count_value))); 4125 __ mov(r1, Operand(Smi::FromInt(count_value)));
4074 4126
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
4193 4245
4194 if (check->Equals(isolate()->heap()->number_symbol())) { 4246 if (check->Equals(isolate()->heap()->number_symbol())) {
4195 __ JumpIfSmi(r0, if_true); 4247 __ JumpIfSmi(r0, if_true);
4196 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); 4248 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
4197 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); 4249 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
4198 __ cmp(r0, ip); 4250 __ cmp(r0, ip);
4199 Split(eq, if_true, if_false, fall_through); 4251 Split(eq, if_true, if_false, fall_through);
4200 } else if (check->Equals(isolate()->heap()->string_symbol())) { 4252 } else if (check->Equals(isolate()->heap()->string_symbol())) {
4201 __ JumpIfSmi(r0, if_false); 4253 __ JumpIfSmi(r0, if_false);
4202 // Check for undetectable objects => false. 4254 // Check for undetectable objects => false.
4203 __ CompareObjectType(r0, r0, r1, FIRST_NONSTRING_TYPE); 4255 __ CompareObjectType(r0, r0, r1, FIRST_NONSTRING_TYPE, ge);
4204 __ b(ge, if_false); 4256 __ bt(if_false);
4205 __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); 4257 __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
4206 __ tst(r1, Operand(1 << Map::kIsUndetectable)); 4258 __ tst(r1, Operand(1 << Map::kIsUndetectable));
4207 Split(eq, if_true, if_false, fall_through); 4259 Split(eq, if_true, if_false, fall_through);
4208 } else if (check->Equals(isolate()->heap()->boolean_symbol())) { 4260 } else if (check->Equals(isolate()->heap()->boolean_symbol())) {
4209 __ CompareRoot(r0, Heap::kTrueValueRootIndex); 4261 __ CompareRoot(r0, Heap::kTrueValueRootIndex);
4210 __ b(eq, if_true); 4262 __ b(eq, if_true);
4211 __ CompareRoot(r0, Heap::kFalseValueRootIndex); 4263 __ CompareRoot(r0, Heap::kFalseValueRootIndex);
4212 Split(eq, if_true, if_false, fall_through); 4264 Split(eq, if_true, if_false, fall_through);
4213 } else if (FLAG_harmony_typeof && 4265 } else if (FLAG_harmony_typeof &&
4214 check->Equals(isolate()->heap()->null_symbol())) { 4266 check->Equals(isolate()->heap()->null_symbol())) {
4215 __ CompareRoot(r0, Heap::kNullValueRootIndex); 4267 __ CompareRoot(r0, Heap::kNullValueRootIndex);
4216 Split(eq, if_true, if_false, fall_through); 4268 Split(eq, if_true, if_false, fall_through);
4217 } else if (check->Equals(isolate()->heap()->undefined_symbol())) { 4269 } else if (check->Equals(isolate()->heap()->undefined_symbol())) {
4218 __ CompareRoot(r0, Heap::kUndefinedValueRootIndex); 4270 __ CompareRoot(r0, Heap::kUndefinedValueRootIndex);
4219 __ b(eq, if_true); 4271 __ b(eq, if_true);
4220 __ JumpIfSmi(r0, if_false); 4272 __ JumpIfSmi(r0, if_false);
4221 // Check for undetectable objects => true. 4273 // Check for undetectable objects => true.
4222 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); 4274 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
4223 __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); 4275 __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
4224 __ tst(r1, Operand(1 << Map::kIsUndetectable)); 4276 __ tst(r1, Operand(1 << Map::kIsUndetectable));
4225 Split(ne, if_true, if_false, fall_through); 4277 Split(ne, if_true, if_false, fall_through);
4226 4278
4227 } else if (check->Equals(isolate()->heap()->function_symbol())) { 4279 } else if (check->Equals(isolate()->heap()->function_symbol())) {
4228 __ JumpIfSmi(r0, if_false); 4280 __ JumpIfSmi(r0, if_false);
4229 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); 4281 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
4230 __ CompareObjectType(r0, r0, r1, JS_FUNCTION_TYPE); 4282 __ CompareObjectType(r0, r0, r1, JS_FUNCTION_TYPE, eq);
4231 __ b(eq, if_true); 4283 __ b(eq, if_true);
4232 __ cmp(r1, Operand(JS_FUNCTION_PROXY_TYPE)); 4284 __ cmp(r1, Operand(JS_FUNCTION_PROXY_TYPE));
4233 Split(eq, if_true, if_false, fall_through); 4285 Split(eq, if_true, if_false, fall_through);
4234 } else if (check->Equals(isolate()->heap()->object_symbol())) { 4286 } else if (check->Equals(isolate()->heap()->object_symbol())) {
4235 __ JumpIfSmi(r0, if_false); 4287 __ JumpIfSmi(r0, if_false);
4236 if (!FLAG_harmony_typeof) { 4288 if (!FLAG_harmony_typeof) {
4237 __ CompareRoot(r0, Heap::kNullValueRootIndex); 4289 __ CompareRoot(r0, Heap::kNullValueRootIndex);
4238 __ b(eq, if_true); 4290 __ b(eq, if_true);
4239 } 4291 }
4240 // Check for JS objects => true. 4292 // Check for JS objects => true.
4241 __ CompareObjectType(r0, r0, r1, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE); 4293 __ CompareObjectType(r0, r0, r1, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, ge);
4242 __ b(lt, if_false); 4294 __ bf(if_false);
4243 __ CompareInstanceType(r0, r1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); 4295 __ CompareInstanceType(r0, r1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE, gt);
4244 __ b(gt, if_false); 4296 __ bt(if_false);
4245 // Check for undetectable objects => false. 4297 // Check for undetectable objects => false.
4246 __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset)); 4298 __ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
4247 __ tst(r1, Operand(1 << Map::kIsUndetectable)); 4299 __ tst(r1, Operand(1 << Map::kIsUndetectable));
4248 Split(eq, if_true, if_false, fall_through); 4300 Split(eq, if_true, if_false, fall_through);
4249 } else { 4301 } else {
4250 if (if_false != fall_through) __ jmp(if_false); 4302 if (if_false != fall_through) __ jmp(if_false);
4251 } 4303 }
4252 context()->Plug(if_true, if_false); 4304 context()->Plug(if_true, if_false);
4253 } 4305 }
4254 4306
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
4317 case Token::INSTANCEOF: 4369 case Token::INSTANCEOF:
4318 default: 4370 default:
4319 UNREACHABLE(); 4371 UNREACHABLE();
4320 } 4372 }
4321 __ pop(r1); 4373 __ pop(r1);
4322 4374
4323 bool inline_smi_code = ShouldInlineSmiCase(op); 4375 bool inline_smi_code = ShouldInlineSmiCase(op);
4324 JumpPatchSite patch_site(masm_); 4376 JumpPatchSite patch_site(masm_);
4325 if (inline_smi_code) { 4377 if (inline_smi_code) {
4326 Label slow_case; 4378 Label slow_case;
4327 __ orr(r2, r0, Operand(r1)); 4379 __ orr(r2, r0, r1);
4328 patch_site.EmitJumpIfNotSmi(r2, &slow_case); 4380 patch_site.EmitJumpIfNotSmi(r2, &slow_case);
4329 __ cmp(r1, r0); 4381 Condition tmp_cond = cond;
4330 Split(cond, if_true, if_false, NULL); 4382 __ cmp(&tmp_cond, r1, r0);
4383 Split(tmp_cond, if_true, if_false, NULL);
4331 __ bind(&slow_case); 4384 __ bind(&slow_case);
4332 } 4385 }
4333 4386
4334 // Record position and call the compare IC. 4387 // Record position and call the compare IC.
4335 SetSourcePosition(expr->position()); 4388 SetSourcePosition(expr->position());
4336 Handle<Code> ic = CompareIC::GetUninitialized(op); 4389 Handle<Code> ic = CompareIC::GetUninitialized(op);
4337 CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId()); 4390 CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId());
4338 patch_site.EmitPatchInfo(); 4391 patch_site.EmitPatchInfo();
4339 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 4392 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4340 __ cmp(r0, Operand(0)); 4393 __ cmp(&cond, r0, Operand(0));
4341 Split(cond, if_true, if_false, fall_through); 4394 Split(cond, if_true, if_false, fall_through);
4342 } 4395 }
4343 } 4396 }
4344 4397
4345 // Convert the result of the comparison into one expected for this 4398 // Convert the result of the comparison into one expected for this
4346 // expression's context. 4399 // expression's context.
4347 context()->Plug(if_true, if_false); 4400 context()->Plug(if_true, if_false);
4348 } 4401 }
4349 4402
4350 4403
(...skipping 21 matching lines...) Expand all
4372 Heap::kUndefinedValueRootIndex : 4425 Heap::kUndefinedValueRootIndex :
4373 Heap::kNullValueRootIndex; 4426 Heap::kNullValueRootIndex;
4374 __ b(eq, if_true); 4427 __ b(eq, if_true);
4375 __ LoadRoot(r1, other_nil_value); 4428 __ LoadRoot(r1, other_nil_value);
4376 __ cmp(r0, r1); 4429 __ cmp(r0, r1);
4377 __ b(eq, if_true); 4430 __ b(eq, if_true);
4378 __ JumpIfSmi(r0, if_false); 4431 __ JumpIfSmi(r0, if_false);
4379 // It can be an undetectable object. 4432 // It can be an undetectable object.
4380 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 4433 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
4381 __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); 4434 __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset));
4382 __ and_(r1, r1, Operand(1 << Map::kIsUndetectable)); 4435 __ land(r1, r1, Operand(1 << Map::kIsUndetectable));
4383 __ cmp(r1, Operand(1 << Map::kIsUndetectable)); 4436 __ cmp(r1, Operand(1 << Map::kIsUndetectable));
4384 Split(eq, if_true, if_false, fall_through); 4437 Split(eq, if_true, if_false, fall_through);
4385 } 4438 }
4386 context()->Plug(if_true, if_false); 4439 context()->Plug(if_true, if_false);
4387 } 4440 }
4388 4441
4389 4442
4390 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { 4443 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
4391 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 4444 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
4392 context()->Plug(r0); 4445 context()->Plug(r0);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
4437 4490
4438 4491
4439 // ---------------------------------------------------------------------------- 4492 // ----------------------------------------------------------------------------
4440 // Non-local control flow support. 4493 // Non-local control flow support.
4441 4494
4442 void FullCodeGenerator::EnterFinallyBlock() { 4495 void FullCodeGenerator::EnterFinallyBlock() {
4443 ASSERT(!result_register().is(r1)); 4496 ASSERT(!result_register().is(r1));
4444 // Store result register while executing finally block. 4497 // Store result register while executing finally block.
4445 __ push(result_register()); 4498 __ push(result_register());
4446 // Cook return address in link register to stack (smi encoded Code* delta) 4499 // Cook return address in link register to stack (smi encoded Code* delta)
4447 __ sub(r1, lr, Operand(masm_->CodeObject())); 4500 __ strpr(r1);
4501 __ sub(r1, r1, Operand(masm_->CodeObject()));
4448 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); 4502 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
4449 STATIC_ASSERT(kSmiTag == 0); 4503 STATIC_ASSERT(kSmiTag == 0);
4450 __ add(r1, r1, Operand(r1)); // Convert to smi. 4504 __ add(r1, r1, r1); // Convert to smi.
4451 4505
4452 // Store result register while executing finally block. 4506 // Store result register while executing finally block.
4453 __ push(r1); 4507 __ push(r1);
4454 4508
4455 // Store pending message while executing finally block. 4509 // Store pending message while executing finally block.
4456 ExternalReference pending_message_obj = 4510 ExternalReference pending_message_obj =
4457 ExternalReference::address_of_pending_message_obj(isolate()); 4511 ExternalReference::address_of_pending_message_obj(isolate());
4458 __ mov(ip, Operand(pending_message_obj)); 4512 __ mov(ip, Operand(pending_message_obj));
4459 __ ldr(r1, MemOperand(ip)); 4513 __ ldr(r1, MemOperand(ip));
4460 __ push(r1); 4514 __ push(r1);
(...skipping 30 matching lines...) Expand all
4491 __ str(r1, MemOperand(ip)); 4545 __ str(r1, MemOperand(ip));
4492 4546
4493 __ pop(r1); 4547 __ pop(r1);
4494 ExternalReference pending_message_obj = 4548 ExternalReference pending_message_obj =
4495 ExternalReference::address_of_pending_message_obj(isolate()); 4549 ExternalReference::address_of_pending_message_obj(isolate());
4496 __ mov(ip, Operand(pending_message_obj)); 4550 __ mov(ip, Operand(pending_message_obj));
4497 __ str(r1, MemOperand(ip)); 4551 __ str(r1, MemOperand(ip));
4498 4552
4499 // Restore result register from stack. 4553 // Restore result register from stack.
4500 __ pop(r1); 4554 __ pop(r1);
4501
4502 // Uncook return address and return. 4555 // Uncook return address and return.
4503 __ pop(result_register()); 4556 __ pop(result_register());
4504 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); 4557 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
4505 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. 4558 __ asr(r1, r1, Operand(1)); // Un-smi-tag value.
4506 __ add(pc, r1, Operand(masm_->CodeObject())); 4559 __ add(r1, r1, Operand(masm_->CodeObject()));
4560 __ jmp(r1);
4507 } 4561 }
4508 4562
4509 4563
4510 #undef __ 4564 #undef __
4511 4565
4512 #define __ ACCESS_MASM(masm()) 4566 #define __ ACCESS_MASM(masm())
4513 4567
4514 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit( 4568 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
4515 int* stack_depth, 4569 int* stack_depth,
4516 int* context_length) { 4570 int* context_length) {
4517 // The macros used here must preserve the result register. 4571 // The macros used here must preserve the result register.
4518 4572
4519 // Because the handler block contains the context of the finally 4573 // Because the handler block contains the context of the finally
4520 // code, we can restore it directly from there for the finally code 4574 // code, we can restore it directly from there for the finally code
4521 // rather than iteratively unwinding contexts via their previous 4575 // rather than iteratively unwinding contexts via their previous
4522 // links. 4576 // links.
4523 __ Drop(*stack_depth); // Down to the handler block. 4577 __ Drop(*stack_depth); // Down to the handler block.
4524 if (*context_length > 0) { 4578 if (*context_length > 0) {
4525 // Restore the context to its dedicated register and the stack. 4579 // Restore the context to its dedicated register and the stack.
4526 __ ldr(cp, MemOperand(sp, StackHandlerConstants::kContextOffset)); 4580 __ ldr(cp, MemOperand(sp, StackHandlerConstants::kContextOffset));
4527 __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 4581 __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
4528 } 4582 }
4529 __ PopTryHandler(); 4583 __ PopTryHandler();
4530 __ bl(finally_entry_); 4584 __ jsr(finally_entry_);
4531 4585
4532 *stack_depth = 0; 4586 *stack_depth = 0;
4533 *context_length = 0; 4587 *context_length = 0;
4534 return previous_; 4588 return previous_;
4535 } 4589 }
4536 4590
4537 4591
4538 #undef __ 4592 #undef __
4539 4593
4540 } } // namespace v8::internal 4594 } } // namespace v8::internal
4541 4595
4542 #endif // V8_TARGET_ARCH_ARM 4596 #endif // V8_TARGET_ARCH_SH4
OLDNEW
« no previous file with comments | « src/sh4/frames-sh4.cc ('k') | src/sh4/ic-sh4.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698