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

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

Issue 371923006: Add mips64 port. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebase Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/mips64/frames-mips64.cc ('k') | src/mips64/ic-mips64.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 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #if V8_TARGET_ARCH_MIPS 7 #if V8_TARGET_ARCH_MIPS64
8 8
9 // Note on Mips implementation: 9 // Note on Mips implementation:
10 // 10 //
11 // The result_register() for mips is the 'v0' register, which is defined 11 // The result_register() for mips is the 'v0' register, which is defined
12 // by the ABI to contain function return values. However, the first 12 // by the ABI to contain function return values. However, the first
13 // parameter to a function is defined to be 'a0'. So there are many 13 // parameter to a function is defined to be 'a0'. So there are many
14 // places where we have to move a previous result in v0 to a0 for the 14 // places where we have to move a previous result in v0 to a0 for the
15 // next call: mov(a0, v0). This is not needed on the other architectures. 15 // next call: mov(a0, v0). This is not needed on the other architectures.
16 16
17 #include "src/code-stubs.h" 17 #include "src/code-stubs.h"
18 #include "src/codegen.h" 18 #include "src/codegen.h"
19 #include "src/compiler.h" 19 #include "src/compiler.h"
20 #include "src/debug.h" 20 #include "src/debug.h"
21 #include "src/full-codegen.h" 21 #include "src/full-codegen.h"
22 #include "src/isolate-inl.h" 22 #include "src/isolate-inl.h"
23 #include "src/parser.h" 23 #include "src/parser.h"
24 #include "src/scopes.h" 24 #include "src/scopes.h"
25 #include "src/stub-cache.h" 25 #include "src/stub-cache.h"
26 26
27 #include "src/mips/code-stubs-mips.h" 27 #include "src/mips64/code-stubs-mips64.h"
28 #include "src/mips/macro-assembler-mips.h" 28 #include "src/mips64/macro-assembler-mips64.h"
29 29
30 namespace v8 { 30 namespace v8 {
31 namespace internal { 31 namespace internal {
32 32
33 #define __ ACCESS_MASM(masm_) 33 #define __ ACCESS_MASM(masm_)
34 34
35 35
36 // A patch site is a location in the code which it is possible to patch. This 36 // A patch site is a location in the code which it is possible to patch. This
37 // class has a number of methods to emit the code which is patchable and the 37 // class has a number of methods to emit the code which is patchable and the
38 // method EmitPatchInfo to record a marker back to the patchable code. This 38 // method EmitPatchInfo to record a marker back to the patchable code. This
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 __ stop("stop-at"); 129 __ stop("stop-at");
130 } 130 }
131 #endif 131 #endif
132 132
133 // Sloppy mode functions and builtins need to replace the receiver with the 133 // Sloppy mode functions and builtins need to replace the receiver with the
134 // global proxy when called as functions (without an explicit receiver 134 // global proxy when called as functions (without an explicit receiver
135 // object). 135 // object).
136 if (info->strict_mode() == SLOPPY && !info->is_native()) { 136 if (info->strict_mode() == SLOPPY && !info->is_native()) {
137 Label ok; 137 Label ok;
138 int receiver_offset = info->scope()->num_parameters() * kPointerSize; 138 int receiver_offset = info->scope()->num_parameters() * kPointerSize;
139 __ lw(at, MemOperand(sp, receiver_offset)); 139 __ ld(at, MemOperand(sp, receiver_offset));
140 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex); 140 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
141 __ Branch(&ok, ne, a2, Operand(at)); 141 __ Branch(&ok, ne, a2, Operand(at));
142 142
143 __ lw(a2, GlobalObjectOperand()); 143 __ ld(a2, GlobalObjectOperand());
144 __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalProxyOffset)); 144 __ ld(a2, FieldMemOperand(a2, GlobalObject::kGlobalProxyOffset));
145 145
146 __ sw(a2, MemOperand(sp, receiver_offset)); 146 __ sd(a2, MemOperand(sp, receiver_offset));
147
148 __ bind(&ok); 147 __ bind(&ok);
149 } 148 }
150
151 // Open a frame scope to indicate that there is a frame on the stack. The 149 // Open a frame scope to indicate that there is a frame on the stack. The
152 // MANUAL indicates that the scope shouldn't actually generate code to set up 150 // MANUAL indicates that the scope shouldn't actually generate code to set up
153 // the frame (that is done below). 151 // the frame (that is done below).
154 FrameScope frame_scope(masm_, StackFrame::MANUAL); 152 FrameScope frame_scope(masm_, StackFrame::MANUAL);
155
156 info->set_prologue_offset(masm_->pc_offset()); 153 info->set_prologue_offset(masm_->pc_offset());
157 __ Prologue(info->IsCodePreAgingActive()); 154 __ Prologue(info->IsCodePreAgingActive());
158 info->AddNoFrameRange(0, masm_->pc_offset()); 155 info->AddNoFrameRange(0, masm_->pc_offset());
159 156
160 { Comment cmnt(masm_, "[ Allocate locals"); 157 { Comment cmnt(masm_, "[ Allocate locals");
161 int locals_count = info->scope()->num_stack_slots(); 158 int locals_count = info->scope()->num_stack_slots();
162 // Generators allocate locals, if any, in context slots. 159 // Generators allocate locals, if any, in context slots.
163 ASSERT(!info->function()->is_generator() || locals_count == 0); 160 ASSERT(!info->function()->is_generator() || locals_count == 0);
164 if (locals_count > 0) { 161 if (locals_count > 0) {
165 if (locals_count >= 128) { 162 if (locals_count >= 128) {
166 Label ok; 163 Label ok;
167 __ Subu(t5, sp, Operand(locals_count * kPointerSize)); 164 __ Dsubu(t1, sp, Operand(locals_count * kPointerSize));
168 __ LoadRoot(a2, Heap::kRealStackLimitRootIndex); 165 __ LoadRoot(a2, Heap::kRealStackLimitRootIndex);
169 __ Branch(&ok, hs, t5, Operand(a2)); 166 __ Branch(&ok, hs, t1, Operand(a2));
170 __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); 167 __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION);
171 __ bind(&ok); 168 __ bind(&ok);
172 } 169 }
173 __ LoadRoot(t5, Heap::kUndefinedValueRootIndex); 170 __ LoadRoot(t1, Heap::kUndefinedValueRootIndex);
174 int kMaxPushes = FLAG_optimize_for_size ? 4 : 32; 171 int kMaxPushes = FLAG_optimize_for_size ? 4 : 32;
175 if (locals_count >= kMaxPushes) { 172 if (locals_count >= kMaxPushes) {
176 int loop_iterations = locals_count / kMaxPushes; 173 int loop_iterations = locals_count / kMaxPushes;
177 __ li(a2, Operand(loop_iterations)); 174 __ li(a2, Operand(loop_iterations));
178 Label loop_header; 175 Label loop_header;
179 __ bind(&loop_header); 176 __ bind(&loop_header);
180 // Do pushes. 177 // Do pushes.
181 __ Subu(sp, sp, Operand(kMaxPushes * kPointerSize)); 178 __ Dsubu(sp, sp, Operand(kMaxPushes * kPointerSize));
182 for (int i = 0; i < kMaxPushes; i++) { 179 for (int i = 0; i < kMaxPushes; i++) {
183 __ sw(t5, MemOperand(sp, i * kPointerSize)); 180 __ sd(t1, MemOperand(sp, i * kPointerSize));
184 } 181 }
185 // Continue loop if not done. 182 // Continue loop if not done.
186 __ Subu(a2, a2, Operand(1)); 183 __ Dsubu(a2, a2, Operand(1));
187 __ Branch(&loop_header, ne, a2, Operand(zero_reg)); 184 __ Branch(&loop_header, ne, a2, Operand(zero_reg));
188 } 185 }
189 int remaining = locals_count % kMaxPushes; 186 int remaining = locals_count % kMaxPushes;
190 // Emit the remaining pushes. 187 // Emit the remaining pushes.
191 __ Subu(sp, sp, Operand(remaining * kPointerSize)); 188 __ Dsubu(sp, sp, Operand(remaining * kPointerSize));
192 for (int i = 0; i < remaining; i++) { 189 for (int i = 0; i < remaining; i++) {
193 __ sw(t5, MemOperand(sp, i * kPointerSize)); 190 __ sd(t1, MemOperand(sp, i * kPointerSize));
194 } 191 }
195 } 192 }
196 } 193 }
197 194
198 bool function_in_register = true; 195 bool function_in_register = true;
199 196
200 // Possibly allocate a local context. 197 // Possibly allocate a local context.
201 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 198 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
202 if (heap_slots > 0) { 199 if (heap_slots > 0) {
203 Comment cmnt(masm_, "[ Allocate context"); 200 Comment cmnt(masm_, "[ Allocate context");
204 // Argument to NewContext is the function, which is still in a1. 201 // Argument to NewContext is the function, which is still in a1.
205 bool need_write_barrier = true; 202 bool need_write_barrier = true;
206 if (FLAG_harmony_scoping && info->scope()->is_global_scope()) { 203 if (FLAG_harmony_scoping && info->scope()->is_global_scope()) {
207 __ push(a1); 204 __ push(a1);
208 __ Push(info->scope()->GetScopeInfo()); 205 __ Push(info->scope()->GetScopeInfo());
209 __ CallRuntime(Runtime::kNewGlobalContext, 2); 206 __ CallRuntime(Runtime::kNewGlobalContext, 2);
210 } else if (heap_slots <= FastNewContextStub::kMaximumSlots) { 207 } else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
211 FastNewContextStub stub(isolate(), heap_slots); 208 FastNewContextStub stub(isolate(), heap_slots);
212 __ CallStub(&stub); 209 __ CallStub(&stub);
213 // Result of FastNewContextStub is always in new space. 210 // Result of FastNewContextStub is always in new space.
214 need_write_barrier = false; 211 need_write_barrier = false;
215 } else { 212 } else {
216 __ push(a1); 213 __ push(a1);
217 __ CallRuntime(Runtime::kNewFunctionContext, 1); 214 __ CallRuntime(Runtime::kNewFunctionContext, 1);
218 } 215 }
219 function_in_register = false; 216 function_in_register = false;
220 // Context is returned in v0. It replaces the context passed to us. 217 // Context is returned in v0. It replaces the context passed to us.
221 // It's saved in the stack and kept live in cp. 218 // It's saved in the stack and kept live in cp.
222 __ mov(cp, v0); 219 __ mov(cp, v0);
223 __ sw(v0, MemOperand(fp, StandardFrameConstants::kContextOffset)); 220 __ sd(v0, MemOperand(fp, StandardFrameConstants::kContextOffset));
224 // Copy any necessary parameters into the context. 221 // Copy any necessary parameters into the context.
225 int num_parameters = info->scope()->num_parameters(); 222 int num_parameters = info->scope()->num_parameters();
226 for (int i = 0; i < num_parameters; i++) { 223 for (int i = 0; i < num_parameters; i++) {
227 Variable* var = scope()->parameter(i); 224 Variable* var = scope()->parameter(i);
228 if (var->IsContextSlot()) { 225 if (var->IsContextSlot()) {
229 int parameter_offset = StandardFrameConstants::kCallerSPOffset + 226 int parameter_offset = StandardFrameConstants::kCallerSPOffset +
230 (num_parameters - 1 - i) * kPointerSize; 227 (num_parameters - 1 - i) * kPointerSize;
231 // Load parameter from stack. 228 // Load parameter from stack.
232 __ lw(a0, MemOperand(fp, parameter_offset)); 229 __ ld(a0, MemOperand(fp, parameter_offset));
233 // Store it in the context. 230 // Store it in the context.
234 MemOperand target = ContextOperand(cp, var->index()); 231 MemOperand target = ContextOperand(cp, var->index());
235 __ sw(a0, target); 232 __ sd(a0, target);
236 233
237 // Update the write barrier. 234 // Update the write barrier.
238 if (need_write_barrier) { 235 if (need_write_barrier) {
239 __ RecordWriteContextSlot( 236 __ RecordWriteContextSlot(
240 cp, target.offset(), a0, a3, kRAHasBeenSaved, kDontSaveFPRegs); 237 cp, target.offset(), a0, a3, kRAHasBeenSaved, kDontSaveFPRegs);
241 } else if (FLAG_debug_code) { 238 } else if (FLAG_debug_code) {
242 Label done; 239 Label done;
243 __ JumpIfInNewSpace(cp, a0, &done); 240 __ JumpIfInNewSpace(cp, a0, &done);
244 __ Abort(kExpectedNewSpaceObject); 241 __ Abort(kExpectedNewSpaceObject);
245 __ bind(&done); 242 __ bind(&done);
246 } 243 }
247 } 244 }
248 } 245 }
249 } 246 }
250
251 Variable* arguments = scope()->arguments(); 247 Variable* arguments = scope()->arguments();
252 if (arguments != NULL) { 248 if (arguments != NULL) {
253 // Function uses arguments object. 249 // Function uses arguments object.
254 Comment cmnt(masm_, "[ Allocate arguments object"); 250 Comment cmnt(masm_, "[ Allocate arguments object");
255 if (!function_in_register) { 251 if (!function_in_register) {
256 // Load this again, if it's used by the local context below. 252 // Load this again, if it's used by the local context below.
257 __ lw(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 253 __ ld(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
258 } else { 254 } else {
259 __ mov(a3, a1); 255 __ mov(a3, a1);
260 } 256 }
261 // Receiver is just before the parameters on the caller's stack. 257 // Receiver is just before the parameters on the caller's stack.
262 int num_parameters = info->scope()->num_parameters(); 258 int num_parameters = info->scope()->num_parameters();
263 int offset = num_parameters * kPointerSize; 259 int offset = num_parameters * kPointerSize;
264 __ Addu(a2, fp, 260 __ Daddu(a2, fp,
265 Operand(StandardFrameConstants::kCallerSPOffset + offset)); 261 Operand(StandardFrameConstants::kCallerSPOffset + offset));
266 __ li(a1, Operand(Smi::FromInt(num_parameters))); 262 __ li(a1, Operand(Smi::FromInt(num_parameters)));
267 __ Push(a3, a2, a1); 263 __ Push(a3, a2, a1);
268 264
269 // Arguments to ArgumentsAccessStub: 265 // Arguments to ArgumentsAccessStub:
270 // function, receiver address, parameter count. 266 // function, receiver address, parameter count.
271 // The stub will rewrite receiever and parameter count if the previous 267 // The stub will rewrite receiever and parameter count if the previous
272 // stack frame was an arguments adapter frame. 268 // stack frame was an arguments adapter frame.
273 ArgumentsAccessStub::Type type; 269 ArgumentsAccessStub::Type type;
274 if (strict_mode() == STRICT) { 270 if (strict_mode() == STRICT) {
275 type = ArgumentsAccessStub::NEW_STRICT; 271 type = ArgumentsAccessStub::NEW_STRICT;
276 } else if (function()->has_duplicate_parameters()) { 272 } else if (function()->has_duplicate_parameters()) {
277 type = ArgumentsAccessStub::NEW_SLOPPY_SLOW; 273 type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
278 } else { 274 } else {
279 type = ArgumentsAccessStub::NEW_SLOPPY_FAST; 275 type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
280 } 276 }
281 ArgumentsAccessStub stub(isolate(), type); 277 ArgumentsAccessStub stub(isolate(), type);
282 __ CallStub(&stub); 278 __ CallStub(&stub);
283 279
284 SetVar(arguments, v0, a1, a2); 280 SetVar(arguments, v0, a1, a2);
285 } 281 }
286 282
287 if (FLAG_trace) { 283 if (FLAG_trace) {
288 __ CallRuntime(Runtime::kTraceEnter, 0); 284 __ CallRuntime(Runtime::kTraceEnter, 0);
289 } 285 }
290
291 // Visit the declarations and body unless there is an illegal 286 // Visit the declarations and body unless there is an illegal
292 // redeclaration. 287 // redeclaration.
293 if (scope()->HasIllegalRedeclaration()) { 288 if (scope()->HasIllegalRedeclaration()) {
294 Comment cmnt(masm_, "[ Declarations"); 289 Comment cmnt(masm_, "[ Declarations");
295 scope()->VisitIllegalRedeclaration(this); 290 scope()->VisitIllegalRedeclaration(this);
296 291
297 } else { 292 } else {
298 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); 293 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
299 { Comment cmnt(masm_, "[ Declarations"); 294 { Comment cmnt(masm_, "[ Declarations");
300 // For named function expressions, declare the function name as a 295 // For named function expressions, declare the function name as a
301 // constant. 296 // constant.
302 if (scope()->is_function_scope() && scope()->function() != NULL) { 297 if (scope()->is_function_scope() && scope()->function() != NULL) {
303 VariableDeclaration* function = scope()->function(); 298 VariableDeclaration* function = scope()->function();
304 ASSERT(function->proxy()->var()->mode() == CONST || 299 ASSERT(function->proxy()->var()->mode() == CONST ||
305 function->proxy()->var()->mode() == CONST_LEGACY); 300 function->proxy()->var()->mode() == CONST_LEGACY);
306 ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED); 301 ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED);
307 VisitVariableDeclaration(function); 302 VisitVariableDeclaration(function);
308 } 303 }
309 VisitDeclarations(scope()->declarations()); 304 VisitDeclarations(scope()->declarations());
310 } 305 }
311
312 { Comment cmnt(masm_, "[ Stack check"); 306 { Comment cmnt(masm_, "[ Stack check");
313 PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS); 307 PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
314 Label ok; 308 Label ok;
315 __ LoadRoot(at, Heap::kStackLimitRootIndex); 309 __ LoadRoot(at, Heap::kStackLimitRootIndex);
316 __ Branch(&ok, hs, sp, Operand(at)); 310 __ Branch(&ok, hs, sp, Operand(at));
317 Handle<Code> stack_check = isolate()->builtins()->StackCheck(); 311 Handle<Code> stack_check = isolate()->builtins()->StackCheck();
318 PredictableCodeSizeScope predictable(masm_, 312 PredictableCodeSizeScope predictable(masm_,
319 masm_->CallSize(stack_check, RelocInfo::CODE_TARGET)); 313 masm_->CallSize(stack_check, RelocInfo::CODE_TARGET));
320 __ Call(stack_check, RelocInfo::CODE_TARGET); 314 __ Call(stack_check, RelocInfo::CODE_TARGET);
321 __ bind(&ok); 315 __ bind(&ok);
322 } 316 }
323 317
324 { Comment cmnt(masm_, "[ Body"); 318 { Comment cmnt(masm_, "[ Body");
325 ASSERT(loop_depth() == 0); 319 ASSERT(loop_depth() == 0);
320
326 VisitStatements(function()->body()); 321 VisitStatements(function()->body());
322
327 ASSERT(loop_depth() == 0); 323 ASSERT(loop_depth() == 0);
328 } 324 }
329 } 325 }
330 326
331 // Always emit a 'return undefined' in case control fell off the end of 327 // Always emit a 'return undefined' in case control fell off the end of
332 // the body. 328 // the body.
333 { Comment cmnt(masm_, "[ return <undefined>;"); 329 { Comment cmnt(masm_, "[ return <undefined>;");
334 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); 330 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
335 } 331 }
336 EmitReturnSequence(); 332 EmitReturnSequence();
337 } 333 }
338 334
339 335
340 void FullCodeGenerator::ClearAccumulator() { 336 void FullCodeGenerator::ClearAccumulator() {
341 ASSERT(Smi::FromInt(0) == 0); 337 ASSERT(Smi::FromInt(0) == 0);
342 __ mov(v0, zero_reg); 338 __ mov(v0, zero_reg);
343 } 339 }
344 340
345 341
346 void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) { 342 void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
347 __ li(a2, Operand(profiling_counter_)); 343 __ li(a2, Operand(profiling_counter_));
348 __ lw(a3, FieldMemOperand(a2, Cell::kValueOffset)); 344 __ ld(a3, FieldMemOperand(a2, Cell::kValueOffset));
349 __ Subu(a3, a3, Operand(Smi::FromInt(delta))); 345 __ Dsubu(a3, a3, Operand(Smi::FromInt(delta)));
350 __ sw(a3, FieldMemOperand(a2, Cell::kValueOffset)); 346 __ sd(a3, FieldMemOperand(a2, Cell::kValueOffset));
351 } 347 }
352 348
353 349
354 void FullCodeGenerator::EmitProfilingCounterReset() { 350 void FullCodeGenerator::EmitProfilingCounterReset() {
355 int reset_value = FLAG_interrupt_budget; 351 int reset_value = FLAG_interrupt_budget;
356 if (info_->is_debug()) { 352 if (info_->is_debug()) {
357 // Detect debug break requests as soon as possible. 353 // Detect debug break requests as soon as possible.
358 reset_value = FLAG_interrupt_budget >> 4; 354 reset_value = FLAG_interrupt_budget >> 4;
359 } 355 }
360 __ li(a2, Operand(profiling_counter_)); 356 __ li(a2, Operand(profiling_counter_));
361 __ li(a3, Operand(Smi::FromInt(reset_value))); 357 __ li(a3, Operand(Smi::FromInt(reset_value)));
362 __ sw(a3, FieldMemOperand(a2, Cell::kValueOffset)); 358 __ sd(a3, FieldMemOperand(a2, Cell::kValueOffset));
363 } 359 }
364 360
365 361
366 void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt, 362 void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
367 Label* back_edge_target) { 363 Label* back_edge_target) {
368 // The generated code is used in Deoptimizer::PatchStackCheckCodeAt so we need 364 // The generated code is used in Deoptimizer::PatchStackCheckCodeAt so we need
369 // to make sure it is constant. Branch may emit a skip-or-jump sequence 365 // to make sure it is constant. Branch may emit a skip-or-jump sequence
370 // instead of the normal Branch. It seems that the "skip" part of that 366 // instead of the normal Branch. It seems that the "skip" part of that
371 // sequence is about as long as this Branch would be so it is safe to ignore 367 // sequence is about as long as this Branch would be so it is safe to ignore
372 // that. 368 // that.
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
437 // sequence. 433 // sequence.
438 { Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); 434 { Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
439 // Here we use masm_-> instead of the __ macro to avoid the code coverage 435 // Here we use masm_-> instead of the __ macro to avoid the code coverage
440 // tool from instrumenting as we rely on the code size here. 436 // tool from instrumenting as we rely on the code size here.
441 int32_t sp_delta = (info_->scope()->num_parameters() + 1) * kPointerSize; 437 int32_t sp_delta = (info_->scope()->num_parameters() + 1) * kPointerSize;
442 CodeGenerator::RecordPositions(masm_, function()->end_position() - 1); 438 CodeGenerator::RecordPositions(masm_, function()->end_position() - 1);
443 __ RecordJSReturn(); 439 __ RecordJSReturn();
444 masm_->mov(sp, fp); 440 masm_->mov(sp, fp);
445 int no_frame_start = masm_->pc_offset(); 441 int no_frame_start = masm_->pc_offset();
446 masm_->MultiPop(static_cast<RegList>(fp.bit() | ra.bit())); 442 masm_->MultiPop(static_cast<RegList>(fp.bit() | ra.bit()));
447 masm_->Addu(sp, sp, Operand(sp_delta)); 443 masm_->Daddu(sp, sp, Operand(sp_delta));
448 masm_->Jump(ra); 444 masm_->Jump(ra);
449 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); 445 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset());
450 } 446 }
451 447
452 #ifdef DEBUG 448 #ifdef DEBUG
453 // Check that the size of the code used for returning is large enough 449 // Check that the size of the code used for returning is large enough
454 // for the debugger's requirements. 450 // for the debugger's requirements.
455 ASSERT(Assembler::kJSReturnSequenceInstructions <= 451 ASSERT(Assembler::kJSReturnSequenceInstructions <=
456 masm_->InstructionsGeneratedSince(&check_exit_codesize)); 452 masm_->InstructionsGeneratedSince(&check_exit_codesize));
457 #endif 453 #endif
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
580 ASSERT(count > 0); 576 ASSERT(count > 0);
581 __ Drop(count); 577 __ Drop(count);
582 __ Move(result_register(), reg); 578 __ Move(result_register(), reg);
583 } 579 }
584 580
585 581
586 void FullCodeGenerator::StackValueContext::DropAndPlug(int count, 582 void FullCodeGenerator::StackValueContext::DropAndPlug(int count,
587 Register reg) const { 583 Register reg) const {
588 ASSERT(count > 0); 584 ASSERT(count > 0);
589 if (count > 1) __ Drop(count - 1); 585 if (count > 1) __ Drop(count - 1);
590 __ sw(reg, MemOperand(sp, 0)); 586 __ sd(reg, MemOperand(sp, 0));
591 } 587 }
592 588
593 589
594 void FullCodeGenerator::TestContext::DropAndPlug(int count, 590 void FullCodeGenerator::TestContext::DropAndPlug(int count,
595 Register reg) const { 591 Register reg) const {
596 ASSERT(count > 0); 592 ASSERT(count > 0);
597 // For simplicity we always test the accumulator register. 593 // For simplicity we always test the accumulator register.
598 __ Drop(count); 594 __ Drop(count);
599 __ Move(result_register(), reg); 595 __ Move(result_register(), reg);
600 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); 596 codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL);
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
728 return ContextOperand(scratch, var->index()); 724 return ContextOperand(scratch, var->index());
729 } else { 725 } else {
730 return StackOperand(var); 726 return StackOperand(var);
731 } 727 }
732 } 728 }
733 729
734 730
735 void FullCodeGenerator::GetVar(Register dest, Variable* var) { 731 void FullCodeGenerator::GetVar(Register dest, Variable* var) {
736 // Use destination as scratch. 732 // Use destination as scratch.
737 MemOperand location = VarOperand(var, dest); 733 MemOperand location = VarOperand(var, dest);
738 __ lw(dest, location); 734 __ ld(dest, location);
739 } 735 }
740 736
741 737
742 void FullCodeGenerator::SetVar(Variable* var, 738 void FullCodeGenerator::SetVar(Variable* var,
743 Register src, 739 Register src,
744 Register scratch0, 740 Register scratch0,
745 Register scratch1) { 741 Register scratch1) {
746 ASSERT(var->IsContextSlot() || var->IsStackAllocated()); 742 ASSERT(var->IsContextSlot() || var->IsStackAllocated());
747 ASSERT(!scratch0.is(src)); 743 ASSERT(!scratch0.is(src));
748 ASSERT(!scratch0.is(scratch1)); 744 ASSERT(!scratch0.is(scratch1));
749 ASSERT(!scratch1.is(src)); 745 ASSERT(!scratch1.is(src));
750 MemOperand location = VarOperand(var, scratch0); 746 MemOperand location = VarOperand(var, scratch0);
751 __ sw(src, location); 747 __ sd(src, location);
752 // Emit the write barrier code if the location is in the heap. 748 // Emit the write barrier code if the location is in the heap.
753 if (var->IsContextSlot()) { 749 if (var->IsContextSlot()) {
754 __ RecordWriteContextSlot(scratch0, 750 __ RecordWriteContextSlot(scratch0,
755 location.offset(), 751 location.offset(),
756 src, 752 src,
757 scratch1, 753 scratch1,
758 kRAHasBeenSaved, 754 kRAHasBeenSaved,
759 kDontSaveFPRegs); 755 kDontSaveFPRegs);
760 } 756 }
761 } 757 }
762 758
763 759
764 void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr, 760 void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
765 bool should_normalize, 761 bool should_normalize,
766 Label* if_true, 762 Label* if_true,
767 Label* if_false) { 763 Label* if_false) {
768 // Only prepare for bailouts before splits if we're in a test 764 // Only prepare for bailouts before splits if we're in a test
769 // context. Otherwise, we let the Visit function deal with the 765 // context. Otherwise, we let the Visit function deal with the
770 // preparation to avoid preparing with the same AST id twice. 766 // preparation to avoid preparing with the same AST id twice.
771 if (!context()->IsTest() || !info_->IsOptimizable()) return; 767 if (!context()->IsTest() || !info_->IsOptimizable()) return;
772 768
773 Label skip; 769 Label skip;
774 if (should_normalize) __ Branch(&skip); 770 if (should_normalize) __ Branch(&skip);
775 PrepareForBailout(expr, TOS_REG); 771 PrepareForBailout(expr, TOS_REG);
776 if (should_normalize) { 772 if (should_normalize) {
777 __ LoadRoot(t0, Heap::kTrueValueRootIndex); 773 __ LoadRoot(a4, Heap::kTrueValueRootIndex);
778 Split(eq, a0, Operand(t0), if_true, if_false, NULL); 774 Split(eq, a0, Operand(a4), if_true, if_false, NULL);
779 __ bind(&skip); 775 __ bind(&skip);
780 } 776 }
781 } 777 }
782 778
783 779
784 void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) { 780 void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
785 // The variable in the declaration always resides in the current function 781 // The variable in the declaration always resides in the current function
786 // context. 782 // context.
787 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope())); 783 ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
788 if (generate_debug_code_) { 784 if (generate_debug_code_) {
789 // Check that we're not inside a with or catch context. 785 // Check that we're not inside a with or catch context.
790 __ lw(a1, FieldMemOperand(cp, HeapObject::kMapOffset)); 786 __ ld(a1, FieldMemOperand(cp, HeapObject::kMapOffset));
791 __ LoadRoot(t0, Heap::kWithContextMapRootIndex); 787 __ LoadRoot(a4, Heap::kWithContextMapRootIndex);
792 __ Check(ne, kDeclarationInWithContext, 788 __ Check(ne, kDeclarationInWithContext,
793 a1, Operand(t0)); 789 a1, Operand(a4));
794 __ LoadRoot(t0, Heap::kCatchContextMapRootIndex); 790 __ LoadRoot(a4, Heap::kCatchContextMapRootIndex);
795 __ Check(ne, kDeclarationInCatchContext, 791 __ Check(ne, kDeclarationInCatchContext,
796 a1, Operand(t0)); 792 a1, Operand(a4));
797 } 793 }
798 } 794 }
799 795
800 796
801 void FullCodeGenerator::VisitVariableDeclaration( 797 void FullCodeGenerator::VisitVariableDeclaration(
802 VariableDeclaration* declaration) { 798 VariableDeclaration* declaration) {
803 // If it was not possible to allocate the variable at compile time, we 799 // If it was not possible to allocate the variable at compile time, we
804 // need to "declare" it at runtime to make sure it actually exists in the 800 // need to "declare" it at runtime to make sure it actually exists in the
805 // local context. 801 // local context.
806 VariableProxy* proxy = declaration->proxy(); 802 VariableProxy* proxy = declaration->proxy();
807 VariableMode mode = declaration->mode(); 803 VariableMode mode = declaration->mode();
808 Variable* variable = proxy->var(); 804 Variable* variable = proxy->var();
809 bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY; 805 bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
810 switch (variable->location()) { 806 switch (variable->location()) {
811 case Variable::UNALLOCATED: 807 case Variable::UNALLOCATED:
812 globals_->Add(variable->name(), zone()); 808 globals_->Add(variable->name(), zone());
813 globals_->Add(variable->binding_needs_init() 809 globals_->Add(variable->binding_needs_init()
814 ? isolate()->factory()->the_hole_value() 810 ? isolate()->factory()->the_hole_value()
815 : isolate()->factory()->undefined_value(), 811 : isolate()->factory()->undefined_value(),
816 zone()); 812 zone());
817 break; 813 break;
818 814
819 case Variable::PARAMETER: 815 case Variable::PARAMETER:
820 case Variable::LOCAL: 816 case Variable::LOCAL:
821 if (hole_init) { 817 if (hole_init) {
822 Comment cmnt(masm_, "[ VariableDeclaration"); 818 Comment cmnt(masm_, "[ VariableDeclaration");
823 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); 819 __ LoadRoot(a4, Heap::kTheHoleValueRootIndex);
824 __ sw(t0, StackOperand(variable)); 820 __ sd(a4, StackOperand(variable));
825 } 821 }
826 break; 822 break;
827 823
828 case Variable::CONTEXT: 824 case Variable::CONTEXT:
829 if (hole_init) { 825 if (hole_init) {
830 Comment cmnt(masm_, "[ VariableDeclaration"); 826 Comment cmnt(masm_, "[ VariableDeclaration");
831 EmitDebugCheckDeclarationContext(variable); 827 EmitDebugCheckDeclarationContext(variable);
832 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 828 __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
833 __ sw(at, ContextOperand(cp, variable->index())); 829 __ sd(at, ContextOperand(cp, variable->index()));
834 // No write barrier since the_hole_value is in old space. 830 // No write barrier since the_hole_value is in old space.
835 PrepareForBailoutForId(proxy->id(), NO_REGISTERS); 831 PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
836 } 832 }
837 break; 833 break;
838 834
839 case Variable::LOOKUP: { 835 case Variable::LOOKUP: {
840 Comment cmnt(masm_, "[ VariableDeclaration"); 836 Comment cmnt(masm_, "[ VariableDeclaration");
841 __ li(a2, Operand(variable->name())); 837 __ li(a2, Operand(variable->name()));
842 // Declaration nodes are always introduced in one of four modes. 838 // Declaration nodes are always introduced in one of four modes.
843 ASSERT(IsDeclaredVariableMode(mode)); 839 ASSERT(IsDeclaredVariableMode(mode));
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
875 // Check for stack-overflow exception. 871 // Check for stack-overflow exception.
876 if (function.is_null()) return SetStackOverflow(); 872 if (function.is_null()) return SetStackOverflow();
877 globals_->Add(function, zone()); 873 globals_->Add(function, zone());
878 break; 874 break;
879 } 875 }
880 876
881 case Variable::PARAMETER: 877 case Variable::PARAMETER:
882 case Variable::LOCAL: { 878 case Variable::LOCAL: {
883 Comment cmnt(masm_, "[ FunctionDeclaration"); 879 Comment cmnt(masm_, "[ FunctionDeclaration");
884 VisitForAccumulatorValue(declaration->fun()); 880 VisitForAccumulatorValue(declaration->fun());
885 __ sw(result_register(), StackOperand(variable)); 881 __ sd(result_register(), StackOperand(variable));
886 break; 882 break;
887 } 883 }
888 884
889 case Variable::CONTEXT: { 885 case Variable::CONTEXT: {
890 Comment cmnt(masm_, "[ FunctionDeclaration"); 886 Comment cmnt(masm_, "[ FunctionDeclaration");
891 EmitDebugCheckDeclarationContext(variable); 887 EmitDebugCheckDeclarationContext(variable);
892 VisitForAccumulatorValue(declaration->fun()); 888 VisitForAccumulatorValue(declaration->fun());
893 __ sw(result_register(), ContextOperand(cp, variable->index())); 889 __ sd(result_register(), ContextOperand(cp, variable->index()));
894 int offset = Context::SlotOffset(variable->index()); 890 int offset = Context::SlotOffset(variable->index());
895 // We know that we have written a function, which is not a smi. 891 // We know that we have written a function, which is not a smi.
896 __ RecordWriteContextSlot(cp, 892 __ RecordWriteContextSlot(cp,
897 offset, 893 offset,
898 result_register(), 894 result_register(),
899 a2, 895 a2,
900 kRAHasBeenSaved, 896 kRAHasBeenSaved,
901 kDontSaveFPRegs, 897 kDontSaveFPRegs,
902 EMIT_REMEMBERED_SET, 898 EMIT_REMEMBERED_SET,
903 OMIT_SMI_CHECK); 899 OMIT_SMI_CHECK);
(...skipping 12 matching lines...) Expand all
916 break; 912 break;
917 } 913 }
918 } 914 }
919 } 915 }
920 916
921 917
922 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { 918 void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) {
923 Variable* variable = declaration->proxy()->var(); 919 Variable* variable = declaration->proxy()->var();
924 ASSERT(variable->location() == Variable::CONTEXT); 920 ASSERT(variable->location() == Variable::CONTEXT);
925 ASSERT(variable->interface()->IsFrozen()); 921 ASSERT(variable->interface()->IsFrozen());
926
927 Comment cmnt(masm_, "[ ModuleDeclaration"); 922 Comment cmnt(masm_, "[ ModuleDeclaration");
928 EmitDebugCheckDeclarationContext(variable); 923 EmitDebugCheckDeclarationContext(variable);
929 924
930 // Load instance object. 925 // Load instance object.
931 __ LoadContext(a1, scope_->ContextChainLength(scope_->GlobalScope())); 926 __ LoadContext(a1, scope_->ContextChainLength(scope_->GlobalScope()));
932 __ lw(a1, ContextOperand(a1, variable->interface()->Index())); 927 __ ld(a1, ContextOperand(a1, variable->interface()->Index()));
933 __ lw(a1, ContextOperand(a1, Context::EXTENSION_INDEX)); 928 __ ld(a1, ContextOperand(a1, Context::EXTENSION_INDEX));
934 929
935 // Assign it. 930 // Assign it.
936 __ sw(a1, ContextOperand(cp, variable->index())); 931 __ sd(a1, ContextOperand(cp, variable->index()));
937 // We know that we have written a module, which is not a smi. 932 // We know that we have written a module, which is not a smi.
938 __ RecordWriteContextSlot(cp, 933 __ RecordWriteContextSlot(cp,
939 Context::SlotOffset(variable->index()), 934 Context::SlotOffset(variable->index()),
940 a1, 935 a1,
941 a3, 936 a3,
942 kRAHasBeenSaved, 937 kRAHasBeenSaved,
943 kDontSaveFPRegs, 938 kDontSaveFPRegs,
944 EMIT_REMEMBERED_SET, 939 EMIT_REMEMBERED_SET,
945 OMIT_SMI_CHECK); 940 OMIT_SMI_CHECK);
946 PrepareForBailoutForId(declaration->proxy()->id(), NO_REGISTERS); 941 PrepareForBailoutForId(declaration->proxy()->id(), NO_REGISTERS);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
1023 1018
1024 Comment cmnt(masm_, "[ Case comparison"); 1019 Comment cmnt(masm_, "[ Case comparison");
1025 __ bind(&next_test); 1020 __ bind(&next_test);
1026 next_test.Unuse(); 1021 next_test.Unuse();
1027 1022
1028 // Compile the label expression. 1023 // Compile the label expression.
1029 VisitForAccumulatorValue(clause->label()); 1024 VisitForAccumulatorValue(clause->label());
1030 __ mov(a0, result_register()); // CompareStub requires args in a0, a1. 1025 __ mov(a0, result_register()); // CompareStub requires args in a0, a1.
1031 1026
1032 // Perform the comparison as if via '==='. 1027 // Perform the comparison as if via '==='.
1033 __ lw(a1, MemOperand(sp, 0)); // Switch value. 1028 __ ld(a1, MemOperand(sp, 0)); // Switch value.
1034 bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT); 1029 bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
1035 JumpPatchSite patch_site(masm_); 1030 JumpPatchSite patch_site(masm_);
1036 if (inline_smi_code) { 1031 if (inline_smi_code) {
1037 Label slow_case; 1032 Label slow_case;
1038 __ or_(a2, a1, a0); 1033 __ or_(a2, a1, a0);
1039 patch_site.EmitJumpIfNotSmi(a2, &slow_case); 1034 patch_site.EmitJumpIfNotSmi(a2, &slow_case);
1040 1035
1041 __ Branch(&next_test, ne, a1, Operand(a0)); 1036 __ Branch(&next_test, ne, a1, Operand(a0));
1042 __ Drop(1); // Switch value is no longer needed. 1037 __ Drop(1); // Switch value is no longer needed.
1043 __ Branch(clause->body_target()); 1038 __ Branch(clause->body_target());
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1097 Label loop, exit; 1092 Label loop, exit;
1098 ForIn loop_statement(this, stmt); 1093 ForIn loop_statement(this, stmt);
1099 increment_loop_depth(); 1094 increment_loop_depth();
1100 1095
1101 // Get the object to enumerate over. If the object is null or undefined, skip 1096 // Get the object to enumerate over. If the object is null or undefined, skip
1102 // over the loop. See ECMA-262 version 5, section 12.6.4. 1097 // over the loop. See ECMA-262 version 5, section 12.6.4.
1103 VisitForAccumulatorValue(stmt->enumerable()); 1098 VisitForAccumulatorValue(stmt->enumerable());
1104 __ mov(a0, result_register()); // Result as param to InvokeBuiltin below. 1099 __ mov(a0, result_register()); // Result as param to InvokeBuiltin below.
1105 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); 1100 __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
1106 __ Branch(&exit, eq, a0, Operand(at)); 1101 __ Branch(&exit, eq, a0, Operand(at));
1107 Register null_value = t1; 1102 Register null_value = a5;
1108 __ LoadRoot(null_value, Heap::kNullValueRootIndex); 1103 __ LoadRoot(null_value, Heap::kNullValueRootIndex);
1109 __ Branch(&exit, eq, a0, Operand(null_value)); 1104 __ Branch(&exit, eq, a0, Operand(null_value));
1110 PrepareForBailoutForId(stmt->PrepareId(), TOS_REG); 1105 PrepareForBailoutForId(stmt->PrepareId(), TOS_REG);
1111 __ mov(a0, v0); 1106 __ mov(a0, v0);
1112 // Convert the object to a JS object. 1107 // Convert the object to a JS object.
1113 Label convert, done_convert; 1108 Label convert, done_convert;
1114 __ JumpIfSmi(a0, &convert); 1109 __ JumpIfSmi(a0, &convert);
1115 __ GetObjectType(a0, a1, a1); 1110 __ GetObjectType(a0, a1, a1);
1116 __ Branch(&done_convert, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE)); 1111 __ Branch(&done_convert, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE));
1117 __ bind(&convert); 1112 __ bind(&convert);
(...skipping 11 matching lines...) Expand all
1129 1124
1130 // Check cache validity in generated code. This is a fast case for 1125 // Check cache validity in generated code. This is a fast case for
1131 // the JSObject::IsSimpleEnum cache validity checks. If we cannot 1126 // the JSObject::IsSimpleEnum cache validity checks. If we cannot
1132 // guarantee cache validity, call the runtime system to check cache 1127 // guarantee cache validity, call the runtime system to check cache
1133 // validity or get the property names in a fixed array. 1128 // validity or get the property names in a fixed array.
1134 __ CheckEnumCache(null_value, &call_runtime); 1129 __ CheckEnumCache(null_value, &call_runtime);
1135 1130
1136 // The enum cache is valid. Load the map of the object being 1131 // The enum cache is valid. Load the map of the object being
1137 // iterated over and use the cache for the iteration. 1132 // iterated over and use the cache for the iteration.
1138 Label use_cache; 1133 Label use_cache;
1139 __ lw(v0, FieldMemOperand(a0, HeapObject::kMapOffset)); 1134 __ ld(v0, FieldMemOperand(a0, HeapObject::kMapOffset));
1140 __ Branch(&use_cache); 1135 __ Branch(&use_cache);
1141 1136
1142 // Get the set of properties to enumerate. 1137 // Get the set of properties to enumerate.
1143 __ bind(&call_runtime); 1138 __ bind(&call_runtime);
1144 __ push(a0); // Duplicate the enumerable object on the stack. 1139 __ push(a0); // Duplicate the enumerable object on the stack.
1145 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); 1140 __ CallRuntime(Runtime::kGetPropertyNamesFast, 1);
1146 1141
1147 // If we got a map from the runtime call, we can do a fast 1142 // If we got a map from the runtime call, we can do a fast
1148 // modification check. Otherwise, we got a fixed array, and we have 1143 // modification check. Otherwise, we got a fixed array, and we have
1149 // to do a slow check. 1144 // to do a slow check.
1150 Label fixed_array; 1145 Label fixed_array;
1151 __ lw(a2, FieldMemOperand(v0, HeapObject::kMapOffset)); 1146 __ ld(a2, FieldMemOperand(v0, HeapObject::kMapOffset));
1152 __ LoadRoot(at, Heap::kMetaMapRootIndex); 1147 __ LoadRoot(at, Heap::kMetaMapRootIndex);
1153 __ Branch(&fixed_array, ne, a2, Operand(at)); 1148 __ Branch(&fixed_array, ne, a2, Operand(at));
1154 1149
1155 // We got a map in register v0. Get the enumeration cache from it. 1150 // We got a map in register v0. Get the enumeration cache from it.
1156 Label no_descriptors; 1151 Label no_descriptors;
1157 __ bind(&use_cache); 1152 __ bind(&use_cache);
1158 1153
1159 __ EnumLength(a1, v0); 1154 __ EnumLength(a1, v0);
1160 __ Branch(&no_descriptors, eq, a1, Operand(Smi::FromInt(0))); 1155 __ Branch(&no_descriptors, eq, a1, Operand(Smi::FromInt(0)));
1161 1156
1162 __ LoadInstanceDescriptors(v0, a2); 1157 __ LoadInstanceDescriptors(v0, a2);
1163 __ lw(a2, FieldMemOperand(a2, DescriptorArray::kEnumCacheOffset)); 1158 __ ld(a2, FieldMemOperand(a2, DescriptorArray::kEnumCacheOffset));
1164 __ lw(a2, FieldMemOperand(a2, DescriptorArray::kEnumCacheBridgeCacheOffset)); 1159 __ ld(a2, FieldMemOperand(a2, DescriptorArray::kEnumCacheBridgeCacheOffset));
1165 1160
1166 // Set up the four remaining stack slots. 1161 // Set up the four remaining stack slots.
1167 __ li(a0, Operand(Smi::FromInt(0))); 1162 __ li(a0, Operand(Smi::FromInt(0)));
1168 // Push map, enumeration cache, enumeration cache length (as smi) and zero. 1163 // Push map, enumeration cache, enumeration cache length (as smi) and zero.
1169 __ Push(v0, a2, a1, a0); 1164 __ Push(v0, a2, a1, a0);
1170 __ jmp(&loop); 1165 __ jmp(&loop);
1171 1166
1172 __ bind(&no_descriptors); 1167 __ bind(&no_descriptors);
1173 __ Drop(1); 1168 __ Drop(1);
1174 __ jmp(&exit); 1169 __ jmp(&exit);
1175 1170
1176 // We got a fixed array in register v0. Iterate through that. 1171 // We got a fixed array in register v0. Iterate through that.
1177 Label non_proxy; 1172 Label non_proxy;
1178 __ bind(&fixed_array); 1173 __ bind(&fixed_array);
1179 1174
1180 __ li(a1, FeedbackVector()); 1175 __ li(a1, FeedbackVector());
1181 __ li(a2, Operand(TypeFeedbackInfo::MegamorphicSentinel(isolate()))); 1176 __ li(a2, Operand(TypeFeedbackInfo::MegamorphicSentinel(isolate())));
1182 __ sw(a2, FieldMemOperand(a1, FixedArray::OffsetOfElementAt(slot))); 1177 __ sd(a2, FieldMemOperand(a1, FixedArray::OffsetOfElementAt(slot)));
1183 1178
1184 __ li(a1, Operand(Smi::FromInt(1))); // Smi indicates slow check 1179 __ li(a1, Operand(Smi::FromInt(1))); // Smi indicates slow check
1185 __ lw(a2, MemOperand(sp, 0 * kPointerSize)); // Get enumerated object 1180 __ ld(a2, MemOperand(sp, 0 * kPointerSize)); // Get enumerated object
1186 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 1181 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
1187 __ GetObjectType(a2, a3, a3); 1182 __ GetObjectType(a2, a3, a3);
1188 __ Branch(&non_proxy, gt, a3, Operand(LAST_JS_PROXY_TYPE)); 1183 __ Branch(&non_proxy, gt, a3, Operand(LAST_JS_PROXY_TYPE));
1189 __ li(a1, Operand(Smi::FromInt(0))); // Zero indicates proxy 1184 __ li(a1, Operand(Smi::FromInt(0))); // Zero indicates proxy
1190 __ bind(&non_proxy); 1185 __ bind(&non_proxy);
1191 __ Push(a1, v0); // Smi and array 1186 __ Push(a1, v0); // Smi and array
1192 __ lw(a1, FieldMemOperand(v0, FixedArray::kLengthOffset)); 1187 __ ld(a1, FieldMemOperand(v0, FixedArray::kLengthOffset));
1193 __ li(a0, Operand(Smi::FromInt(0))); 1188 __ li(a0, Operand(Smi::FromInt(0)));
1194 __ Push(a1, a0); // Fixed array length (as smi) and initial index. 1189 __ Push(a1, a0); // Fixed array length (as smi) and initial index.
1195 1190
1196 // Generate code for doing the condition check. 1191 // Generate code for doing the condition check.
1197 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); 1192 PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
1198 __ bind(&loop); 1193 __ bind(&loop);
1199 // Load the current count to a0, load the length to a1. 1194 // Load the current count to a0, load the length to a1.
1200 __ lw(a0, MemOperand(sp, 0 * kPointerSize)); 1195 __ ld(a0, MemOperand(sp, 0 * kPointerSize));
1201 __ lw(a1, MemOperand(sp, 1 * kPointerSize)); 1196 __ ld(a1, MemOperand(sp, 1 * kPointerSize));
1202 __ Branch(loop_statement.break_label(), hs, a0, Operand(a1)); 1197 __ Branch(loop_statement.break_label(), hs, a0, Operand(a1));
1203 1198
1204 // Get the current entry of the array into register a3. 1199 // Get the current entry of the array into register a3.
1205 __ lw(a2, MemOperand(sp, 2 * kPointerSize)); 1200 __ ld(a2, MemOperand(sp, 2 * kPointerSize));
1206 __ Addu(a2, a2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 1201 __ Daddu(a2, a2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
1207 __ sll(t0, a0, kPointerSizeLog2 - kSmiTagSize); 1202 __ SmiScale(a4, a0, kPointerSizeLog2);
1208 __ addu(t0, a2, t0); // Array base + scaled (smi) index. 1203 __ daddu(a4, a2, a4); // Array base + scaled (smi) index.
1209 __ lw(a3, MemOperand(t0)); // Current entry. 1204 __ ld(a3, MemOperand(a4)); // Current entry.
1210 1205
1211 // Get the expected map from the stack or a smi in the 1206 // Get the expected map from the stack or a smi in the
1212 // permanent slow case into register a2. 1207 // permanent slow case into register a2.
1213 __ lw(a2, MemOperand(sp, 3 * kPointerSize)); 1208 __ ld(a2, MemOperand(sp, 3 * kPointerSize));
1214 1209
1215 // Check if the expected map still matches that of the enumerable. 1210 // Check if the expected map still matches that of the enumerable.
1216 // If not, we may have to filter the key. 1211 // If not, we may have to filter the key.
1217 Label update_each; 1212 Label update_each;
1218 __ lw(a1, MemOperand(sp, 4 * kPointerSize)); 1213 __ ld(a1, MemOperand(sp, 4 * kPointerSize));
1219 __ lw(t0, FieldMemOperand(a1, HeapObject::kMapOffset)); 1214 __ ld(a4, FieldMemOperand(a1, HeapObject::kMapOffset));
1220 __ Branch(&update_each, eq, t0, Operand(a2)); 1215 __ Branch(&update_each, eq, a4, Operand(a2));
1221 1216
1222 // For proxies, no filtering is done. 1217 // For proxies, no filtering is done.
1223 // TODO(rossberg): What if only a prototype is a proxy? Not specified yet. 1218 // TODO(rossberg): What if only a prototype is a proxy? Not specified yet.
1224 ASSERT_EQ(Smi::FromInt(0), 0); 1219 ASSERT_EQ(Smi::FromInt(0), 0);
1225 __ Branch(&update_each, eq, a2, Operand(zero_reg)); 1220 __ Branch(&update_each, eq, a2, Operand(zero_reg));
1226 1221
1227 // Convert the entry to a string or (smi) 0 if it isn't a property 1222 // Convert the entry to a string or (smi) 0 if it isn't a property
1228 // any more. If the property has been removed while iterating, we 1223 // any more. If the property has been removed while iterating, we
1229 // just skip it. 1224 // just skip it.
1230 __ Push(a1, a3); // Enumerable and current entry. 1225 __ Push(a1, a3); // Enumerable and current entry.
(...skipping 10 matching lines...) Expand all
1241 EmitAssignment(stmt->each()); 1236 EmitAssignment(stmt->each());
1242 } 1237 }
1243 1238
1244 // Generate code for the body of the loop. 1239 // Generate code for the body of the loop.
1245 Visit(stmt->body()); 1240 Visit(stmt->body());
1246 1241
1247 // Generate code for the going to the next element by incrementing 1242 // Generate code for the going to the next element by incrementing
1248 // the index (smi) stored on top of the stack. 1243 // the index (smi) stored on top of the stack.
1249 __ bind(loop_statement.continue_label()); 1244 __ bind(loop_statement.continue_label());
1250 __ pop(a0); 1245 __ pop(a0);
1251 __ Addu(a0, a0, Operand(Smi::FromInt(1))); 1246 __ Daddu(a0, a0, Operand(Smi::FromInt(1)));
1252 __ push(a0); 1247 __ push(a0);
1253 1248
1254 EmitBackEdgeBookkeeping(stmt, &loop); 1249 EmitBackEdgeBookkeeping(stmt, &loop);
1255 __ Branch(&loop); 1250 __ Branch(&loop);
1256 1251
1257 // Remove the pointers stored on the stack. 1252 // Remove the pointers stored on the stack.
1258 __ bind(loop_statement.break_label()); 1253 __ bind(loop_statement.break_label());
1259 __ Drop(5); 1254 __ Drop(5);
1260 1255
1261 // Exit and decrement the loop depth. 1256 // Exit and decrement the loop depth.
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
1357 Label* slow) { 1352 Label* slow) {
1358 Register current = cp; 1353 Register current = cp;
1359 Register next = a1; 1354 Register next = a1;
1360 Register temp = a2; 1355 Register temp = a2;
1361 1356
1362 Scope* s = scope(); 1357 Scope* s = scope();
1363 while (s != NULL) { 1358 while (s != NULL) {
1364 if (s->num_heap_slots() > 0) { 1359 if (s->num_heap_slots() > 0) {
1365 if (s->calls_sloppy_eval()) { 1360 if (s->calls_sloppy_eval()) {
1366 // Check that extension is NULL. 1361 // Check that extension is NULL.
1367 __ lw(temp, ContextOperand(current, Context::EXTENSION_INDEX)); 1362 __ ld(temp, ContextOperand(current, Context::EXTENSION_INDEX));
1368 __ Branch(slow, ne, temp, Operand(zero_reg)); 1363 __ Branch(slow, ne, temp, Operand(zero_reg));
1369 } 1364 }
1370 // Load next context in chain. 1365 // Load next context in chain.
1371 __ lw(next, ContextOperand(current, Context::PREVIOUS_INDEX)); 1366 __ ld(next, ContextOperand(current, Context::PREVIOUS_INDEX));
1372 // Walk the rest of the chain without clobbering cp. 1367 // Walk the rest of the chain without clobbering cp.
1373 current = next; 1368 current = next;
1374 } 1369 }
1375 // If no outer scope calls eval, we do not need to check more 1370 // If no outer scope calls eval, we do not need to check more
1376 // context extensions. 1371 // context extensions.
1377 if (!s->outer_scope_calls_sloppy_eval() || s->is_eval_scope()) break; 1372 if (!s->outer_scope_calls_sloppy_eval() || s->is_eval_scope()) break;
1378 s = s->outer_scope(); 1373 s = s->outer_scope();
1379 } 1374 }
1380 1375
1381 if (s->is_eval_scope()) { 1376 if (s->is_eval_scope()) {
1382 Label loop, fast; 1377 Label loop, fast;
1383 if (!current.is(next)) { 1378 if (!current.is(next)) {
1384 __ Move(next, current); 1379 __ Move(next, current);
1385 } 1380 }
1386 __ bind(&loop); 1381 __ bind(&loop);
1387 // Terminate at native context. 1382 // Terminate at native context.
1388 __ lw(temp, FieldMemOperand(next, HeapObject::kMapOffset)); 1383 __ ld(temp, FieldMemOperand(next, HeapObject::kMapOffset));
1389 __ LoadRoot(t0, Heap::kNativeContextMapRootIndex); 1384 __ LoadRoot(a4, Heap::kNativeContextMapRootIndex);
1390 __ Branch(&fast, eq, temp, Operand(t0)); 1385 __ Branch(&fast, eq, temp, Operand(a4));
1391 // Check that extension is NULL. 1386 // Check that extension is NULL.
1392 __ lw(temp, ContextOperand(next, Context::EXTENSION_INDEX)); 1387 __ ld(temp, ContextOperand(next, Context::EXTENSION_INDEX));
1393 __ Branch(slow, ne, temp, Operand(zero_reg)); 1388 __ Branch(slow, ne, temp, Operand(zero_reg));
1394 // Load next context in chain. 1389 // Load next context in chain.
1395 __ lw(next, ContextOperand(next, Context::PREVIOUS_INDEX)); 1390 __ ld(next, ContextOperand(next, Context::PREVIOUS_INDEX));
1396 __ Branch(&loop); 1391 __ Branch(&loop);
1397 __ bind(&fast); 1392 __ bind(&fast);
1398 } 1393 }
1399 1394
1400 __ lw(LoadIC::ReceiverRegister(), GlobalObjectOperand()); 1395 __ ld(LoadIC::ReceiverRegister(), GlobalObjectOperand());
1401 __ li(LoadIC::NameRegister(), Operand(var->name())); 1396 __ li(LoadIC::NameRegister(), Operand(var->name()));
1402 ContextualMode mode = (typeof_state == INSIDE_TYPEOF) 1397 ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
1403 ? NOT_CONTEXTUAL 1398 ? NOT_CONTEXTUAL
1404 : CONTEXTUAL; 1399 : CONTEXTUAL;
1405 CallLoadIC(mode); 1400 CallLoadIC(mode);
1406 } 1401 }
1407 1402
1408 1403
1409 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, 1404 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
1410 Label* slow) { 1405 Label* slow) {
1411 ASSERT(var->IsContextSlot()); 1406 ASSERT(var->IsContextSlot());
1412 Register context = cp; 1407 Register context = cp;
1413 Register next = a3; 1408 Register next = a3;
1414 Register temp = t0; 1409 Register temp = a4;
1415 1410
1416 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { 1411 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
1417 if (s->num_heap_slots() > 0) { 1412 if (s->num_heap_slots() > 0) {
1418 if (s->calls_sloppy_eval()) { 1413 if (s->calls_sloppy_eval()) {
1419 // Check that extension is NULL. 1414 // Check that extension is NULL.
1420 __ lw(temp, ContextOperand(context, Context::EXTENSION_INDEX)); 1415 __ ld(temp, ContextOperand(context, Context::EXTENSION_INDEX));
1421 __ Branch(slow, ne, temp, Operand(zero_reg)); 1416 __ Branch(slow, ne, temp, Operand(zero_reg));
1422 } 1417 }
1423 __ lw(next, ContextOperand(context, Context::PREVIOUS_INDEX)); 1418 __ ld(next, ContextOperand(context, Context::PREVIOUS_INDEX));
1424 // Walk the rest of the chain without clobbering cp. 1419 // Walk the rest of the chain without clobbering cp.
1425 context = next; 1420 context = next;
1426 } 1421 }
1427 } 1422 }
1428 // Check that last extension is NULL. 1423 // Check that last extension is NULL.
1429 __ lw(temp, ContextOperand(context, Context::EXTENSION_INDEX)); 1424 __ ld(temp, ContextOperand(context, Context::EXTENSION_INDEX));
1430 __ Branch(slow, ne, temp, Operand(zero_reg)); 1425 __ Branch(slow, ne, temp, Operand(zero_reg));
1431 1426
1432 // This function is used only for loads, not stores, so it's safe to 1427 // This function is used only for loads, not stores, so it's safe to
1433 // return an cp-based operand (the write barrier cannot be allowed to 1428 // return an cp-based operand (the write barrier cannot be allowed to
1434 // destroy the cp register). 1429 // destroy the cp register).
1435 return ContextOperand(context, var->index()); 1430 return ContextOperand(context, var->index());
1436 } 1431 }
1437 1432
1438 1433
1439 void FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var, 1434 void FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var,
1440 TypeofState typeof_state, 1435 TypeofState typeof_state,
1441 Label* slow, 1436 Label* slow,
1442 Label* done) { 1437 Label* done) {
1443 // Generate fast-case code for variables that might be shadowed by 1438 // Generate fast-case code for variables that might be shadowed by
1444 // eval-introduced variables. Eval is used a lot without 1439 // eval-introduced variables. Eval is used a lot without
1445 // introducing variables. In those cases, we do not want to 1440 // introducing variables. In those cases, we do not want to
1446 // perform a runtime call for all variables in the scope 1441 // perform a runtime call for all variables in the scope
1447 // containing the eval. 1442 // containing the eval.
1448 if (var->mode() == DYNAMIC_GLOBAL) { 1443 if (var->mode() == DYNAMIC_GLOBAL) {
1449 EmitLoadGlobalCheckExtensions(var, typeof_state, slow); 1444 EmitLoadGlobalCheckExtensions(var, typeof_state, slow);
1450 __ Branch(done); 1445 __ Branch(done);
1451 } else if (var->mode() == DYNAMIC_LOCAL) { 1446 } else if (var->mode() == DYNAMIC_LOCAL) {
1452 Variable* local = var->local_if_not_shadowed(); 1447 Variable* local = var->local_if_not_shadowed();
1453 __ lw(v0, ContextSlotOperandCheckExtensions(local, slow)); 1448 __ ld(v0, ContextSlotOperandCheckExtensions(local, slow));
1454 if (local->mode() == LET || local->mode() == CONST || 1449 if (local->mode() == LET || local->mode() == CONST ||
1455 local->mode() == CONST_LEGACY) { 1450 local->mode() == CONST_LEGACY) {
1456 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 1451 __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
1457 __ subu(at, v0, at); // Sub as compare: at == 0 on eq. 1452 __ dsubu(at, v0, at); // Sub as compare: at == 0 on eq.
1458 if (local->mode() == CONST_LEGACY) { 1453 if (local->mode() == CONST_LEGACY) {
1459 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); 1454 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex);
1460 __ Movz(v0, a0, at); // Conditional move: return Undefined if TheHole. 1455 __ Movz(v0, a0, at); // Conditional move: return Undefined if TheHole.
1461 } else { // LET || CONST 1456 } else { // LET || CONST
1462 __ Branch(done, ne, at, Operand(zero_reg)); 1457 __ Branch(done, ne, at, Operand(zero_reg));
1463 __ li(a0, Operand(var->name())); 1458 __ li(a0, Operand(var->name()));
1464 __ push(a0); 1459 __ push(a0);
1465 __ CallRuntime(Runtime::kThrowReferenceError, 1); 1460 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1466 } 1461 }
1467 } 1462 }
1468 __ Branch(done); 1463 __ Branch(done);
1469 } 1464 }
1470 } 1465 }
1471 1466
1472 1467
1473 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { 1468 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
1474 // Record position before possible IC call. 1469 // Record position before possible IC call.
1475 SetSourcePosition(proxy->position()); 1470 SetSourcePosition(proxy->position());
1476 Variable* var = proxy->var(); 1471 Variable* var = proxy->var();
1477 1472
1478 // Three cases: global variables, lookup variables, and all other types of 1473 // Three cases: global variables, lookup variables, and all other types of
1479 // variables. 1474 // variables.
1480 switch (var->location()) { 1475 switch (var->location()) {
1481 case Variable::UNALLOCATED: { 1476 case Variable::UNALLOCATED: {
1482 Comment cmnt(masm_, "[ Global variable"); 1477 Comment cmnt(masm_, "[ Global variable");
1483 __ lw(LoadIC::ReceiverRegister(), GlobalObjectOperand()); 1478 // Use inline caching. Variable name is passed in a2 and the global
1479 // object (receiver) in a0.
1480 __ ld(LoadIC::ReceiverRegister(), GlobalObjectOperand());
1484 __ li(LoadIC::NameRegister(), Operand(var->name())); 1481 __ li(LoadIC::NameRegister(), Operand(var->name()));
1485 CallLoadIC(CONTEXTUAL); 1482 CallLoadIC(CONTEXTUAL);
1486 context()->Plug(v0); 1483 context()->Plug(v0);
1487 break; 1484 break;
1488 } 1485 }
1489 1486
1490 case Variable::PARAMETER: 1487 case Variable::PARAMETER:
1491 case Variable::LOCAL: 1488 case Variable::LOCAL:
1492 case Variable::CONTEXT: { 1489 case Variable::CONTEXT: {
1493 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" 1490 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
(...skipping 30 matching lines...) Expand all
1524 ASSERT(var->initializer_position() != RelocInfo::kNoPosition); 1521 ASSERT(var->initializer_position() != RelocInfo::kNoPosition);
1525 ASSERT(proxy->position() != RelocInfo::kNoPosition); 1522 ASSERT(proxy->position() != RelocInfo::kNoPosition);
1526 skip_init_check = var->mode() != CONST_LEGACY && 1523 skip_init_check = var->mode() != CONST_LEGACY &&
1527 var->initializer_position() < proxy->position(); 1524 var->initializer_position() < proxy->position();
1528 } 1525 }
1529 1526
1530 if (!skip_init_check) { 1527 if (!skip_init_check) {
1531 // Let and const need a read barrier. 1528 // Let and const need a read barrier.
1532 GetVar(v0, var); 1529 GetVar(v0, var);
1533 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 1530 __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
1534 __ subu(at, v0, at); // Sub as compare: at == 0 on eq. 1531 __ dsubu(at, v0, at); // Sub as compare: at == 0 on eq.
1535 if (var->mode() == LET || var->mode() == CONST) { 1532 if (var->mode() == LET || var->mode() == CONST) {
1536 // Throw a reference error when using an uninitialized let/const 1533 // Throw a reference error when using an uninitialized let/const
1537 // binding in harmony mode. 1534 // binding in harmony mode.
1538 Label done; 1535 Label done;
1539 __ Branch(&done, ne, at, Operand(zero_reg)); 1536 __ Branch(&done, ne, at, Operand(zero_reg));
1540 __ li(a0, Operand(var->name())); 1537 __ li(a0, Operand(var->name()));
1541 __ push(a0); 1538 __ push(a0);
1542 __ CallRuntime(Runtime::kThrowReferenceError, 1); 1539 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1543 __ bind(&done); 1540 __ bind(&done);
1544 } else { 1541 } else {
(...skipping 24 matching lines...) Expand all
1569 context()->Plug(v0); 1566 context()->Plug(v0);
1570 } 1567 }
1571 } 1568 }
1572 } 1569 }
1573 1570
1574 1571
1575 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 1572 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1576 Comment cmnt(masm_, "[ RegExpLiteral"); 1573 Comment cmnt(masm_, "[ RegExpLiteral");
1577 Label materialized; 1574 Label materialized;
1578 // Registers will be used as follows: 1575 // Registers will be used as follows:
1579 // t1 = materialized value (RegExp literal) 1576 // a5 = materialized value (RegExp literal)
1580 // t0 = JS function, literals array 1577 // a4 = JS function, literals array
1581 // a3 = literal index 1578 // a3 = literal index
1582 // a2 = RegExp pattern 1579 // a2 = RegExp pattern
1583 // a1 = RegExp flags 1580 // a1 = RegExp flags
1584 // a0 = RegExp literal clone 1581 // a0 = RegExp literal clone
1585 __ lw(a0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 1582 __ ld(a0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
1586 __ lw(t0, FieldMemOperand(a0, JSFunction::kLiteralsOffset)); 1583 __ ld(a4, FieldMemOperand(a0, JSFunction::kLiteralsOffset));
1587 int literal_offset = 1584 int literal_offset =
1588 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; 1585 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
1589 __ lw(t1, FieldMemOperand(t0, literal_offset)); 1586 __ ld(a5, FieldMemOperand(a4, literal_offset));
1590 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); 1587 __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
1591 __ Branch(&materialized, ne, t1, Operand(at)); 1588 __ Branch(&materialized, ne, a5, Operand(at));
1592 1589
1593 // Create regexp literal using runtime function. 1590 // Create regexp literal using runtime function.
1594 // Result will be in v0. 1591 // Result will be in v0.
1595 __ li(a3, Operand(Smi::FromInt(expr->literal_index()))); 1592 __ li(a3, Operand(Smi::FromInt(expr->literal_index())));
1596 __ li(a2, Operand(expr->pattern())); 1593 __ li(a2, Operand(expr->pattern()));
1597 __ li(a1, Operand(expr->flags())); 1594 __ li(a1, Operand(expr->flags()));
1598 __ Push(t0, a3, a2, a1); 1595 __ Push(a4, a3, a2, a1);
1599 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 1596 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
1600 __ mov(t1, v0); 1597 __ mov(a5, v0);
1601 1598
1602 __ bind(&materialized); 1599 __ bind(&materialized);
1603 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; 1600 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
1604 Label allocated, runtime_allocate; 1601 Label allocated, runtime_allocate;
1605 __ Allocate(size, v0, a2, a3, &runtime_allocate, TAG_OBJECT); 1602 __ Allocate(size, v0, a2, a3, &runtime_allocate, TAG_OBJECT);
1606 __ jmp(&allocated); 1603 __ jmp(&allocated);
1607 1604
1608 __ bind(&runtime_allocate); 1605 __ bind(&runtime_allocate);
1609 __ li(a0, Operand(Smi::FromInt(size))); 1606 __ li(a0, Operand(Smi::FromInt(size)));
1610 __ Push(t1, a0); 1607 __ Push(a5, a0);
1611 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); 1608 __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
1612 __ pop(t1); 1609 __ pop(a5);
1613 1610
1614 __ bind(&allocated); 1611 __ bind(&allocated);
1615 1612
1616 // After this, registers are used as follows: 1613 // After this, registers are used as follows:
1617 // v0: Newly allocated regexp. 1614 // v0: Newly allocated regexp.
1618 // t1: Materialized regexp. 1615 // a5: Materialized regexp.
1619 // a2: temp. 1616 // a2: temp.
1620 __ CopyFields(v0, t1, a2.bit(), size / kPointerSize); 1617 __ CopyFields(v0, a5, a2.bit(), size / kPointerSize);
1621 context()->Plug(v0); 1618 context()->Plug(v0);
1622 } 1619 }
1623 1620
1624 1621
1625 void FullCodeGenerator::EmitAccessor(Expression* expression) { 1622 void FullCodeGenerator::EmitAccessor(Expression* expression) {
1626 if (expression == NULL) { 1623 if (expression == NULL) {
1627 __ LoadRoot(a1, Heap::kNullValueRootIndex); 1624 __ LoadRoot(a1, Heap::kNullValueRootIndex);
1628 __ push(a1); 1625 __ push(a1);
1629 } else { 1626 } else {
1630 VisitForStackValue(expression); 1627 VisitForStackValue(expression);
1631 } 1628 }
1632 } 1629 }
1633 1630
1634 1631
1635 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 1632 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1636 Comment cmnt(masm_, "[ ObjectLiteral"); 1633 Comment cmnt(masm_, "[ ObjectLiteral");
1637 1634
1638 expr->BuildConstantProperties(isolate()); 1635 expr->BuildConstantProperties(isolate());
1639 Handle<FixedArray> constant_properties = expr->constant_properties(); 1636 Handle<FixedArray> constant_properties = expr->constant_properties();
1640 __ lw(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 1637 __ ld(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
1641 __ lw(a3, FieldMemOperand(a3, JSFunction::kLiteralsOffset)); 1638 __ ld(a3, FieldMemOperand(a3, JSFunction::kLiteralsOffset));
1642 __ li(a2, Operand(Smi::FromInt(expr->literal_index()))); 1639 __ li(a2, Operand(Smi::FromInt(expr->literal_index())));
1643 __ li(a1, Operand(constant_properties)); 1640 __ li(a1, Operand(constant_properties));
1644 int flags = expr->fast_elements() 1641 int flags = expr->fast_elements()
1645 ? ObjectLiteral::kFastElements 1642 ? ObjectLiteral::kFastElements
1646 : ObjectLiteral::kNoFlags; 1643 : ObjectLiteral::kNoFlags;
1647 flags |= expr->has_function() 1644 flags |= expr->has_function()
1648 ? ObjectLiteral::kHasFunction 1645 ? ObjectLiteral::kHasFunction
1649 : ObjectLiteral::kNoFlags; 1646 : ObjectLiteral::kNoFlags;
1650 __ li(a0, Operand(Smi::FromInt(flags))); 1647 __ li(a0, Operand(Smi::FromInt(flags)));
1651 int properties_count = constant_properties->length() / 2; 1648 int properties_count = constant_properties->length() / 2;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1684 UNREACHABLE(); 1681 UNREACHABLE();
1685 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1682 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1686 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); 1683 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value()));
1687 // Fall through. 1684 // Fall through.
1688 case ObjectLiteral::Property::COMPUTED: 1685 case ObjectLiteral::Property::COMPUTED:
1689 if (key->value()->IsInternalizedString()) { 1686 if (key->value()->IsInternalizedString()) {
1690 if (property->emit_store()) { 1687 if (property->emit_store()) {
1691 VisitForAccumulatorValue(value); 1688 VisitForAccumulatorValue(value);
1692 __ mov(a0, result_register()); 1689 __ mov(a0, result_register());
1693 __ li(a2, Operand(key->value())); 1690 __ li(a2, Operand(key->value()));
1694 __ lw(a1, MemOperand(sp)); 1691 __ ld(a1, MemOperand(sp));
1695 CallStoreIC(key->LiteralFeedbackId()); 1692 CallStoreIC(key->LiteralFeedbackId());
1696 PrepareForBailoutForId(key->id(), NO_REGISTERS); 1693 PrepareForBailoutForId(key->id(), NO_REGISTERS);
1697 } else { 1694 } else {
1698 VisitForEffect(value); 1695 VisitForEffect(value);
1699 } 1696 }
1700 break; 1697 break;
1701 } 1698 }
1702 // Duplicate receiver on stack. 1699 // Duplicate receiver on stack.
1703 __ lw(a0, MemOperand(sp)); 1700 __ ld(a0, MemOperand(sp));
1704 __ push(a0); 1701 __ push(a0);
1705 VisitForStackValue(key); 1702 VisitForStackValue(key);
1706 VisitForStackValue(value); 1703 VisitForStackValue(value);
1707 if (property->emit_store()) { 1704 if (property->emit_store()) {
1708 __ li(a0, Operand(Smi::FromInt(SLOPPY))); // PropertyAttributes. 1705 __ li(a0, Operand(Smi::FromInt(SLOPPY))); // PropertyAttributes.
1709 __ push(a0); 1706 __ push(a0);
1710 __ CallRuntime(Runtime::kSetProperty, 4); 1707 __ CallRuntime(Runtime::kSetProperty, 4);
1711 } else { 1708 } else {
1712 __ Drop(3); 1709 __ Drop(3);
1713 } 1710 }
1714 break; 1711 break;
1715 case ObjectLiteral::Property::PROTOTYPE: 1712 case ObjectLiteral::Property::PROTOTYPE:
1716 // Duplicate receiver on stack. 1713 // Duplicate receiver on stack.
1717 __ lw(a0, MemOperand(sp)); 1714 __ ld(a0, MemOperand(sp));
1718 __ push(a0); 1715 __ push(a0);
1719 VisitForStackValue(value); 1716 VisitForStackValue(value);
1720 if (property->emit_store()) { 1717 if (property->emit_store()) {
1721 __ CallRuntime(Runtime::kSetPrototype, 2); 1718 __ CallRuntime(Runtime::kSetPrototype, 2);
1722 } else { 1719 } else {
1723 __ Drop(2); 1720 __ Drop(2);
1724 } 1721 }
1725 break; 1722 break;
1726 case ObjectLiteral::Property::GETTER: 1723 case ObjectLiteral::Property::GETTER:
1727 accessor_table.lookup(key)->second->getter = value; 1724 accessor_table.lookup(key)->second->getter = value;
1728 break; 1725 break;
1729 case ObjectLiteral::Property::SETTER: 1726 case ObjectLiteral::Property::SETTER:
1730 accessor_table.lookup(key)->second->setter = value; 1727 accessor_table.lookup(key)->second->setter = value;
1731 break; 1728 break;
1732 } 1729 }
1733 } 1730 }
1734 1731
1735 // Emit code to define accessors, using only a single call to the runtime for 1732 // Emit code to define accessors, using only a single call to the runtime for
1736 // each pair of corresponding getters and setters. 1733 // each pair of corresponding getters and setters.
1737 for (AccessorTable::Iterator it = accessor_table.begin(); 1734 for (AccessorTable::Iterator it = accessor_table.begin();
1738 it != accessor_table.end(); 1735 it != accessor_table.end();
1739 ++it) { 1736 ++it) {
1740 __ lw(a0, MemOperand(sp)); // Duplicate receiver. 1737 __ ld(a0, MemOperand(sp)); // Duplicate receiver.
1741 __ push(a0); 1738 __ push(a0);
1742 VisitForStackValue(it->first); 1739 VisitForStackValue(it->first);
1743 EmitAccessor(it->second->getter); 1740 EmitAccessor(it->second->getter);
1744 EmitAccessor(it->second->setter); 1741 EmitAccessor(it->second->setter);
1745 __ li(a0, Operand(Smi::FromInt(NONE))); 1742 __ li(a0, Operand(Smi::FromInt(NONE)));
1746 __ push(a0); 1743 __ push(a0);
1747 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); 1744 __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
1748 } 1745 }
1749 1746
1750 if (expr->has_function()) { 1747 if (expr->has_function()) {
1751 ASSERT(result_saved); 1748 ASSERT(result_saved);
1752 __ lw(a0, MemOperand(sp)); 1749 __ ld(a0, MemOperand(sp));
1753 __ push(a0); 1750 __ push(a0);
1754 __ CallRuntime(Runtime::kToFastProperties, 1); 1751 __ CallRuntime(Runtime::kToFastProperties, 1);
1755 } 1752 }
1756 1753
1757 if (result_saved) { 1754 if (result_saved) {
1758 context()->PlugTOS(); 1755 context()->PlugTOS();
1759 } else { 1756 } else {
1760 context()->Plug(v0); 1757 context()->Plug(v0);
1761 } 1758 }
1762 } 1759 }
(...skipping 20 matching lines...) Expand all
1783 FixedArrayBase::cast(constant_elements->get(1))); 1780 FixedArrayBase::cast(constant_elements->get(1)));
1784 1781
1785 AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE; 1782 AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
1786 if (has_fast_elements && !FLAG_allocation_site_pretenuring) { 1783 if (has_fast_elements && !FLAG_allocation_site_pretenuring) {
1787 // If the only customer of allocation sites is transitioning, then 1784 // If the only customer of allocation sites is transitioning, then
1788 // we can turn it off if we don't have anywhere else to transition to. 1785 // we can turn it off if we don't have anywhere else to transition to.
1789 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; 1786 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE;
1790 } 1787 }
1791 1788
1792 __ mov(a0, result_register()); 1789 __ mov(a0, result_register());
1793 __ lw(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 1790 __ ld(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
1794 __ lw(a3, FieldMemOperand(a3, JSFunction::kLiteralsOffset)); 1791 __ ld(a3, FieldMemOperand(a3, JSFunction::kLiteralsOffset));
1795 __ li(a2, Operand(Smi::FromInt(expr->literal_index()))); 1792 __ li(a2, Operand(Smi::FromInt(expr->literal_index())));
1796 __ li(a1, Operand(constant_elements)); 1793 __ li(a1, Operand(constant_elements));
1797 if (expr->depth() > 1 || length > JSObject::kInitialMaxFastElementArray) { 1794 if (expr->depth() > 1 || length > JSObject::kInitialMaxFastElementArray) {
1798 __ li(a0, Operand(Smi::FromInt(flags))); 1795 __ li(a0, Operand(Smi::FromInt(flags)));
1799 __ Push(a3, a2, a1, a0); 1796 __ Push(a3, a2, a1, a0);
1800 __ CallRuntime(Runtime::kCreateArrayLiteral, 4); 1797 __ CallRuntime(Runtime::kCreateArrayLiteral, 4);
1801 } else { 1798 } else {
1802 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); 1799 FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
1803 __ CallStub(&stub); 1800 __ CallStub(&stub);
1804 } 1801 }
(...skipping 11 matching lines...) Expand all
1816 if (!result_saved) { 1813 if (!result_saved) {
1817 __ push(v0); // array literal 1814 __ push(v0); // array literal
1818 __ Push(Smi::FromInt(expr->literal_index())); 1815 __ Push(Smi::FromInt(expr->literal_index()));
1819 result_saved = true; 1816 result_saved = true;
1820 } 1817 }
1821 1818
1822 VisitForAccumulatorValue(subexpr); 1819 VisitForAccumulatorValue(subexpr);
1823 1820
1824 if (IsFastObjectElementsKind(constant_elements_kind)) { 1821 if (IsFastObjectElementsKind(constant_elements_kind)) {
1825 int offset = FixedArray::kHeaderSize + (i * kPointerSize); 1822 int offset = FixedArray::kHeaderSize + (i * kPointerSize);
1826 __ lw(t2, MemOperand(sp, kPointerSize)); // Copy of array literal. 1823 __ ld(a6, MemOperand(sp, kPointerSize)); // Copy of array literal.
1827 __ lw(a1, FieldMemOperand(t2, JSObject::kElementsOffset)); 1824 __ ld(a1, FieldMemOperand(a6, JSObject::kElementsOffset));
1828 __ sw(result_register(), FieldMemOperand(a1, offset)); 1825 __ sd(result_register(), FieldMemOperand(a1, offset));
1829 // Update the write barrier for the array store. 1826 // Update the write barrier for the array store.
1830 __ RecordWriteField(a1, offset, result_register(), a2, 1827 __ RecordWriteField(a1, offset, result_register(), a2,
1831 kRAHasBeenSaved, kDontSaveFPRegs, 1828 kRAHasBeenSaved, kDontSaveFPRegs,
1832 EMIT_REMEMBERED_SET, INLINE_SMI_CHECK); 1829 EMIT_REMEMBERED_SET, INLINE_SMI_CHECK);
1833 } else { 1830 } else {
1834 __ li(a3, Operand(Smi::FromInt(i))); 1831 __ li(a3, Operand(Smi::FromInt(i)));
1835 __ mov(a0, result_register()); 1832 __ mov(a0, result_register());
1836 StoreArrayLiteralElementStub stub(isolate()); 1833 StoreArrayLiteralElementStub stub(isolate());
1837 __ CallStub(&stub); 1834 __ CallStub(&stub);
1838 } 1835 }
(...skipping 27 matching lines...) Expand all
1866 1863
1867 // Evaluate LHS expression. 1864 // Evaluate LHS expression.
1868 switch (assign_type) { 1865 switch (assign_type) {
1869 case VARIABLE: 1866 case VARIABLE:
1870 // Nothing to do here. 1867 // Nothing to do here.
1871 break; 1868 break;
1872 case NAMED_PROPERTY: 1869 case NAMED_PROPERTY:
1873 if (expr->is_compound()) { 1870 if (expr->is_compound()) {
1874 // We need the receiver both on the stack and in the register. 1871 // We need the receiver both on the stack and in the register.
1875 VisitForStackValue(property->obj()); 1872 VisitForStackValue(property->obj());
1876 __ lw(LoadIC::ReceiverRegister(), MemOperand(sp, 0)); 1873 __ ld(LoadIC::ReceiverRegister(), MemOperand(sp, 0));
1877 } else { 1874 } else {
1878 VisitForStackValue(property->obj()); 1875 VisitForStackValue(property->obj());
1879 } 1876 }
1880 break; 1877 break;
1881 case KEYED_PROPERTY: 1878 case KEYED_PROPERTY:
1882 // We need the key and receiver on both the stack and in v0 and a1. 1879 // We need the key and receiver on both the stack and in v0 and a1.
1883 if (expr->is_compound()) { 1880 if (expr->is_compound()) {
1884 VisitForStackValue(property->obj()); 1881 VisitForStackValue(property->obj());
1885 VisitForStackValue(property->key()); 1882 VisitForStackValue(property->key());
1886 __ lw(LoadIC::ReceiverRegister(), MemOperand(sp, 1 * kPointerSize)); 1883 __ ld(LoadIC::ReceiverRegister(), MemOperand(sp, 1 * kPointerSize));
1887 __ lw(LoadIC::NameRegister(), MemOperand(sp, 0)); 1884 __ ld(LoadIC::NameRegister(), MemOperand(sp, 0));
1888 } else { 1885 } else {
1889 VisitForStackValue(property->obj()); 1886 VisitForStackValue(property->obj());
1890 VisitForStackValue(property->key()); 1887 VisitForStackValue(property->key());
1891 } 1888 }
1892 break; 1889 break;
1893 } 1890 }
1894 1891
1895 // For compound assignments we need another deoptimization point after the 1892 // For compound assignments we need another deoptimization point after the
1896 // variable/property load. 1893 // variable/property load.
1897 if (expr->is_compound()) { 1894 if (expr->is_compound()) {
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1975 1972
1976 __ jmp(&suspend); 1973 __ jmp(&suspend);
1977 1974
1978 __ bind(&continuation); 1975 __ bind(&continuation);
1979 __ jmp(&resume); 1976 __ jmp(&resume);
1980 1977
1981 __ bind(&suspend); 1978 __ bind(&suspend);
1982 VisitForAccumulatorValue(expr->generator_object()); 1979 VisitForAccumulatorValue(expr->generator_object());
1983 ASSERT(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); 1980 ASSERT(continuation.pos() > 0 && Smi::IsValid(continuation.pos()));
1984 __ li(a1, Operand(Smi::FromInt(continuation.pos()))); 1981 __ li(a1, Operand(Smi::FromInt(continuation.pos())));
1985 __ sw(a1, FieldMemOperand(v0, JSGeneratorObject::kContinuationOffset)); 1982 __ sd(a1, FieldMemOperand(v0, JSGeneratorObject::kContinuationOffset));
1986 __ sw(cp, FieldMemOperand(v0, JSGeneratorObject::kContextOffset)); 1983 __ sd(cp, FieldMemOperand(v0, JSGeneratorObject::kContextOffset));
1987 __ mov(a1, cp); 1984 __ mov(a1, cp);
1988 __ RecordWriteField(v0, JSGeneratorObject::kContextOffset, a1, a2, 1985 __ RecordWriteField(v0, JSGeneratorObject::kContextOffset, a1, a2,
1989 kRAHasBeenSaved, kDontSaveFPRegs); 1986 kRAHasBeenSaved, kDontSaveFPRegs);
1990 __ Addu(a1, fp, Operand(StandardFrameConstants::kExpressionsOffset)); 1987 __ Daddu(a1, fp, Operand(StandardFrameConstants::kExpressionsOffset));
1991 __ Branch(&post_runtime, eq, sp, Operand(a1)); 1988 __ Branch(&post_runtime, eq, sp, Operand(a1));
1992 __ push(v0); // generator object 1989 __ push(v0); // generator object
1993 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); 1990 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
1994 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 1991 __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
1995 __ bind(&post_runtime); 1992 __ bind(&post_runtime);
1996 __ pop(result_register()); 1993 __ pop(result_register());
1997 EmitReturnSequence(); 1994 EmitReturnSequence();
1998 1995
1999 __ bind(&resume); 1996 __ bind(&resume);
2000 context()->Plug(result_register()); 1997 context()->Plug(result_register());
2001 break; 1998 break;
2002 } 1999 }
2003 2000
2004 case Yield::FINAL: { 2001 case Yield::FINAL: {
2005 VisitForAccumulatorValue(expr->generator_object()); 2002 VisitForAccumulatorValue(expr->generator_object());
2006 __ li(a1, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorClosed))); 2003 __ li(a1, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorClosed)));
2007 __ sw(a1, FieldMemOperand(result_register(), 2004 __ sd(a1, FieldMemOperand(result_register(),
2008 JSGeneratorObject::kContinuationOffset)); 2005 JSGeneratorObject::kContinuationOffset));
2009 // Pop value from top-of-stack slot, box result into result register. 2006 // Pop value from top-of-stack slot, box result into result register.
2010 EmitCreateIteratorResult(true); 2007 EmitCreateIteratorResult(true);
2011 EmitUnwindBeforeReturn(); 2008 EmitUnwindBeforeReturn();
2012 EmitReturnSequence(); 2009 EmitReturnSequence();
2013 break; 2010 break;
2014 } 2011 }
2015 2012
2016 case Yield::DELEGATING: { 2013 case Yield::DELEGATING: {
2017 VisitForStackValue(expr->generator_object()); 2014 VisitForStackValue(expr->generator_object());
2018 2015
2019 // Initial stack layout is as follows: 2016 // Initial stack layout is as follows:
2020 // [sp + 1 * kPointerSize] iter 2017 // [sp + 1 * kPointerSize] iter
2021 // [sp + 0 * kPointerSize] g 2018 // [sp + 0 * kPointerSize] g
2022 2019
2023 Label l_catch, l_try, l_suspend, l_continuation, l_resume; 2020 Label l_catch, l_try, l_suspend, l_continuation, l_resume;
2024 Label l_next, l_call; 2021 Label l_next, l_call;
2025 Register load_receiver = LoadIC::ReceiverRegister(); 2022 Register load_receiver = LoadIC::ReceiverRegister();
2026 Register load_name = LoadIC::NameRegister(); 2023 Register load_name = LoadIC::NameRegister();
2027
2028 // Initial send value is undefined. 2024 // Initial send value is undefined.
2029 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); 2025 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex);
2030 __ Branch(&l_next); 2026 __ Branch(&l_next);
2031 2027
2032 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } 2028 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
2033 __ bind(&l_catch); 2029 __ bind(&l_catch);
2034 __ mov(a0, v0); 2030 __ mov(a0, v0);
2035 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); 2031 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
2036 __ LoadRoot(load_name, Heap::kthrow_stringRootIndex); // "throw" 2032 __ LoadRoot(a2, Heap::kthrow_stringRootIndex); // "throw"
2037 __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter 2033 __ ld(a3, MemOperand(sp, 1 * kPointerSize)); // iter
2038 __ Push(load_name, a3, a0); // "throw", iter, except 2034 __ Push(a2, a3, a0); // "throw", iter, except
2039 __ jmp(&l_call); 2035 __ jmp(&l_call);
2040 2036
2041 // try { received = %yield result } 2037 // try { received = %yield result }
2042 // Shuffle the received result above a try handler and yield it without 2038 // Shuffle the received result above a try handler and yield it without
2043 // re-boxing. 2039 // re-boxing.
2044 __ bind(&l_try); 2040 __ bind(&l_try);
2045 __ pop(a0); // result 2041 __ pop(a0); // result
2046 __ PushTryHandler(StackHandler::CATCH, expr->index()); 2042 __ PushTryHandler(StackHandler::CATCH, expr->index());
2047 const int handler_size = StackHandlerConstants::kSize; 2043 const int handler_size = StackHandlerConstants::kSize;
2048 __ push(a0); // result 2044 __ push(a0); // result
2049 __ jmp(&l_suspend); 2045 __ jmp(&l_suspend);
2050 __ bind(&l_continuation); 2046 __ bind(&l_continuation);
2051 __ mov(a0, v0); 2047 __ mov(a0, v0);
2052 __ jmp(&l_resume); 2048 __ jmp(&l_resume);
2053 __ bind(&l_suspend); 2049 __ bind(&l_suspend);
2054 const int generator_object_depth = kPointerSize + handler_size; 2050 const int generator_object_depth = kPointerSize + handler_size;
2055 __ lw(a0, MemOperand(sp, generator_object_depth)); 2051 __ ld(a0, MemOperand(sp, generator_object_depth));
2056 __ push(a0); // g 2052 __ push(a0); // g
2057 ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); 2053 ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos()));
2058 __ li(a1, Operand(Smi::FromInt(l_continuation.pos()))); 2054 __ li(a1, Operand(Smi::FromInt(l_continuation.pos())));
2059 __ sw(a1, FieldMemOperand(a0, JSGeneratorObject::kContinuationOffset)); 2055 __ sd(a1, FieldMemOperand(a0, JSGeneratorObject::kContinuationOffset));
2060 __ sw(cp, FieldMemOperand(a0, JSGeneratorObject::kContextOffset)); 2056 __ sd(cp, FieldMemOperand(a0, JSGeneratorObject::kContextOffset));
2061 __ mov(a1, cp); 2057 __ mov(a1, cp);
2062 __ RecordWriteField(a0, JSGeneratorObject::kContextOffset, a1, a2, 2058 __ RecordWriteField(a0, JSGeneratorObject::kContextOffset, a1, a2,
2063 kRAHasBeenSaved, kDontSaveFPRegs); 2059 kRAHasBeenSaved, kDontSaveFPRegs);
2064 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); 2060 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
2065 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2061 __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2066 __ pop(v0); // result 2062 __ pop(v0); // result
2067 EmitReturnSequence(); 2063 EmitReturnSequence();
2068 __ mov(a0, v0); 2064 __ mov(a0, v0);
2069 __ bind(&l_resume); // received in a0 2065 __ bind(&l_resume); // received in a0
2070 __ PopTryHandler(); 2066 __ PopTryHandler();
2071 2067
2072 // receiver = iter; f = 'next'; arg = received; 2068 // receiver = iter; f = 'next'; arg = received;
2073 __ bind(&l_next); 2069 __ bind(&l_next);
2074
2075 __ LoadRoot(load_name, Heap::knext_stringRootIndex); // "next" 2070 __ LoadRoot(load_name, Heap::knext_stringRootIndex); // "next"
2076 __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter 2071 __ ld(a3, MemOperand(sp, 1 * kPointerSize)); // iter
2077 __ Push(load_name, a3, a0); // "next", iter, received 2072 __ Push(load_name, a3, a0); // "next", iter, received
2078 2073
2079 // result = receiver[f](arg); 2074 // result = receiver[f](arg);
2080 __ bind(&l_call); 2075 __ bind(&l_call);
2081 __ lw(load_receiver, MemOperand(sp, kPointerSize)); 2076 __ ld(load_receiver, MemOperand(sp, kPointerSize));
2082 __ lw(load_name, MemOperand(sp, 2 * kPointerSize)); 2077 __ ld(load_name, MemOperand(sp, 2 * kPointerSize));
2083 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); 2078 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
2084 CallIC(ic, TypeFeedbackId::None()); 2079 CallIC(ic, TypeFeedbackId::None());
2085 __ mov(a0, v0); 2080 __ mov(a0, v0);
2086 __ mov(a1, a0); 2081 __ mov(a1, a0);
2087 __ sw(a1, MemOperand(sp, 2 * kPointerSize)); 2082 __ sd(a1, MemOperand(sp, 2 * kPointerSize));
2088 CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD); 2083 CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD);
2089 __ CallStub(&stub); 2084 __ CallStub(&stub);
2090 2085
2091 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2086 __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2092 __ Drop(1); // The function is still on the stack; drop it. 2087 __ Drop(1); // The function is still on the stack; drop it.
2093 2088
2094 // if (!result.done) goto l_try; 2089 // if (!result.done) goto l_try;
2095 __ Move(load_receiver, v0); 2090 __ Move(load_receiver, v0);
2096 2091
2097 __ push(load_receiver); // save result 2092 __ push(load_receiver); // save result
2098 __ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done" 2093 __ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done"
2099 CallLoadIC(NOT_CONTEXTUAL); // v0=result.done 2094 CallLoadIC(NOT_CONTEXTUAL); // v0=result.done
2100 __ mov(a0, v0); 2095 __ mov(a0, v0);
2101 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); 2096 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
2102 CallIC(bool_ic); 2097 CallIC(bool_ic);
2103 __ Branch(&l_try, eq, v0, Operand(zero_reg)); 2098 __ Branch(&l_try, eq, v0, Operand(zero_reg));
2104 2099
2105 // result.value 2100 // result.value
2106 __ pop(load_receiver); // result 2101 __ pop(load_receiver); // result
2107 __ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value" 2102 __ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value"
(...skipping 11 matching lines...) Expand all
2119 // The value stays in a0, and is ultimately read by the resumed generator, as 2114 // The value stays in a0, and is ultimately read by the resumed generator, as
2120 // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it 2115 // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it
2121 // is read to throw the value when the resumed generator is already closed. 2116 // is read to throw the value when the resumed generator is already closed.
2122 // a1 will hold the generator object until the activation has been resumed. 2117 // a1 will hold the generator object until the activation has been resumed.
2123 VisitForStackValue(generator); 2118 VisitForStackValue(generator);
2124 VisitForAccumulatorValue(value); 2119 VisitForAccumulatorValue(value);
2125 __ pop(a1); 2120 __ pop(a1);
2126 2121
2127 // Check generator state. 2122 // Check generator state.
2128 Label wrong_state, closed_state, done; 2123 Label wrong_state, closed_state, done;
2129 __ lw(a3, FieldMemOperand(a1, JSGeneratorObject::kContinuationOffset)); 2124 __ ld(a3, FieldMemOperand(a1, JSGeneratorObject::kContinuationOffset));
2130 STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0); 2125 STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0);
2131 STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0); 2126 STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0);
2132 __ Branch(&closed_state, eq, a3, Operand(zero_reg)); 2127 __ Branch(&closed_state, eq, a3, Operand(zero_reg));
2133 __ Branch(&wrong_state, lt, a3, Operand(zero_reg)); 2128 __ Branch(&wrong_state, lt, a3, Operand(zero_reg));
2134 2129
2135 // Load suspended function and context. 2130 // Load suspended function and context.
2136 __ lw(cp, FieldMemOperand(a1, JSGeneratorObject::kContextOffset)); 2131 __ ld(cp, FieldMemOperand(a1, JSGeneratorObject::kContextOffset));
2137 __ lw(t0, FieldMemOperand(a1, JSGeneratorObject::kFunctionOffset)); 2132 __ ld(a4, FieldMemOperand(a1, JSGeneratorObject::kFunctionOffset));
2138 2133
2139 // Load receiver and store as the first argument. 2134 // Load receiver and store as the first argument.
2140 __ lw(a2, FieldMemOperand(a1, JSGeneratorObject::kReceiverOffset)); 2135 __ ld(a2, FieldMemOperand(a1, JSGeneratorObject::kReceiverOffset));
2141 __ push(a2); 2136 __ push(a2);
2142 2137
2143 // Push holes for the rest of the arguments to the generator function. 2138 // Push holes for the rest of the arguments to the generator function.
2144 __ lw(a3, FieldMemOperand(t0, JSFunction::kSharedFunctionInfoOffset)); 2139 __ ld(a3, FieldMemOperand(a4, JSFunction::kSharedFunctionInfoOffset));
2140 // The argument count is stored as int32_t on 64-bit platforms.
2141 // TODO(plind): Smi on 32-bit platforms.
2145 __ lw(a3, 2142 __ lw(a3,
2146 FieldMemOperand(a3, SharedFunctionInfo::kFormalParameterCountOffset)); 2143 FieldMemOperand(a3, SharedFunctionInfo::kFormalParameterCountOffset));
2147 __ LoadRoot(a2, Heap::kTheHoleValueRootIndex); 2144 __ LoadRoot(a2, Heap::kTheHoleValueRootIndex);
2148 Label push_argument_holes, push_frame; 2145 Label push_argument_holes, push_frame;
2149 __ bind(&push_argument_holes); 2146 __ bind(&push_argument_holes);
2150 __ Subu(a3, a3, Operand(Smi::FromInt(1))); 2147 __ Dsubu(a3, a3, Operand(1));
2151 __ Branch(&push_frame, lt, a3, Operand(zero_reg)); 2148 __ Branch(&push_frame, lt, a3, Operand(zero_reg));
2152 __ push(a2); 2149 __ push(a2);
2153 __ jmp(&push_argument_holes); 2150 __ jmp(&push_argument_holes);
2154 2151
2155 // Enter a new JavaScript frame, and initialize its slots as they were when 2152 // Enter a new JavaScript frame, and initialize its slots as they were when
2156 // the generator was suspended. 2153 // the generator was suspended.
2157 Label resume_frame; 2154 Label resume_frame;
2158 __ bind(&push_frame); 2155 __ bind(&push_frame);
2159 __ Call(&resume_frame); 2156 __ Call(&resume_frame);
2160 __ jmp(&done); 2157 __ jmp(&done);
2161 __ bind(&resume_frame); 2158 __ bind(&resume_frame);
2162 // ra = return address. 2159 // ra = return address.
2163 // fp = caller's frame pointer. 2160 // fp = caller's frame pointer.
2164 // cp = callee's context, 2161 // cp = callee's context,
2165 // t0 = callee's JS function. 2162 // a4 = callee's JS function.
2166 __ Push(ra, fp, cp, t0); 2163 __ Push(ra, fp, cp, a4);
2167 // Adjust FP to point to saved FP. 2164 // Adjust FP to point to saved FP.
2168 __ Addu(fp, sp, 2 * kPointerSize); 2165 __ Daddu(fp, sp, 2 * kPointerSize);
2169 2166
2170 // Load the operand stack size. 2167 // Load the operand stack size.
2171 __ lw(a3, FieldMemOperand(a1, JSGeneratorObject::kOperandStackOffset)); 2168 __ ld(a3, FieldMemOperand(a1, JSGeneratorObject::kOperandStackOffset));
2172 __ lw(a3, FieldMemOperand(a3, FixedArray::kLengthOffset)); 2169 __ ld(a3, FieldMemOperand(a3, FixedArray::kLengthOffset));
2173 __ SmiUntag(a3); 2170 __ SmiUntag(a3);
2174 2171
2175 // If we are sending a value and there is no operand stack, we can jump back 2172 // If we are sending a value and there is no operand stack, we can jump back
2176 // in directly. 2173 // in directly.
2177 if (resume_mode == JSGeneratorObject::NEXT) { 2174 if (resume_mode == JSGeneratorObject::NEXT) {
2178 Label slow_resume; 2175 Label slow_resume;
2179 __ Branch(&slow_resume, ne, a3, Operand(zero_reg)); 2176 __ Branch(&slow_resume, ne, a3, Operand(zero_reg));
2180 __ lw(a3, FieldMemOperand(t0, JSFunction::kCodeEntryOffset)); 2177 __ ld(a3, FieldMemOperand(a4, JSFunction::kCodeEntryOffset));
2181 __ lw(a2, FieldMemOperand(a1, JSGeneratorObject::kContinuationOffset)); 2178 __ ld(a2, FieldMemOperand(a1, JSGeneratorObject::kContinuationOffset));
2182 __ SmiUntag(a2); 2179 __ SmiUntag(a2);
2183 __ Addu(a3, a3, Operand(a2)); 2180 __ Daddu(a3, a3, Operand(a2));
2184 __ li(a2, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting))); 2181 __ li(a2, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)));
2185 __ sw(a2, FieldMemOperand(a1, JSGeneratorObject::kContinuationOffset)); 2182 __ sd(a2, FieldMemOperand(a1, JSGeneratorObject::kContinuationOffset));
2186 __ Jump(a3); 2183 __ Jump(a3);
2187 __ bind(&slow_resume); 2184 __ bind(&slow_resume);
2188 } 2185 }
2189 2186
2190 // Otherwise, we push holes for the operand stack and call the runtime to fix 2187 // Otherwise, we push holes for the operand stack and call the runtime to fix
2191 // up the stack and the handlers. 2188 // up the stack and the handlers.
2192 Label push_operand_holes, call_resume; 2189 Label push_operand_holes, call_resume;
2193 __ bind(&push_operand_holes); 2190 __ bind(&push_operand_holes);
2194 __ Subu(a3, a3, Operand(1)); 2191 __ Dsubu(a3, a3, Operand(1));
2195 __ Branch(&call_resume, lt, a3, Operand(zero_reg)); 2192 __ Branch(&call_resume, lt, a3, Operand(zero_reg));
2196 __ push(a2); 2193 __ push(a2);
2197 __ Branch(&push_operand_holes); 2194 __ Branch(&push_operand_holes);
2198 __ bind(&call_resume); 2195 __ bind(&call_resume);
2199 ASSERT(!result_register().is(a1)); 2196 ASSERT(!result_register().is(a1));
2200 __ Push(a1, result_register()); 2197 __ Push(a1, result_register());
2201 __ Push(Smi::FromInt(resume_mode)); 2198 __ Push(Smi::FromInt(resume_mode));
2202 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); 2199 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3);
2203 // Not reached: the runtime call returns elsewhere. 2200 // Not reached: the runtime call returns elsewhere.
2204 __ stop("not-reached"); 2201 __ stop("not-reached");
(...skipping 28 matching lines...) Expand all
2233 Label allocated; 2230 Label allocated;
2234 2231
2235 Handle<Map> map(isolate()->native_context()->iterator_result_map()); 2232 Handle<Map> map(isolate()->native_context()->iterator_result_map());
2236 2233
2237 __ Allocate(map->instance_size(), v0, a2, a3, &gc_required, TAG_OBJECT); 2234 __ Allocate(map->instance_size(), v0, a2, a3, &gc_required, TAG_OBJECT);
2238 __ jmp(&allocated); 2235 __ jmp(&allocated);
2239 2236
2240 __ bind(&gc_required); 2237 __ bind(&gc_required);
2241 __ Push(Smi::FromInt(map->instance_size())); 2238 __ Push(Smi::FromInt(map->instance_size()));
2242 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); 2239 __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
2243 __ lw(context_register(), 2240 __ ld(context_register(),
2244 MemOperand(fp, StandardFrameConstants::kContextOffset)); 2241 MemOperand(fp, StandardFrameConstants::kContextOffset));
2245 2242
2246 __ bind(&allocated); 2243 __ bind(&allocated);
2247 __ li(a1, Operand(map)); 2244 __ li(a1, Operand(map));
2248 __ pop(a2); 2245 __ pop(a2);
2249 __ li(a3, Operand(isolate()->factory()->ToBoolean(done))); 2246 __ li(a3, Operand(isolate()->factory()->ToBoolean(done)));
2250 __ li(t0, Operand(isolate()->factory()->empty_fixed_array())); 2247 __ li(a4, Operand(isolate()->factory()->empty_fixed_array()));
2251 ASSERT_EQ(map->instance_size(), 5 * kPointerSize); 2248 ASSERT_EQ(map->instance_size(), 5 * kPointerSize);
2252 __ sw(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); 2249 __ sd(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
2253 __ sw(t0, FieldMemOperand(v0, JSObject::kPropertiesOffset)); 2250 __ sd(a4, FieldMemOperand(v0, JSObject::kPropertiesOffset));
2254 __ sw(t0, FieldMemOperand(v0, JSObject::kElementsOffset)); 2251 __ sd(a4, FieldMemOperand(v0, JSObject::kElementsOffset));
2255 __ sw(a2, 2252 __ sd(a2,
2256 FieldMemOperand(v0, JSGeneratorObject::kResultValuePropertyOffset)); 2253 FieldMemOperand(v0, JSGeneratorObject::kResultValuePropertyOffset));
2257 __ sw(a3, 2254 __ sd(a3,
2258 FieldMemOperand(v0, JSGeneratorObject::kResultDonePropertyOffset)); 2255 FieldMemOperand(v0, JSGeneratorObject::kResultDonePropertyOffset));
2259 2256
2260 // Only the value field needs a write barrier, as the other values are in the 2257 // Only the value field needs a write barrier, as the other values are in the
2261 // root set. 2258 // root set.
2262 __ RecordWriteField(v0, JSGeneratorObject::kResultValuePropertyOffset, 2259 __ RecordWriteField(v0, JSGeneratorObject::kResultValuePropertyOffset,
2263 a2, a3, kRAHasBeenSaved, kDontSaveFPRegs); 2260 a2, a3, kRAHasBeenSaved, kDontSaveFPRegs);
2264 } 2261 }
2265 2262
2266 2263
2267 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { 2264 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2308 CallIC(stub.GetCode(), expr->BinaryOperationFeedbackId()); 2305 CallIC(stub.GetCode(), expr->BinaryOperationFeedbackId());
2309 patch_site.EmitPatchInfo(); 2306 patch_site.EmitPatchInfo();
2310 __ jmp(&done); 2307 __ jmp(&done);
2311 2308
2312 __ bind(&smi_case); 2309 __ bind(&smi_case);
2313 // Smi case. This code works the same way as the smi-smi case in the type 2310 // Smi case. This code works the same way as the smi-smi case in the type
2314 // recording binary operation stub, see 2311 // recording binary operation stub, see
2315 switch (op) { 2312 switch (op) {
2316 case Token::SAR: 2313 case Token::SAR:
2317 __ GetLeastBitsFromSmi(scratch1, right, 5); 2314 __ GetLeastBitsFromSmi(scratch1, right, 5);
2318 __ srav(right, left, scratch1); 2315 __ dsrav(right, left, scratch1);
2319 __ And(v0, right, Operand(~kSmiTagMask)); 2316 __ And(v0, right, Operand(0xffffffff00000000L));
2320 break; 2317 break;
2321 case Token::SHL: { 2318 case Token::SHL: {
2322 __ SmiUntag(scratch1, left); 2319 __ SmiUntag(scratch1, left);
2323 __ GetLeastBitsFromSmi(scratch2, right, 5); 2320 __ GetLeastBitsFromSmi(scratch2, right, 5);
2324 __ sllv(scratch1, scratch1, scratch2); 2321 __ dsllv(scratch1, scratch1, scratch2);
2325 __ Addu(scratch2, scratch1, Operand(0x40000000));
2326 __ Branch(&stub_call, lt, scratch2, Operand(zero_reg));
2327 __ SmiTag(v0, scratch1); 2322 __ SmiTag(v0, scratch1);
2328 break; 2323 break;
2329 } 2324 }
2330 case Token::SHR: { 2325 case Token::SHR: {
2331 __ SmiUntag(scratch1, left); 2326 __ SmiUntag(scratch1, left);
2332 __ GetLeastBitsFromSmi(scratch2, right, 5); 2327 __ GetLeastBitsFromSmi(scratch2, right, 5);
2333 __ srlv(scratch1, scratch1, scratch2); 2328 __ dsrlv(scratch1, scratch1, scratch2);
2334 __ And(scratch2, scratch1, 0xc0000000); 2329 __ And(scratch2, scratch1, 0x80000000);
2335 __ Branch(&stub_call, ne, scratch2, Operand(zero_reg)); 2330 __ Branch(&stub_call, ne, scratch2, Operand(zero_reg));
2336 __ SmiTag(v0, scratch1); 2331 __ SmiTag(v0, scratch1);
2337 break; 2332 break;
2338 } 2333 }
2339 case Token::ADD: 2334 case Token::ADD:
2340 __ AdduAndCheckForOverflow(v0, left, right, scratch1); 2335 __ AdduAndCheckForOverflow(v0, left, right, scratch1);
2341 __ BranchOnOverflow(&stub_call, scratch1); 2336 __ BranchOnOverflow(&stub_call, scratch1);
2342 break; 2337 break;
2343 case Token::SUB: 2338 case Token::SUB:
2344 __ SubuAndCheckForOverflow(v0, left, right, scratch1); 2339 __ SubuAndCheckForOverflow(v0, left, right, scratch1);
2345 __ BranchOnOverflow(&stub_call, scratch1); 2340 __ BranchOnOverflow(&stub_call, scratch1);
2346 break; 2341 break;
2347 case Token::MUL: { 2342 case Token::MUL: {
2348 __ SmiUntag(scratch1, right); 2343 __ SmiUntag(scratch1, right);
2349 __ Mult(left, scratch1); 2344 __ Dmult(left, scratch1);
2350 __ mflo(scratch1); 2345 __ mflo(scratch1);
2351 __ mfhi(scratch2); 2346 __ mfhi(scratch2);
2352 __ sra(scratch1, scratch1, 31); 2347 __ dsra32(scratch1, scratch1, 31);
2353 __ Branch(&stub_call, ne, scratch1, Operand(scratch2)); 2348 __ Branch(&stub_call, ne, scratch1, Operand(scratch2));
2354 __ mflo(v0); 2349 __ mflo(v0);
2355 __ Branch(&done, ne, v0, Operand(zero_reg)); 2350 __ Branch(&done, ne, v0, Operand(zero_reg));
2356 __ Addu(scratch2, right, left); 2351 __ Daddu(scratch2, right, left);
2357 __ Branch(&stub_call, lt, scratch2, Operand(zero_reg)); 2352 __ Branch(&stub_call, lt, scratch2, Operand(zero_reg));
2358 ASSERT(Smi::FromInt(0) == 0); 2353 ASSERT(Smi::FromInt(0) == 0);
2359 __ mov(v0, zero_reg); 2354 __ mov(v0, zero_reg);
2360 break; 2355 break;
2361 } 2356 }
2362 case Token::BIT_OR: 2357 case Token::BIT_OR:
2363 __ Or(v0, left, Operand(right)); 2358 __ Or(v0, left, Operand(right));
2364 break; 2359 break;
2365 case Token::BIT_AND: 2360 case Token::BIT_AND:
2366 __ And(v0, left, Operand(right)); 2361 __ And(v0, left, Operand(right));
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
2432 CallIC(ic); 2427 CallIC(ic);
2433 break; 2428 break;
2434 } 2429 }
2435 } 2430 }
2436 context()->Plug(v0); 2431 context()->Plug(v0);
2437 } 2432 }
2438 2433
2439 2434
2440 void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( 2435 void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
2441 Variable* var, MemOperand location) { 2436 Variable* var, MemOperand location) {
2442 __ sw(result_register(), location); 2437 __ sd(result_register(), location);
2443 if (var->IsContextSlot()) { 2438 if (var->IsContextSlot()) {
2444 // RecordWrite may destroy all its register arguments. 2439 // RecordWrite may destroy all its register arguments.
2445 __ Move(a3, result_register()); 2440 __ Move(a3, result_register());
2446 int offset = Context::SlotOffset(var->index()); 2441 int offset = Context::SlotOffset(var->index());
2447 __ RecordWriteContextSlot( 2442 __ RecordWriteContextSlot(
2448 a1, offset, a3, a2, kRAHasBeenSaved, kDontSaveFPRegs); 2443 a1, offset, a3, a2, kRAHasBeenSaved, kDontSaveFPRegs);
2449 } 2444 }
2450 } 2445 }
2451 2446
2452 2447
2453 void FullCodeGenerator::EmitCallStoreContextSlot( 2448 void FullCodeGenerator::EmitCallStoreContextSlot(
2454 Handle<String> name, StrictMode strict_mode) { 2449 Handle<String> name, StrictMode strict_mode) {
2455 __ li(a1, Operand(name)); 2450 __ li(a1, Operand(name));
2456 __ li(a0, Operand(Smi::FromInt(strict_mode))); 2451 __ li(a0, Operand(Smi::FromInt(strict_mode)));
2457 __ Push(v0, cp, a1, a0); // Value, context, name, strict mode. 2452 __ Push(v0, cp, a1, a0); // Value, context, name, strict mode.
2458 __ CallRuntime(Runtime::kStoreContextSlot, 4); 2453 __ CallRuntime(Runtime::kStoreContextSlot, 4);
2459 } 2454 }
2460 2455
2461 2456
2462 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { 2457 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) {
2463 if (var->IsUnallocated()) { 2458 if (var->IsUnallocated()) {
2464 // Global var, const, or let. 2459 // Global var, const, or let.
2465 __ mov(a0, result_register()); 2460 __ mov(a0, result_register());
2466 __ li(a2, Operand(var->name())); 2461 __ li(a2, Operand(var->name()));
2467 __ lw(a1, GlobalObjectOperand()); 2462 __ ld(a1, GlobalObjectOperand());
2468 CallStoreIC(); 2463 CallStoreIC();
2469
2470 } else if (op == Token::INIT_CONST_LEGACY) { 2464 } else if (op == Token::INIT_CONST_LEGACY) {
2471 // Const initializers need a write barrier. 2465 // Const initializers need a write barrier.
2472 ASSERT(!var->IsParameter()); // No const parameters. 2466 ASSERT(!var->IsParameter()); // No const parameters.
2473 if (var->IsLookupSlot()) { 2467 if (var->IsLookupSlot()) {
2474 __ li(a0, Operand(var->name())); 2468 __ li(a0, Operand(var->name()));
2475 __ Push(v0, cp, a0); // Context and name. 2469 __ Push(v0, cp, a0); // Context and name.
2476 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); 2470 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
2477 } else { 2471 } else {
2478 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 2472 ASSERT(var->IsStackAllocated() || var->IsContextSlot());
2479 Label skip; 2473 Label skip;
2480 MemOperand location = VarOperand(var, a1); 2474 MemOperand location = VarOperand(var, a1);
2481 __ lw(a2, location); 2475 __ ld(a2, location);
2482 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 2476 __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
2483 __ Branch(&skip, ne, a2, Operand(at)); 2477 __ Branch(&skip, ne, a2, Operand(at));
2484 EmitStoreToStackLocalOrContextSlot(var, location); 2478 EmitStoreToStackLocalOrContextSlot(var, location);
2485 __ bind(&skip); 2479 __ bind(&skip);
2486 } 2480 }
2487 2481
2488 } else if (var->mode() == LET && op != Token::INIT_LET) { 2482 } else if (var->mode() == LET && op != Token::INIT_LET) {
2489 // Non-initializing assignment to let variable needs a write barrier. 2483 // Non-initializing assignment to let variable needs a write barrier.
2490 if (var->IsLookupSlot()) { 2484 if (var->IsLookupSlot()) {
2491 EmitCallStoreContextSlot(var->name(), strict_mode()); 2485 EmitCallStoreContextSlot(var->name(), strict_mode());
2492 } else { 2486 } else {
2493 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 2487 ASSERT(var->IsStackAllocated() || var->IsContextSlot());
2494 Label assign; 2488 Label assign;
2495 MemOperand location = VarOperand(var, a1); 2489 MemOperand location = VarOperand(var, a1);
2496 __ lw(a3, location); 2490 __ ld(a3, location);
2497 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); 2491 __ LoadRoot(a4, Heap::kTheHoleValueRootIndex);
2498 __ Branch(&assign, ne, a3, Operand(t0)); 2492 __ Branch(&assign, ne, a3, Operand(a4));
2499 __ li(a3, Operand(var->name())); 2493 __ li(a3, Operand(var->name()));
2500 __ push(a3); 2494 __ push(a3);
2501 __ CallRuntime(Runtime::kThrowReferenceError, 1); 2495 __ CallRuntime(Runtime::kThrowReferenceError, 1);
2502 // Perform the assignment. 2496 // Perform the assignment.
2503 __ bind(&assign); 2497 __ bind(&assign);
2504 EmitStoreToStackLocalOrContextSlot(var, location); 2498 EmitStoreToStackLocalOrContextSlot(var, location);
2505 } 2499 }
2506 2500
2507 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { 2501 } else if (!var->is_const_mode() || op == Token::INIT_CONST) {
2508 // Assignment to var or initializing assignment to let/const 2502 // Assignment to var or initializing assignment to let/const
2509 // in harmony mode. 2503 // in harmony mode.
2510 if (var->IsLookupSlot()) { 2504 if (var->IsLookupSlot()) {
2511 EmitCallStoreContextSlot(var->name(), strict_mode()); 2505 EmitCallStoreContextSlot(var->name(), strict_mode());
2512 } else { 2506 } else {
2513 ASSERT((var->IsStackAllocated() || var->IsContextSlot())); 2507 ASSERT((var->IsStackAllocated() || var->IsContextSlot()));
2514 MemOperand location = VarOperand(var, a1); 2508 MemOperand location = VarOperand(var, a1);
2515 if (generate_debug_code_ && op == Token::INIT_LET) { 2509 if (generate_debug_code_ && op == Token::INIT_LET) {
2516 // Check for an uninitialized let binding. 2510 // Check for an uninitialized let binding.
2517 __ lw(a2, location); 2511 __ ld(a2, location);
2518 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); 2512 __ LoadRoot(a4, Heap::kTheHoleValueRootIndex);
2519 __ Check(eq, kLetBindingReInitialization, a2, Operand(t0)); 2513 __ Check(eq, kLetBindingReInitialization, a2, Operand(a4));
2520 } 2514 }
2521 EmitStoreToStackLocalOrContextSlot(var, location); 2515 EmitStoreToStackLocalOrContextSlot(var, location);
2522 } 2516 }
2523 } 2517 }
2524 // Non-initializing assignments to consts are ignored. 2518 // Non-initializing assignments to consts are ignored.
2525 } 2519 }
2526 2520
2527 2521
2528 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 2522 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
2529 // Assignment to a property, using a named store IC. 2523 // Assignment to a property, using a named store IC.
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
2608 { StackValueContext context(this); 2602 { StackValueContext context(this);
2609 EmitVariableLoad(callee->AsVariableProxy()); 2603 EmitVariableLoad(callee->AsVariableProxy());
2610 PrepareForBailout(callee, NO_REGISTERS); 2604 PrepareForBailout(callee, NO_REGISTERS);
2611 } 2605 }
2612 // Push undefined as receiver. This is patched in the method prologue if it 2606 // Push undefined as receiver. This is patched in the method prologue if it
2613 // is a sloppy mode method. 2607 // is a sloppy mode method.
2614 __ Push(isolate()->factory()->undefined_value()); 2608 __ Push(isolate()->factory()->undefined_value());
2615 } else { 2609 } else {
2616 // Load the function from the receiver. 2610 // Load the function from the receiver.
2617 ASSERT(callee->IsProperty()); 2611 ASSERT(callee->IsProperty());
2618 __ lw(LoadIC::ReceiverRegister(), MemOperand(sp, 0)); 2612 __ ld(LoadIC::ReceiverRegister(), MemOperand(sp, 0));
2619 EmitNamedPropertyLoad(callee->AsProperty()); 2613 EmitNamedPropertyLoad(callee->AsProperty());
2620 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); 2614 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2621 // Push the target function under the receiver. 2615 // Push the target function under the receiver.
2622 __ lw(at, MemOperand(sp, 0)); 2616 __ ld(at, MemOperand(sp, 0));
2623 __ push(at); 2617 __ push(at);
2624 __ sw(v0, MemOperand(sp, kPointerSize)); 2618 __ sd(v0, MemOperand(sp, kPointerSize));
2625 } 2619 }
2626 2620
2627 EmitCall(expr, call_type); 2621 EmitCall(expr, call_type);
2628 } 2622 }
2629 2623
2630 2624
2631 // Code common for calls using the IC. 2625 // Code common for calls using the IC.
2632 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, 2626 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
2633 Expression* key) { 2627 Expression* key) {
2634 // Load the key. 2628 // Load the key.
2635 VisitForAccumulatorValue(key); 2629 VisitForAccumulatorValue(key);
2636 2630
2637 Expression* callee = expr->expression(); 2631 Expression* callee = expr->expression();
2638 2632
2639 // Load the function from the receiver. 2633 // Load the function from the receiver.
2640 ASSERT(callee->IsProperty()); 2634 ASSERT(callee->IsProperty());
2641 __ lw(LoadIC::ReceiverRegister(), MemOperand(sp, 0)); 2635 __ ld(LoadIC::ReceiverRegister(), MemOperand(sp, 0));
2642 __ Move(LoadIC::NameRegister(), v0); 2636 __ Move(LoadIC::NameRegister(), v0);
2643 EmitKeyedPropertyLoad(callee->AsProperty()); 2637 EmitKeyedPropertyLoad(callee->AsProperty());
2644 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); 2638 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2645 2639
2646 // Push the target function under the receiver. 2640 // Push the target function under the receiver.
2647 __ lw(at, MemOperand(sp, 0)); 2641 __ ld(at, MemOperand(sp, 0));
2648 __ push(at); 2642 __ push(at);
2649 __ sw(v0, MemOperand(sp, kPointerSize)); 2643 __ sd(v0, MemOperand(sp, kPointerSize));
2650 2644
2651 EmitCall(expr, CallIC::METHOD); 2645 EmitCall(expr, CallIC::METHOD);
2652 } 2646 }
2653 2647
2654 2648
2655 void FullCodeGenerator::EmitCall(Call* expr, CallIC::CallType call_type) { 2649 void FullCodeGenerator::EmitCall(Call* expr, CallIC::CallType call_type) {
2656 // Load the arguments. 2650 // Load the arguments.
2657 ZoneList<Expression*>* args = expr->arguments(); 2651 ZoneList<Expression*>* args = expr->arguments();
2658 int arg_count = args->length(); 2652 int arg_count = args->length();
2659 { PreservePositionScope scope(masm()->positions_recorder()); 2653 { PreservePositionScope scope(masm()->positions_recorder());
2660 for (int i = 0; i < arg_count; i++) { 2654 for (int i = 0; i < arg_count; i++) {
2661 VisitForStackValue(args->at(i)); 2655 VisitForStackValue(args->at(i));
2662 } 2656 }
2663 } 2657 }
2664 2658
2665 // Record source position of the IC call. 2659 // Record source position of the IC call.
2666 SetSourcePosition(expr->position()); 2660 SetSourcePosition(expr->position());
2667 Handle<Code> ic = CallIC::initialize_stub( 2661 Handle<Code> ic = CallIC::initialize_stub(
2668 isolate(), arg_count, call_type); 2662 isolate(), arg_count, call_type);
2669 __ li(a3, Operand(Smi::FromInt(expr->CallFeedbackSlot()))); 2663 __ li(a3, Operand(Smi::FromInt(expr->CallFeedbackSlot())));
2670 __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize)); 2664 __ ld(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
2671 // Don't assign a type feedback id to the IC, since type feedback is provided 2665 // Don't assign a type feedback id to the IC, since type feedback is provided
2672 // by the vector above. 2666 // by the vector above.
2673 CallIC(ic); 2667 CallIC(ic);
2674
2675 RecordJSReturnSite(expr); 2668 RecordJSReturnSite(expr);
2676 // Restore context register. 2669 // Restore context register.
2677 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2670 __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2678 context()->DropAndPlug(1, v0); 2671 context()->DropAndPlug(1, v0);
2679 } 2672 }
2680 2673
2681 2674
2682 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { 2675 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
2683 // t2: copy of the first argument or undefined if it doesn't exist. 2676 // a6: copy of the first argument or undefined if it doesn't exist.
2684 if (arg_count > 0) { 2677 if (arg_count > 0) {
2685 __ lw(t2, MemOperand(sp, arg_count * kPointerSize)); 2678 __ ld(a6, MemOperand(sp, arg_count * kPointerSize));
2686 } else { 2679 } else {
2687 __ LoadRoot(t2, Heap::kUndefinedValueRootIndex); 2680 __ LoadRoot(a6, Heap::kUndefinedValueRootIndex);
2688 } 2681 }
2689 2682
2690 // t1: the receiver of the enclosing function. 2683 // a5: the receiver of the enclosing function.
2691 int receiver_offset = 2 + info_->scope()->num_parameters(); 2684 int receiver_offset = 2 + info_->scope()->num_parameters();
2692 __ lw(t1, MemOperand(fp, receiver_offset * kPointerSize)); 2685 __ ld(a5, MemOperand(fp, receiver_offset * kPointerSize));
2693 2686
2694 // t0: the strict mode. 2687 // a4: the strict mode.
2695 __ li(t0, Operand(Smi::FromInt(strict_mode()))); 2688 __ li(a4, Operand(Smi::FromInt(strict_mode())));
2696 2689
2697 // a1: the start position of the scope the calls resides in. 2690 // a1: the start position of the scope the calls resides in.
2698 __ li(a1, Operand(Smi::FromInt(scope()->start_position()))); 2691 __ li(a1, Operand(Smi::FromInt(scope()->start_position())));
2699 2692
2700 // Do the runtime call. 2693 // Do the runtime call.
2701 __ Push(t2, t1, t0, a1); 2694 __ Push(a6, a5, a4, a1);
2702 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); 2695 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
2703 } 2696 }
2704 2697
2705 2698
2706 void FullCodeGenerator::VisitCall(Call* expr) { 2699 void FullCodeGenerator::VisitCall(Call* expr) {
2707 #ifdef DEBUG 2700 #ifdef DEBUG
2708 // We want to verify that RecordJSReturnSite gets called on all paths 2701 // We want to verify that RecordJSReturnSite gets called on all paths
2709 // through this function. Avoid early returns. 2702 // through this function. Avoid early returns.
2710 expr->return_is_recorded_ = false; 2703 expr->return_is_recorded_ = false;
2711 #endif 2704 #endif
(...skipping 15 matching lines...) Expand all
2727 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex); 2720 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
2728 __ push(a2); // Reserved receiver slot. 2721 __ push(a2); // Reserved receiver slot.
2729 2722
2730 // Push the arguments. 2723 // Push the arguments.
2731 for (int i = 0; i < arg_count; i++) { 2724 for (int i = 0; i < arg_count; i++) {
2732 VisitForStackValue(args->at(i)); 2725 VisitForStackValue(args->at(i));
2733 } 2726 }
2734 2727
2735 // Push a copy of the function (found below the arguments) and 2728 // Push a copy of the function (found below the arguments) and
2736 // resolve eval. 2729 // resolve eval.
2737 __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize)); 2730 __ ld(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
2738 __ push(a1); 2731 __ push(a1);
2739 EmitResolvePossiblyDirectEval(arg_count); 2732 EmitResolvePossiblyDirectEval(arg_count);
2740 2733
2741 // The runtime call returns a pair of values in v0 (function) and 2734 // The runtime call returns a pair of values in v0 (function) and
2742 // v1 (receiver). Touch up the stack with the right values. 2735 // v1 (receiver). Touch up the stack with the right values.
2743 __ sw(v0, MemOperand(sp, (arg_count + 1) * kPointerSize)); 2736 __ sd(v0, MemOperand(sp, (arg_count + 1) * kPointerSize));
2744 __ sw(v1, MemOperand(sp, arg_count * kPointerSize)); 2737 __ sd(v1, MemOperand(sp, arg_count * kPointerSize));
2745 } 2738 }
2746 // Record source position for debugger. 2739 // Record source position for debugger.
2747 SetSourcePosition(expr->position()); 2740 SetSourcePosition(expr->position());
2748 CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS); 2741 CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
2749 __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize)); 2742 __ ld(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
2750 __ CallStub(&stub); 2743 __ CallStub(&stub);
2751 RecordJSReturnSite(expr); 2744 RecordJSReturnSite(expr);
2752 // Restore context register. 2745 // Restore context register.
2753 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2746 __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2754 context()->DropAndPlug(1, v0); 2747 context()->DropAndPlug(1, v0);
2755 } else if (call_type == Call::GLOBAL_CALL) { 2748 } else if (call_type == Call::GLOBAL_CALL) {
2756 EmitCallWithLoadIC(expr); 2749 EmitCallWithLoadIC(expr);
2757 } else if (call_type == Call::LOOKUP_SLOT_CALL) { 2750 } else if (call_type == Call::LOOKUP_SLOT_CALL) {
2758 // Call to a lookup slot (dynamically introduced variable). 2751 // Call to a lookup slot (dynamically introduced variable).
2759 VariableProxy* proxy = callee->AsVariableProxy(); 2752 VariableProxy* proxy = callee->AsVariableProxy();
2760 Label slow, done; 2753 Label slow, done;
2761 2754
2762 { PreservePositionScope scope(masm()->positions_recorder()); 2755 { PreservePositionScope scope(masm()->positions_recorder());
2763 // Generate code for loading from variables potentially shadowed 2756 // Generate code for loading from variables potentially shadowed
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
2832 // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is 2825 // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is
2833 // ignored. 2826 // ignored.
2834 VisitForStackValue(expr->expression()); 2827 VisitForStackValue(expr->expression());
2835 2828
2836 // Push the arguments ("left-to-right") on the stack. 2829 // Push the arguments ("left-to-right") on the stack.
2837 ZoneList<Expression*>* args = expr->arguments(); 2830 ZoneList<Expression*>* args = expr->arguments();
2838 int arg_count = args->length(); 2831 int arg_count = args->length();
2839 for (int i = 0; i < arg_count; i++) { 2832 for (int i = 0; i < arg_count; i++) {
2840 VisitForStackValue(args->at(i)); 2833 VisitForStackValue(args->at(i));
2841 } 2834 }
2842
2843 // Call the construct call builtin that handles allocation and 2835 // Call the construct call builtin that handles allocation and
2844 // constructor invocation. 2836 // constructor invocation.
2845 SetSourcePosition(expr->position()); 2837 SetSourcePosition(expr->position());
2846 2838
2847 // Load function and argument count into a1 and a0. 2839 // Load function and argument count into a1 and a0.
2848 __ li(a0, Operand(arg_count)); 2840 __ li(a0, Operand(arg_count));
2849 __ lw(a1, MemOperand(sp, arg_count * kPointerSize)); 2841 __ ld(a1, MemOperand(sp, arg_count * kPointerSize));
2850 2842
2851 // Record call targets in unoptimized code. 2843 // Record call targets in unoptimized code.
2852 if (FLAG_pretenuring_call_new) { 2844 if (FLAG_pretenuring_call_new) {
2853 EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot()); 2845 EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot());
2854 ASSERT(expr->AllocationSiteFeedbackSlot() == 2846 ASSERT(expr->AllocationSiteFeedbackSlot() ==
2855 expr->CallNewFeedbackSlot() + 1); 2847 expr->CallNewFeedbackSlot() + 1);
2856 } 2848 }
2857 2849
2858 __ li(a2, FeedbackVector()); 2850 __ li(a2, FeedbackVector());
2859 __ li(a3, Operand(Smi::FromInt(expr->CallNewFeedbackSlot()))); 2851 __ li(a3, Operand(Smi::FromInt(expr->CallNewFeedbackSlot())));
(...skipping 12 matching lines...) Expand all
2872 VisitForAccumulatorValue(args->at(0)); 2864 VisitForAccumulatorValue(args->at(0));
2873 2865
2874 Label materialize_true, materialize_false; 2866 Label materialize_true, materialize_false;
2875 Label* if_true = NULL; 2867 Label* if_true = NULL;
2876 Label* if_false = NULL; 2868 Label* if_false = NULL;
2877 Label* fall_through = NULL; 2869 Label* fall_through = NULL;
2878 context()->PrepareTest(&materialize_true, &materialize_false, 2870 context()->PrepareTest(&materialize_true, &materialize_false,
2879 &if_true, &if_false, &fall_through); 2871 &if_true, &if_false, &fall_through);
2880 2872
2881 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2873 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2882 __ SmiTst(v0, t0); 2874 __ SmiTst(v0, a4);
2883 Split(eq, t0, Operand(zero_reg), if_true, if_false, fall_through); 2875 Split(eq, a4, Operand(zero_reg), if_true, if_false, fall_through);
2884 2876
2885 context()->Plug(if_true, if_false); 2877 context()->Plug(if_true, if_false);
2886 } 2878 }
2887 2879
2888 2880
2889 void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) { 2881 void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) {
2890 ZoneList<Expression*>* args = expr->arguments(); 2882 ZoneList<Expression*>* args = expr->arguments();
2891 ASSERT(args->length() == 1); 2883 ASSERT(args->length() == 1);
2892 2884
2893 VisitForAccumulatorValue(args->at(0)); 2885 VisitForAccumulatorValue(args->at(0));
(...skipping 22 matching lines...) Expand all
2916 Label materialize_true, materialize_false; 2908 Label materialize_true, materialize_false;
2917 Label* if_true = NULL; 2909 Label* if_true = NULL;
2918 Label* if_false = NULL; 2910 Label* if_false = NULL;
2919 Label* fall_through = NULL; 2911 Label* fall_through = NULL;
2920 context()->PrepareTest(&materialize_true, &materialize_false, 2912 context()->PrepareTest(&materialize_true, &materialize_false,
2921 &if_true, &if_false, &fall_through); 2913 &if_true, &if_false, &fall_through);
2922 2914
2923 __ JumpIfSmi(v0, if_false); 2915 __ JumpIfSmi(v0, if_false);
2924 __ LoadRoot(at, Heap::kNullValueRootIndex); 2916 __ LoadRoot(at, Heap::kNullValueRootIndex);
2925 __ Branch(if_true, eq, v0, Operand(at)); 2917 __ Branch(if_true, eq, v0, Operand(at));
2926 __ lw(a2, FieldMemOperand(v0, HeapObject::kMapOffset)); 2918 __ ld(a2, FieldMemOperand(v0, HeapObject::kMapOffset));
2927 // Undetectable objects behave like undefined when tested with typeof. 2919 // Undetectable objects behave like undefined when tested with typeof.
2928 __ lbu(a1, FieldMemOperand(a2, Map::kBitFieldOffset)); 2920 __ lbu(a1, FieldMemOperand(a2, Map::kBitFieldOffset));
2929 __ And(at, a1, Operand(1 << Map::kIsUndetectable)); 2921 __ And(at, a1, Operand(1 << Map::kIsUndetectable));
2930 __ Branch(if_false, ne, at, Operand(zero_reg)); 2922 __ Branch(if_false, ne, at, Operand(zero_reg));
2931 __ lbu(a1, FieldMemOperand(a2, Map::kInstanceTypeOffset)); 2923 __ lbu(a1, FieldMemOperand(a2, Map::kInstanceTypeOffset));
2932 __ Branch(if_false, lt, a1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); 2924 __ Branch(if_false, lt, a1, Operand(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2933 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2925 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2934 Split(le, a1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE), 2926 Split(le, a1, Operand(LAST_NONCALLABLE_SPEC_OBJECT_TYPE),
2935 if_true, if_false, fall_through); 2927 if_true, if_false, fall_through);
2936 2928
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2968 VisitForAccumulatorValue(args->at(0)); 2960 VisitForAccumulatorValue(args->at(0));
2969 2961
2970 Label materialize_true, materialize_false; 2962 Label materialize_true, materialize_false;
2971 Label* if_true = NULL; 2963 Label* if_true = NULL;
2972 Label* if_false = NULL; 2964 Label* if_false = NULL;
2973 Label* fall_through = NULL; 2965 Label* fall_through = NULL;
2974 context()->PrepareTest(&materialize_true, &materialize_false, 2966 context()->PrepareTest(&materialize_true, &materialize_false,
2975 &if_true, &if_false, &fall_through); 2967 &if_true, &if_false, &fall_through);
2976 2968
2977 __ JumpIfSmi(v0, if_false); 2969 __ JumpIfSmi(v0, if_false);
2978 __ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); 2970 __ ld(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
2979 __ lbu(a1, FieldMemOperand(a1, Map::kBitFieldOffset)); 2971 __ lbu(a1, FieldMemOperand(a1, Map::kBitFieldOffset));
2980 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2972 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
2981 __ And(at, a1, Operand(1 << Map::kIsUndetectable)); 2973 __ And(at, a1, Operand(1 << Map::kIsUndetectable));
2982 Split(ne, at, Operand(zero_reg), if_true, if_false, fall_through); 2974 Split(ne, at, Operand(zero_reg), if_true, if_false, fall_through);
2983 2975
2984 context()->Plug(if_true, if_false); 2976 context()->Plug(if_true, if_false);
2985 } 2977 }
2986 2978
2987 2979
2988 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( 2980 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
2989 CallRuntime* expr) { 2981 CallRuntime* expr) {
2990 ZoneList<Expression*>* args = expr->arguments(); 2982 ZoneList<Expression*>* args = expr->arguments();
2991 ASSERT(args->length() == 1); 2983 ASSERT(args->length() == 1);
2992 2984
2993 VisitForAccumulatorValue(args->at(0)); 2985 VisitForAccumulatorValue(args->at(0));
2994 2986
2995 Label materialize_true, materialize_false, skip_lookup; 2987 Label materialize_true, materialize_false, skip_lookup;
2996 Label* if_true = NULL; 2988 Label* if_true = NULL;
2997 Label* if_false = NULL; 2989 Label* if_false = NULL;
2998 Label* fall_through = NULL; 2990 Label* fall_through = NULL;
2999 context()->PrepareTest(&materialize_true, &materialize_false, 2991 context()->PrepareTest(&materialize_true, &materialize_false,
3000 &if_true, &if_false, &fall_through); 2992 &if_true, &if_false, &fall_through);
3001 2993
3002 __ AssertNotSmi(v0); 2994 __ AssertNotSmi(v0);
3003 2995
3004 __ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); 2996 __ ld(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
3005 __ lbu(t0, FieldMemOperand(a1, Map::kBitField2Offset)); 2997 __ lbu(a4, FieldMemOperand(a1, Map::kBitField2Offset));
3006 __ And(t0, t0, 1 << Map::kStringWrapperSafeForDefaultValueOf); 2998 __ And(a4, a4, 1 << Map::kStringWrapperSafeForDefaultValueOf);
3007 __ Branch(&skip_lookup, ne, t0, Operand(zero_reg)); 2999 __ Branch(&skip_lookup, ne, a4, Operand(zero_reg));
3008 3000
3009 // Check for fast case object. Generate false result for slow case object. 3001 // Check for fast case object. Generate false result for slow case object.
3010 __ lw(a2, FieldMemOperand(v0, JSObject::kPropertiesOffset)); 3002 __ ld(a2, FieldMemOperand(v0, JSObject::kPropertiesOffset));
3011 __ lw(a2, FieldMemOperand(a2, HeapObject::kMapOffset)); 3003 __ ld(a2, FieldMemOperand(a2, HeapObject::kMapOffset));
3012 __ LoadRoot(t0, Heap::kHashTableMapRootIndex); 3004 __ LoadRoot(a4, Heap::kHashTableMapRootIndex);
3013 __ Branch(if_false, eq, a2, Operand(t0)); 3005 __ Branch(if_false, eq, a2, Operand(a4));
3014 3006
3015 // Look for valueOf name in the descriptor array, and indicate false if 3007 // Look for valueOf name in the descriptor array, and indicate false if
3016 // found. Since we omit an enumeration index check, if it is added via a 3008 // found. Since we omit an enumeration index check, if it is added via a
3017 // transition that shares its descriptor array, this is a false positive. 3009 // transition that shares its descriptor array, this is a false positive.
3018 Label entry, loop, done; 3010 Label entry, loop, done;
3019 3011
3020 // Skip loop if no descriptors are valid. 3012 // Skip loop if no descriptors are valid.
3021 __ NumberOfOwnDescriptors(a3, a1); 3013 __ NumberOfOwnDescriptors(a3, a1);
3022 __ Branch(&done, eq, a3, Operand(zero_reg)); 3014 __ Branch(&done, eq, a3, Operand(zero_reg));
3023 3015
3024 __ LoadInstanceDescriptors(a1, t0); 3016 __ LoadInstanceDescriptors(a1, a4);
3025 // t0: descriptor array. 3017 // a4: descriptor array.
3026 // a3: valid entries in the descriptor array. 3018 // a3: valid entries in the descriptor array.
3027 STATIC_ASSERT(kSmiTag == 0); 3019 STATIC_ASSERT(kSmiTag == 0);
3028 STATIC_ASSERT(kSmiTagSize == 1); 3020 STATIC_ASSERT(kSmiTagSize == 1);
3029 STATIC_ASSERT(kPointerSize == 4); 3021 // Does not need?
3022 // STATIC_ASSERT(kPointerSize == 4);
3030 __ li(at, Operand(DescriptorArray::kDescriptorSize)); 3023 __ li(at, Operand(DescriptorArray::kDescriptorSize));
3031 __ Mul(a3, a3, at); 3024 __ Dmul(a3, a3, at);
3032 // Calculate location of the first key name. 3025 // Calculate location of the first key name.
3033 __ Addu(t0, t0, Operand(DescriptorArray::kFirstOffset - kHeapObjectTag)); 3026 __ Daddu(a4, a4, Operand(DescriptorArray::kFirstOffset - kHeapObjectTag));
3034 // Calculate the end of the descriptor array. 3027 // Calculate the end of the descriptor array.
3035 __ mov(a2, t0); 3028 __ mov(a2, a4);
3036 __ sll(t1, a3, kPointerSizeLog2); 3029 __ dsll(a5, a3, kPointerSizeLog2);
3037 __ Addu(a2, a2, t1); 3030 __ Daddu(a2, a2, a5);
3038 3031
3039 // Loop through all the keys in the descriptor array. If one of these is the 3032 // Loop through all the keys in the descriptor array. If one of these is the
3040 // string "valueOf" the result is false. 3033 // string "valueOf" the result is false.
3041 // The use of t2 to store the valueOf string assumes that it is not otherwise 3034 // The use of a6 to store the valueOf string assumes that it is not otherwise
3042 // used in the loop below. 3035 // used in the loop below.
3043 __ li(t2, Operand(isolate()->factory()->value_of_string())); 3036 __ li(a6, Operand(isolate()->factory()->value_of_string()));
3044 __ jmp(&entry); 3037 __ jmp(&entry);
3045 __ bind(&loop); 3038 __ bind(&loop);
3046 __ lw(a3, MemOperand(t0, 0)); 3039 __ ld(a3, MemOperand(a4, 0));
3047 __ Branch(if_false, eq, a3, Operand(t2)); 3040 __ Branch(if_false, eq, a3, Operand(a6));
3048 __ Addu(t0, t0, Operand(DescriptorArray::kDescriptorSize * kPointerSize)); 3041 __ Daddu(a4, a4, Operand(DescriptorArray::kDescriptorSize * kPointerSize));
3049 __ bind(&entry); 3042 __ bind(&entry);
3050 __ Branch(&loop, ne, t0, Operand(a2)); 3043 __ Branch(&loop, ne, a4, Operand(a2));
3051 3044
3052 __ bind(&done); 3045 __ bind(&done);
3053 3046
3054 // Set the bit in the map to indicate that there is no local valueOf field. 3047 // Set the bit in the map to indicate that there is no local valueOf field.
3055 __ lbu(a2, FieldMemOperand(a1, Map::kBitField2Offset)); 3048 __ lbu(a2, FieldMemOperand(a1, Map::kBitField2Offset));
3056 __ Or(a2, a2, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf)); 3049 __ Or(a2, a2, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
3057 __ sb(a2, FieldMemOperand(a1, Map::kBitField2Offset)); 3050 __ sb(a2, FieldMemOperand(a1, Map::kBitField2Offset));
3058 3051
3059 __ bind(&skip_lookup); 3052 __ bind(&skip_lookup);
3060 3053
3061 // If a valueOf property is not found on the object check that its 3054 // If a valueOf property is not found on the object check that its
3062 // prototype is the un-modified String prototype. If not result is false. 3055 // prototype is the un-modified String prototype. If not result is false.
3063 __ lw(a2, FieldMemOperand(a1, Map::kPrototypeOffset)); 3056 __ ld(a2, FieldMemOperand(a1, Map::kPrototypeOffset));
3064 __ JumpIfSmi(a2, if_false); 3057 __ JumpIfSmi(a2, if_false);
3065 __ lw(a2, FieldMemOperand(a2, HeapObject::kMapOffset)); 3058 __ ld(a2, FieldMemOperand(a2, HeapObject::kMapOffset));
3066 __ lw(a3, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); 3059 __ ld(a3, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
3067 __ lw(a3, FieldMemOperand(a3, GlobalObject::kNativeContextOffset)); 3060 __ ld(a3, FieldMemOperand(a3, GlobalObject::kNativeContextOffset));
3068 __ lw(a3, ContextOperand(a3, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); 3061 __ ld(a3, ContextOperand(a3, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
3069 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 3062 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3070 Split(eq, a2, Operand(a3), if_true, if_false, fall_through); 3063 Split(eq, a2, Operand(a3), if_true, if_false, fall_through);
3071 3064
3072 context()->Plug(if_true, if_false); 3065 context()->Plug(if_true, if_false);
3073 } 3066 }
3074 3067
3075 3068
3076 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) { 3069 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
3077 ZoneList<Expression*>* args = expr->arguments(); 3070 ZoneList<Expression*>* args = expr->arguments();
3078 ASSERT(args->length() == 1); 3071 ASSERT(args->length() == 1);
(...skipping 24 matching lines...) Expand all
3103 VisitForAccumulatorValue(args->at(0)); 3096 VisitForAccumulatorValue(args->at(0));
3104 3097
3105 Label materialize_true, materialize_false; 3098 Label materialize_true, materialize_false;
3106 Label* if_true = NULL; 3099 Label* if_true = NULL;
3107 Label* if_false = NULL; 3100 Label* if_false = NULL;
3108 Label* fall_through = NULL; 3101 Label* fall_through = NULL;
3109 context()->PrepareTest(&materialize_true, &materialize_false, 3102 context()->PrepareTest(&materialize_true, &materialize_false,
3110 &if_true, &if_false, &fall_through); 3103 &if_true, &if_false, &fall_through);
3111 3104
3112 __ CheckMap(v0, a1, Heap::kHeapNumberMapRootIndex, if_false, DO_SMI_CHECK); 3105 __ CheckMap(v0, a1, Heap::kHeapNumberMapRootIndex, if_false, DO_SMI_CHECK);
3113 __ lw(a2, FieldMemOperand(v0, HeapNumber::kExponentOffset)); 3106 __ lwu(a2, FieldMemOperand(v0, HeapNumber::kExponentOffset));
3114 __ lw(a1, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); 3107 __ lwu(a1, FieldMemOperand(v0, HeapNumber::kMantissaOffset));
3115 __ li(t0, 0x80000000); 3108 __ li(a4, 0x80000000);
3116 Label not_nan; 3109 Label not_nan;
3117 __ Branch(&not_nan, ne, a2, Operand(t0)); 3110 __ Branch(&not_nan, ne, a2, Operand(a4));
3118 __ mov(t0, zero_reg); 3111 __ mov(a4, zero_reg);
3119 __ mov(a2, a1); 3112 __ mov(a2, a1);
3120 __ bind(&not_nan); 3113 __ bind(&not_nan);
3121 3114
3122 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 3115 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3123 Split(eq, a2, Operand(t0), if_true, if_false, fall_through); 3116 Split(eq, a2, Operand(a4), if_true, if_false, fall_through);
3124 3117
3125 context()->Plug(if_true, if_false); 3118 context()->Plug(if_true, if_false);
3126 } 3119 }
3127 3120
3128 3121
3129 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) { 3122 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
3130 ZoneList<Expression*>* args = expr->arguments(); 3123 ZoneList<Expression*>* args = expr->arguments();
3131 ASSERT(args->length() == 1); 3124 ASSERT(args->length() == 1);
3132 3125
3133 VisitForAccumulatorValue(args->at(0)); 3126 VisitForAccumulatorValue(args->at(0));
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
3175 ASSERT(expr->arguments()->length() == 0); 3168 ASSERT(expr->arguments()->length() == 0);
3176 3169
3177 Label materialize_true, materialize_false; 3170 Label materialize_true, materialize_false;
3178 Label* if_true = NULL; 3171 Label* if_true = NULL;
3179 Label* if_false = NULL; 3172 Label* if_false = NULL;
3180 Label* fall_through = NULL; 3173 Label* fall_through = NULL;
3181 context()->PrepareTest(&materialize_true, &materialize_false, 3174 context()->PrepareTest(&materialize_true, &materialize_false,
3182 &if_true, &if_false, &fall_through); 3175 &if_true, &if_false, &fall_through);
3183 3176
3184 // Get the frame pointer for the calling frame. 3177 // Get the frame pointer for the calling frame.
3185 __ lw(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 3178 __ ld(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
3186 3179
3187 // Skip the arguments adaptor frame if it exists. 3180 // Skip the arguments adaptor frame if it exists.
3188 Label check_frame_marker; 3181 Label check_frame_marker;
3189 __ lw(a1, MemOperand(a2, StandardFrameConstants::kContextOffset)); 3182 __ ld(a1, MemOperand(a2, StandardFrameConstants::kContextOffset));
3190 __ Branch(&check_frame_marker, ne, 3183 __ Branch(&check_frame_marker, ne,
3191 a1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 3184 a1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
3192 __ lw(a2, MemOperand(a2, StandardFrameConstants::kCallerFPOffset)); 3185 __ ld(a2, MemOperand(a2, StandardFrameConstants::kCallerFPOffset));
3193 3186
3194 // Check the marker in the calling frame. 3187 // Check the marker in the calling frame.
3195 __ bind(&check_frame_marker); 3188 __ bind(&check_frame_marker);
3196 __ lw(a1, MemOperand(a2, StandardFrameConstants::kMarkerOffset)); 3189 __ ld(a1, MemOperand(a2, StandardFrameConstants::kMarkerOffset));
3197 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 3190 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3198 Split(eq, a1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)), 3191 Split(eq, a1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)),
3199 if_true, if_false, fall_through); 3192 if_true, if_false, fall_through);
3200 3193
3201 context()->Plug(if_true, if_false); 3194 context()->Plug(if_true, if_false);
3202 } 3195 }
3203 3196
3204 3197
3205 void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) { 3198 void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
3206 ZoneList<Expression*>* args = expr->arguments(); 3199 ZoneList<Expression*>* args = expr->arguments();
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
3240 } 3233 }
3241 3234
3242 3235
3243 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { 3236 void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
3244 ASSERT(expr->arguments()->length() == 0); 3237 ASSERT(expr->arguments()->length() == 0);
3245 Label exit; 3238 Label exit;
3246 // Get the number of formal parameters. 3239 // Get the number of formal parameters.
3247 __ li(v0, Operand(Smi::FromInt(info_->scope()->num_parameters()))); 3240 __ li(v0, Operand(Smi::FromInt(info_->scope()->num_parameters())));
3248 3241
3249 // Check if the calling frame is an arguments adaptor frame. 3242 // Check if the calling frame is an arguments adaptor frame.
3250 __ lw(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 3243 __ ld(a2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
3251 __ lw(a3, MemOperand(a2, StandardFrameConstants::kContextOffset)); 3244 __ ld(a3, MemOperand(a2, StandardFrameConstants::kContextOffset));
3252 __ Branch(&exit, ne, a3, 3245 __ Branch(&exit, ne, a3,
3253 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 3246 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
3254 3247
3255 // Arguments adaptor case: Read the arguments length from the 3248 // Arguments adaptor case: Read the arguments length from the
3256 // adaptor frame. 3249 // adaptor frame.
3257 __ lw(v0, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset)); 3250 __ ld(v0, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset));
3258 3251
3259 __ bind(&exit); 3252 __ bind(&exit);
3260 context()->Plug(v0); 3253 context()->Plug(v0);
3261 } 3254 }
3262 3255
3263 3256
3264 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { 3257 void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
3265 ZoneList<Expression*>* args = expr->arguments(); 3258 ZoneList<Expression*>* args = expr->arguments();
3266 ASSERT(args->length() == 1); 3259 ASSERT(args->length() == 1);
3267 Label done, null, function, non_function_constructor; 3260 Label done, null, function, non_function_constructor;
(...skipping 15 matching lines...) Expand all
3283 FIRST_SPEC_OBJECT_TYPE + 1); 3276 FIRST_SPEC_OBJECT_TYPE + 1);
3284 __ Branch(&function, eq, a1, Operand(FIRST_SPEC_OBJECT_TYPE)); 3277 __ Branch(&function, eq, a1, Operand(FIRST_SPEC_OBJECT_TYPE));
3285 3278
3286 STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == 3279 STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
3287 LAST_SPEC_OBJECT_TYPE - 1); 3280 LAST_SPEC_OBJECT_TYPE - 1);
3288 __ Branch(&function, eq, a1, Operand(LAST_SPEC_OBJECT_TYPE)); 3281 __ Branch(&function, eq, a1, Operand(LAST_SPEC_OBJECT_TYPE));
3289 // Assume that there is no larger type. 3282 // Assume that there is no larger type.
3290 STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1); 3283 STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1);
3291 3284
3292 // Check if the constructor in the map is a JS function. 3285 // Check if the constructor in the map is a JS function.
3293 __ lw(v0, FieldMemOperand(v0, Map::kConstructorOffset)); 3286 __ ld(v0, FieldMemOperand(v0, Map::kConstructorOffset));
3294 __ GetObjectType(v0, a1, a1); 3287 __ GetObjectType(v0, a1, a1);
3295 __ Branch(&non_function_constructor, ne, a1, Operand(JS_FUNCTION_TYPE)); 3288 __ Branch(&non_function_constructor, ne, a1, Operand(JS_FUNCTION_TYPE));
3296 3289
3297 // v0 now contains the constructor function. Grab the 3290 // v0 now contains the constructor function. Grab the
3298 // instance class name from there. 3291 // instance class name from there.
3299 __ lw(v0, FieldMemOperand(v0, JSFunction::kSharedFunctionInfoOffset)); 3292 __ ld(v0, FieldMemOperand(v0, JSFunction::kSharedFunctionInfoOffset));
3300 __ lw(v0, FieldMemOperand(v0, SharedFunctionInfo::kInstanceClassNameOffset)); 3293 __ ld(v0, FieldMemOperand(v0, SharedFunctionInfo::kInstanceClassNameOffset));
3301 __ Branch(&done); 3294 __ Branch(&done);
3302 3295
3303 // Functions have class 'Function'. 3296 // Functions have class 'Function'.
3304 __ bind(&function); 3297 __ bind(&function);
3305 __ LoadRoot(v0, Heap::kfunction_class_stringRootIndex); 3298 __ LoadRoot(v0, Heap::kfunction_class_stringRootIndex);
3306 __ jmp(&done); 3299 __ jmp(&done);
3307 3300
3308 // Objects with a non-function constructor have class 'Object'. 3301 // Objects with a non-function constructor have class 'Object'.
3309 __ bind(&non_function_constructor); 3302 __ bind(&non_function_constructor);
3310 __ LoadRoot(v0, Heap::kObject_stringRootIndex); 3303 __ LoadRoot(v0, Heap::kObject_stringRootIndex);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
3354 3347
3355 VisitForAccumulatorValue(args->at(0)); // Load the object. 3348 VisitForAccumulatorValue(args->at(0)); // Load the object.
3356 3349
3357 Label done; 3350 Label done;
3358 // If the object is a smi return the object. 3351 // If the object is a smi return the object.
3359 __ JumpIfSmi(v0, &done); 3352 __ JumpIfSmi(v0, &done);
3360 // If the object is not a value type, return the object. 3353 // If the object is not a value type, return the object.
3361 __ GetObjectType(v0, a1, a1); 3354 __ GetObjectType(v0, a1, a1);
3362 __ Branch(&done, ne, a1, Operand(JS_VALUE_TYPE)); 3355 __ Branch(&done, ne, a1, Operand(JS_VALUE_TYPE));
3363 3356
3364 __ lw(v0, FieldMemOperand(v0, JSValue::kValueOffset)); 3357 __ ld(v0, FieldMemOperand(v0, JSValue::kValueOffset));
3365 3358
3366 __ bind(&done); 3359 __ bind(&done);
3367 context()->Plug(v0); 3360 context()->Plug(v0);
3368 } 3361 }
3369 3362
3370 3363
3371 void FullCodeGenerator::EmitDateField(CallRuntime* expr) { 3364 void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
3372 ZoneList<Expression*>* args = expr->arguments(); 3365 ZoneList<Expression*>* args = expr->arguments();
3373 ASSERT(args->length() == 2); 3366 ASSERT(args->length() == 2);
3374 ASSERT_NE(NULL, args->at(1)->AsLiteral()); 3367 ASSERT_NE(NULL, args->at(1)->AsLiteral());
3375 Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value())); 3368 Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value()));
3376 3369
3377 VisitForAccumulatorValue(args->at(0)); // Load the object. 3370 VisitForAccumulatorValue(args->at(0)); // Load the object.
3378 3371
3379 Label runtime, done, not_date_object; 3372 Label runtime, done, not_date_object;
3380 Register object = v0; 3373 Register object = v0;
3381 Register result = v0; 3374 Register result = v0;
3382 Register scratch0 = t5; 3375 Register scratch0 = t1;
3383 Register scratch1 = a1; 3376 Register scratch1 = a1;
3384 3377
3385 __ JumpIfSmi(object, &not_date_object); 3378 __ JumpIfSmi(object, &not_date_object);
3386 __ GetObjectType(object, scratch1, scratch1); 3379 __ GetObjectType(object, scratch1, scratch1);
3387 __ Branch(&not_date_object, ne, scratch1, Operand(JS_DATE_TYPE)); 3380 __ Branch(&not_date_object, ne, scratch1, Operand(JS_DATE_TYPE));
3388 3381
3389 if (index->value() == 0) { 3382 if (index->value() == 0) {
3390 __ lw(result, FieldMemOperand(object, JSDate::kValueOffset)); 3383 __ ld(result, FieldMemOperand(object, JSDate::kValueOffset));
3391 __ jmp(&done); 3384 __ jmp(&done);
3392 } else { 3385 } else {
3393 if (index->value() < JSDate::kFirstUncachedField) { 3386 if (index->value() < JSDate::kFirstUncachedField) {
3394 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); 3387 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
3395 __ li(scratch1, Operand(stamp)); 3388 __ li(scratch1, Operand(stamp));
3396 __ lw(scratch1, MemOperand(scratch1)); 3389 __ ld(scratch1, MemOperand(scratch1));
3397 __ lw(scratch0, FieldMemOperand(object, JSDate::kCacheStampOffset)); 3390 __ ld(scratch0, FieldMemOperand(object, JSDate::kCacheStampOffset));
3398 __ Branch(&runtime, ne, scratch1, Operand(scratch0)); 3391 __ Branch(&runtime, ne, scratch1, Operand(scratch0));
3399 __ lw(result, FieldMemOperand(object, JSDate::kValueOffset + 3392 __ ld(result, FieldMemOperand(object, JSDate::kValueOffset +
3400 kPointerSize * index->value())); 3393 kPointerSize * index->value()));
3401 __ jmp(&done); 3394 __ jmp(&done);
3402 } 3395 }
3403 __ bind(&runtime); 3396 __ bind(&runtime);
3404 __ PrepareCallCFunction(2, scratch1); 3397 __ PrepareCallCFunction(2, scratch1);
3405 __ li(a1, Operand(index)); 3398 __ li(a1, Operand(index));
3406 __ Move(a0, object); 3399 __ Move(a0, object);
3407 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); 3400 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
3408 __ jmp(&done); 3401 __ jmp(&done);
3409 } 3402 }
(...skipping 18 matching lines...) Expand all
3428 VisitForAccumulatorValue(args->at(0)); // string 3421 VisitForAccumulatorValue(args->at(0)); // string
3429 __ Pop(index, value); 3422 __ Pop(index, value);
3430 3423
3431 if (FLAG_debug_code) { 3424 if (FLAG_debug_code) {
3432 __ SmiTst(value, at); 3425 __ SmiTst(value, at);
3433 __ Check(eq, kNonSmiValue, at, Operand(zero_reg)); 3426 __ Check(eq, kNonSmiValue, at, Operand(zero_reg));
3434 __ SmiTst(index, at); 3427 __ SmiTst(index, at);
3435 __ Check(eq, kNonSmiIndex, at, Operand(zero_reg)); 3428 __ Check(eq, kNonSmiIndex, at, Operand(zero_reg));
3436 __ SmiUntag(index, index); 3429 __ SmiUntag(index, index);
3437 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; 3430 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
3438 Register scratch = t5; 3431 Register scratch = t1;
3439 __ EmitSeqStringSetCharCheck( 3432 __ EmitSeqStringSetCharCheck(
3440 string, index, value, scratch, one_byte_seq_type); 3433 string, index, value, scratch, one_byte_seq_type);
3441 __ SmiTag(index, index); 3434 __ SmiTag(index, index);
3442 } 3435 }
3443 3436
3444 __ SmiUntag(value, value); 3437 __ SmiUntag(value, value);
3445 __ Addu(at, 3438 __ Daddu(at,
3446 string, 3439 string,
3447 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 3440 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
3448 __ SmiUntag(index); 3441 __ SmiUntag(index);
3449 __ Addu(at, at, index); 3442 __ Daddu(at, at, index);
3450 __ sb(value, MemOperand(at)); 3443 __ sb(value, MemOperand(at));
3451 context()->Plug(string); 3444 context()->Plug(string);
3452 } 3445 }
3453 3446
3454 3447
3455 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { 3448 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
3456 ZoneList<Expression*>* args = expr->arguments(); 3449 ZoneList<Expression*>* args = expr->arguments();
3457 ASSERT_EQ(3, args->length()); 3450 ASSERT_EQ(3, args->length());
3458 3451
3459 Register string = v0; 3452 Register string = v0;
3460 Register index = a1; 3453 Register index = a1;
3461 Register value = a2; 3454 Register value = a2;
3462 3455
3463 VisitForStackValue(args->at(1)); // index 3456 VisitForStackValue(args->at(1)); // index
3464 VisitForStackValue(args->at(2)); // value 3457 VisitForStackValue(args->at(2)); // value
3465 VisitForAccumulatorValue(args->at(0)); // string 3458 VisitForAccumulatorValue(args->at(0)); // string
3466 __ Pop(index, value); 3459 __ Pop(index, value);
3467 3460
3468 if (FLAG_debug_code) { 3461 if (FLAG_debug_code) {
3469 __ SmiTst(value, at); 3462 __ SmiTst(value, at);
3470 __ Check(eq, kNonSmiValue, at, Operand(zero_reg)); 3463 __ Check(eq, kNonSmiValue, at, Operand(zero_reg));
3471 __ SmiTst(index, at); 3464 __ SmiTst(index, at);
3472 __ Check(eq, kNonSmiIndex, at, Operand(zero_reg)); 3465 __ Check(eq, kNonSmiIndex, at, Operand(zero_reg));
3473 __ SmiUntag(index, index); 3466 __ SmiUntag(index, index);
3474 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; 3467 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
3475 Register scratch = t5; 3468 Register scratch = t1;
3476 __ EmitSeqStringSetCharCheck( 3469 __ EmitSeqStringSetCharCheck(
3477 string, index, value, scratch, two_byte_seq_type); 3470 string, index, value, scratch, two_byte_seq_type);
3478 __ SmiTag(index, index); 3471 __ SmiTag(index, index);
3479 } 3472 }
3480 3473
3481 __ SmiUntag(value, value); 3474 __ SmiUntag(value, value);
3482 __ Addu(at, 3475 __ Daddu(at,
3483 string, 3476 string,
3484 Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag)); 3477 Operand(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
3485 __ Addu(at, at, index); 3478 __ dsra(index, index, 32 - 1);
3479 __ Daddu(at, at, index);
3486 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 3480 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
3487 __ sh(value, MemOperand(at)); 3481 __ sh(value, MemOperand(at));
3488 context()->Plug(string); 3482 context()->Plug(string);
3489 } 3483 }
3490 3484
3491 3485
3492 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) { 3486 void FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
3493 // Load the arguments on the stack and call the runtime function. 3487 // Load the arguments on the stack and call the runtime function.
3494 ZoneList<Expression*>* args = expr->arguments(); 3488 ZoneList<Expression*>* args = expr->arguments();
3495 ASSERT(args->length() == 2); 3489 ASSERT(args->length() == 2);
(...skipping 15 matching lines...) Expand all
3511 3505
3512 Label done; 3506 Label done;
3513 // If the object is a smi, return the value. 3507 // If the object is a smi, return the value.
3514 __ JumpIfSmi(a1, &done); 3508 __ JumpIfSmi(a1, &done);
3515 3509
3516 // If the object is not a value type, return the value. 3510 // If the object is not a value type, return the value.
3517 __ GetObjectType(a1, a2, a2); 3511 __ GetObjectType(a1, a2, a2);
3518 __ Branch(&done, ne, a2, Operand(JS_VALUE_TYPE)); 3512 __ Branch(&done, ne, a2, Operand(JS_VALUE_TYPE));
3519 3513
3520 // Store the value. 3514 // Store the value.
3521 __ sw(v0, FieldMemOperand(a1, JSValue::kValueOffset)); 3515 __ sd(v0, FieldMemOperand(a1, JSValue::kValueOffset));
3522 // Update the write barrier. Save the value as it will be 3516 // Update the write barrier. Save the value as it will be
3523 // overwritten by the write barrier code and is needed afterward. 3517 // overwritten by the write barrier code and is needed afterward.
3524 __ mov(a2, v0); 3518 __ mov(a2, v0);
3525 __ RecordWriteField( 3519 __ RecordWriteField(
3526 a1, JSValue::kValueOffset, a2, a3, kRAHasBeenSaved, kDontSaveFPRegs); 3520 a1, JSValue::kValueOffset, a2, a3, kRAHasBeenSaved, kDontSaveFPRegs);
3527 3521
3528 __ bind(&done); 3522 __ bind(&done);
3529 context()->Plug(v0); 3523 context()->Plug(v0);
3530 } 3524 }
3531 3525
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
3699 Label runtime, done; 3693 Label runtime, done;
3700 // Check for non-function argument (including proxy). 3694 // Check for non-function argument (including proxy).
3701 __ JumpIfSmi(v0, &runtime); 3695 __ JumpIfSmi(v0, &runtime);
3702 __ GetObjectType(v0, a1, a1); 3696 __ GetObjectType(v0, a1, a1);
3703 __ Branch(&runtime, ne, a1, Operand(JS_FUNCTION_TYPE)); 3697 __ Branch(&runtime, ne, a1, Operand(JS_FUNCTION_TYPE));
3704 3698
3705 // InvokeFunction requires the function in a1. Move it in there. 3699 // InvokeFunction requires the function in a1. Move it in there.
3706 __ mov(a1, result_register()); 3700 __ mov(a1, result_register());
3707 ParameterCount count(arg_count); 3701 ParameterCount count(arg_count);
3708 __ InvokeFunction(a1, count, CALL_FUNCTION, NullCallWrapper()); 3702 __ InvokeFunction(a1, count, CALL_FUNCTION, NullCallWrapper());
3709 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 3703 __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
3710 __ jmp(&done); 3704 __ jmp(&done);
3711 3705
3712 __ bind(&runtime); 3706 __ bind(&runtime);
3713 __ push(v0); 3707 __ push(v0);
3714 __ CallRuntime(Runtime::kCall, args->length()); 3708 __ CallRuntime(Runtime::kCall, args->length());
3715 __ bind(&done); 3709 __ bind(&done);
3716 3710
3717 context()->Plug(v0); 3711 context()->Plug(v0);
3718 } 3712 }
3719 3713
(...skipping 26 matching lines...) Expand all
3746 __ Abort(kAttemptToUseUndefinedCache); 3740 __ Abort(kAttemptToUseUndefinedCache);
3747 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); 3741 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
3748 context()->Plug(v0); 3742 context()->Plug(v0);
3749 return; 3743 return;
3750 } 3744 }
3751 3745
3752 VisitForAccumulatorValue(args->at(1)); 3746 VisitForAccumulatorValue(args->at(1));
3753 3747
3754 Register key = v0; 3748 Register key = v0;
3755 Register cache = a1; 3749 Register cache = a1;
3756 __ lw(cache, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); 3750 __ ld(cache, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
3757 __ lw(cache, FieldMemOperand(cache, GlobalObject::kNativeContextOffset)); 3751 __ ld(cache, FieldMemOperand(cache, GlobalObject::kNativeContextOffset));
3758 __ lw(cache, 3752 __ ld(cache,
3759 ContextOperand( 3753 ContextOperand(
3760 cache, Context::JSFUNCTION_RESULT_CACHES_INDEX)); 3754 cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
3761 __ lw(cache, 3755 __ ld(cache,
3762 FieldMemOperand(cache, FixedArray::OffsetOfElementAt(cache_id))); 3756 FieldMemOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
3763 3757
3764 3758
3765 Label done, not_found; 3759 Label done, not_found;
3766 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 3760 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
3767 __ lw(a2, FieldMemOperand(cache, JSFunctionResultCache::kFingerOffset)); 3761 __ ld(a2, FieldMemOperand(cache, JSFunctionResultCache::kFingerOffset));
3768 // a2 now holds finger offset as a smi. 3762 // a2 now holds finger offset as a smi.
3769 __ Addu(a3, cache, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 3763 __ Daddu(a3, cache, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
3770 // a3 now points to the start of fixed array elements. 3764 // a3 now points to the start of fixed array elements.
3771 __ sll(at, a2, kPointerSizeLog2 - kSmiTagSize); 3765 __ SmiScale(at, a2, kPointerSizeLog2);
3772 __ addu(a3, a3, at); 3766 __ daddu(a3, a3, at);
3773 // a3 now points to key of indexed element of cache. 3767 // a3 now points to key of indexed element of cache.
3774 __ lw(a2, MemOperand(a3)); 3768 __ ld(a2, MemOperand(a3));
3775 __ Branch(&not_found, ne, key, Operand(a2)); 3769 __ Branch(&not_found, ne, key, Operand(a2));
3776 3770
3777 __ lw(v0, MemOperand(a3, kPointerSize)); 3771 __ ld(v0, MemOperand(a3, kPointerSize));
3778 __ Branch(&done); 3772 __ Branch(&done);
3779 3773
3780 __ bind(&not_found); 3774 __ bind(&not_found);
3781 // Call runtime to perform the lookup. 3775 // Call runtime to perform the lookup.
3782 __ Push(cache, key); 3776 __ Push(cache, key);
3783 __ CallRuntime(Runtime::kGetFromCache, 2); 3777 __ CallRuntime(Runtime::kGetFromCache, 2);
3784 3778
3785 __ bind(&done); 3779 __ bind(&done);
3786 context()->Plug(v0); 3780 context()->Plug(v0);
3787 } 3781 }
3788 3782
3789 3783
3790 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { 3784 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
3791 ZoneList<Expression*>* args = expr->arguments(); 3785 ZoneList<Expression*>* args = expr->arguments();
3792 VisitForAccumulatorValue(args->at(0)); 3786 VisitForAccumulatorValue(args->at(0));
3793 3787
3794 Label materialize_true, materialize_false; 3788 Label materialize_true, materialize_false;
3795 Label* if_true = NULL; 3789 Label* if_true = NULL;
3796 Label* if_false = NULL; 3790 Label* if_false = NULL;
3797 Label* fall_through = NULL; 3791 Label* fall_through = NULL;
3798 context()->PrepareTest(&materialize_true, &materialize_false, 3792 context()->PrepareTest(&materialize_true, &materialize_false,
3799 &if_true, &if_false, &fall_through); 3793 &if_true, &if_false, &fall_through);
3800 3794
3801 __ lw(a0, FieldMemOperand(v0, String::kHashFieldOffset)); 3795 __ lwu(a0, FieldMemOperand(v0, String::kHashFieldOffset));
3802 __ And(a0, a0, Operand(String::kContainsCachedArrayIndexMask)); 3796 __ And(a0, a0, Operand(String::kContainsCachedArrayIndexMask));
3803 3797
3804 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 3798 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3805 Split(eq, a0, Operand(zero_reg), if_true, if_false, fall_through); 3799 Split(eq, a0, Operand(zero_reg), if_true, if_false, fall_through);
3806 3800
3807 context()->Plug(if_true, if_false); 3801 context()->Plug(if_true, if_false);
3808 } 3802 }
3809 3803
3810 3804
3811 void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) { 3805 void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
3812 ZoneList<Expression*>* args = expr->arguments(); 3806 ZoneList<Expression*>* args = expr->arguments();
3813 ASSERT(args->length() == 1); 3807 ASSERT(args->length() == 1);
3814 VisitForAccumulatorValue(args->at(0)); 3808 VisitForAccumulatorValue(args->at(0));
3815 3809
3816 __ AssertString(v0); 3810 __ AssertString(v0);
3817 3811
3818 __ lw(v0, FieldMemOperand(v0, String::kHashFieldOffset)); 3812 __ lwu(v0, FieldMemOperand(v0, String::kHashFieldOffset));
3819 __ IndexFromHash(v0, v0); 3813 __ IndexFromHash(v0, v0);
3820 3814
3821 context()->Plug(v0); 3815 context()->Plug(v0);
3822 } 3816 }
3823 3817
3824 3818
3825 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { 3819 void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
3826 Label bailout, done, one_char_separator, long_separator, 3820 Label bailout, done, one_char_separator, long_separator,
3827 non_trivial_array, not_size_one_array, loop, 3821 non_trivial_array, not_size_one_array, loop,
3828 empty_separator_loop, one_char_separator_loop, 3822 empty_separator_loop, one_char_separator_loop,
3829 one_char_separator_loop_entry, long_separator_loop; 3823 one_char_separator_loop_entry, long_separator_loop;
3830 ZoneList<Expression*>* args = expr->arguments(); 3824 ZoneList<Expression*>* args = expr->arguments();
3831 ASSERT(args->length() == 2); 3825 ASSERT(args->length() == 2);
3832 VisitForStackValue(args->at(1)); 3826 VisitForStackValue(args->at(1));
3833 VisitForAccumulatorValue(args->at(0)); 3827 VisitForAccumulatorValue(args->at(0));
3834 3828
3835 // All aliases of the same register have disjoint lifetimes. 3829 // All aliases of the same register have disjoint lifetimes.
3836 Register array = v0; 3830 Register array = v0;
3837 Register elements = no_reg; // Will be v0. 3831 Register elements = no_reg; // Will be v0.
3838 Register result = no_reg; // Will be v0. 3832 Register result = no_reg; // Will be v0.
3839 Register separator = a1; 3833 Register separator = a1;
3840 Register array_length = a2; 3834 Register array_length = a2;
3841 Register result_pos = no_reg; // Will be a2. 3835 Register result_pos = no_reg; // Will be a2.
3842 Register string_length = a3; 3836 Register string_length = a3;
3843 Register string = t0; 3837 Register string = a4;
3844 Register element = t1; 3838 Register element = a5;
3845 Register elements_end = t2; 3839 Register elements_end = a6;
3846 Register scratch1 = t3; 3840 Register scratch1 = a7;
3847 Register scratch2 = t5; 3841 Register scratch2 = t1;
3848 Register scratch3 = t4; 3842 Register scratch3 = t0;
3849 3843
3850 // Separator operand is on the stack. 3844 // Separator operand is on the stack.
3851 __ pop(separator); 3845 __ pop(separator);
3852 3846
3853 // Check that the array is a JSArray. 3847 // Check that the array is a JSArray.
3854 __ JumpIfSmi(array, &bailout); 3848 __ JumpIfSmi(array, &bailout);
3855 __ GetObjectType(array, scratch1, scratch2); 3849 __ GetObjectType(array, scratch1, scratch2);
3856 __ Branch(&bailout, ne, scratch2, Operand(JS_ARRAY_TYPE)); 3850 __ Branch(&bailout, ne, scratch2, Operand(JS_ARRAY_TYPE));
3857 3851
3858 // Check that the array has fast elements. 3852 // Check that the array has fast elements.
3859 __ CheckFastElements(scratch1, scratch2, &bailout); 3853 __ CheckFastElements(scratch1, scratch2, &bailout);
3860 3854
3861 // If the array has length zero, return the empty string. 3855 // If the array has length zero, return the empty string.
3862 __ lw(array_length, FieldMemOperand(array, JSArray::kLengthOffset)); 3856 __ ld(array_length, FieldMemOperand(array, JSArray::kLengthOffset));
3863 __ SmiUntag(array_length); 3857 __ SmiUntag(array_length);
3864 __ Branch(&non_trivial_array, ne, array_length, Operand(zero_reg)); 3858 __ Branch(&non_trivial_array, ne, array_length, Operand(zero_reg));
3865 __ LoadRoot(v0, Heap::kempty_stringRootIndex); 3859 __ LoadRoot(v0, Heap::kempty_stringRootIndex);
3866 __ Branch(&done); 3860 __ Branch(&done);
3867 3861
3868 __ bind(&non_trivial_array); 3862 __ bind(&non_trivial_array);
3869 3863
3870 // Get the FixedArray containing array's elements. 3864 // Get the FixedArray containing array's elements.
3871 elements = array; 3865 elements = array;
3872 __ lw(elements, FieldMemOperand(array, JSArray::kElementsOffset)); 3866 __ ld(elements, FieldMemOperand(array, JSArray::kElementsOffset));
3873 array = no_reg; // End of array's live range. 3867 array = no_reg; // End of array's live range.
3874 3868
3875 // Check that all array elements are sequential ASCII strings, and 3869 // Check that all array elements are sequential ASCII strings, and
3876 // accumulate the sum of their lengths, as a smi-encoded value. 3870 // accumulate the sum of their lengths, as a smi-encoded value.
3877 __ mov(string_length, zero_reg); 3871 __ mov(string_length, zero_reg);
3878 __ Addu(element, 3872 __ Daddu(element,
3879 elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 3873 elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
3880 __ sll(elements_end, array_length, kPointerSizeLog2); 3874 __ dsll(elements_end, array_length, kPointerSizeLog2);
3881 __ Addu(elements_end, element, elements_end); 3875 __ Daddu(elements_end, element, elements_end);
3882 // Loop condition: while (element < elements_end). 3876 // Loop condition: while (element < elements_end).
3883 // Live values in registers: 3877 // Live values in registers:
3884 // elements: Fixed array of strings. 3878 // elements: Fixed array of strings.
3885 // array_length: Length of the fixed array of strings (not smi) 3879 // array_length: Length of the fixed array of strings (not smi)
3886 // separator: Separator string 3880 // separator: Separator string
3887 // string_length: Accumulated sum of string lengths (smi). 3881 // string_length: Accumulated sum of string lengths (smi).
3888 // element: Current array element. 3882 // element: Current array element.
3889 // elements_end: Array end. 3883 // elements_end: Array end.
3890 if (generate_debug_code_) { 3884 if (generate_debug_code_) {
3891 __ Assert(gt, kNoEmptyArraysHereInEmitFastAsciiArrayJoin, 3885 __ Assert(gt, kNoEmptyArraysHereInEmitFastAsciiArrayJoin,
3892 array_length, Operand(zero_reg)); 3886 array_length, Operand(zero_reg));
3893 } 3887 }
3894 __ bind(&loop); 3888 __ bind(&loop);
3895 __ lw(string, MemOperand(element)); 3889 __ ld(string, MemOperand(element));
3896 __ Addu(element, element, kPointerSize); 3890 __ Daddu(element, element, kPointerSize);
3897 __ JumpIfSmi(string, &bailout); 3891 __ JumpIfSmi(string, &bailout);
3898 __ lw(scratch1, FieldMemOperand(string, HeapObject::kMapOffset)); 3892 __ ld(scratch1, FieldMemOperand(string, HeapObject::kMapOffset));
3899 __ lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); 3893 __ lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
3900 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout); 3894 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout);
3901 __ lw(scratch1, FieldMemOperand(string, SeqOneByteString::kLengthOffset)); 3895 __ ld(scratch1, FieldMemOperand(string, SeqOneByteString::kLengthOffset));
3902 __ AdduAndCheckForOverflow(string_length, string_length, scratch1, scratch3); 3896 __ AdduAndCheckForOverflow(string_length, string_length, scratch1, scratch3);
3903 __ BranchOnOverflow(&bailout, scratch3); 3897 __ BranchOnOverflow(&bailout, scratch3);
3904 __ Branch(&loop, lt, element, Operand(elements_end)); 3898 __ Branch(&loop, lt, element, Operand(elements_end));
3905 3899
3906 // If array_length is 1, return elements[0], a string. 3900 // If array_length is 1, return elements[0], a string.
3907 __ Branch(&not_size_one_array, ne, array_length, Operand(1)); 3901 __ Branch(&not_size_one_array, ne, array_length, Operand(1));
3908 __ lw(v0, FieldMemOperand(elements, FixedArray::kHeaderSize)); 3902 __ ld(v0, FieldMemOperand(elements, FixedArray::kHeaderSize));
3909 __ Branch(&done); 3903 __ Branch(&done);
3910 3904
3911 __ bind(&not_size_one_array); 3905 __ bind(&not_size_one_array);
3912 3906
3913 // Live values in registers: 3907 // Live values in registers:
3914 // separator: Separator string 3908 // separator: Separator string
3915 // array_length: Length of the array. 3909 // array_length: Length of the array.
3916 // string_length: Sum of string lengths (smi). 3910 // string_length: Sum of string lengths (smi).
3917 // elements: FixedArray of strings. 3911 // elements: FixedArray of strings.
3918 3912
3919 // Check that the separator is a flat ASCII string. 3913 // Check that the separator is a flat ASCII string.
3920 __ JumpIfSmi(separator, &bailout); 3914 __ JumpIfSmi(separator, &bailout);
3921 __ lw(scratch1, FieldMemOperand(separator, HeapObject::kMapOffset)); 3915 __ ld(scratch1, FieldMemOperand(separator, HeapObject::kMapOffset));
3922 __ lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); 3916 __ lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
3923 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout); 3917 __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout);
3924 3918
3925 // Add (separator length times array_length) - separator length to the 3919 // Add (separator length times array_length) - separator length to the
3926 // string_length to get the length of the result string. array_length is not 3920 // string_length to get the length of the result string. array_length is not
3927 // smi but the other values are, so the result is a smi. 3921 // smi but the other values are, so the result is a smi.
3928 __ lw(scratch1, FieldMemOperand(separator, SeqOneByteString::kLengthOffset)); 3922 __ ld(scratch1, FieldMemOperand(separator, SeqOneByteString::kLengthOffset));
3929 __ Subu(string_length, string_length, Operand(scratch1)); 3923 __ Dsubu(string_length, string_length, Operand(scratch1));
3930 __ Mult(array_length, scratch1); 3924 __ SmiUntag(scratch1);
3925 __ Dmult(array_length, scratch1);
3931 // Check for smi overflow. No overflow if higher 33 bits of 64-bit result are 3926 // Check for smi overflow. No overflow if higher 33 bits of 64-bit result are
3932 // zero. 3927 // zero.
3933 __ mfhi(scratch2); 3928 __ mfhi(scratch2);
3934 __ Branch(&bailout, ne, scratch2, Operand(zero_reg)); 3929 __ Branch(&bailout, ne, scratch2, Operand(zero_reg));
3935 __ mflo(scratch2); 3930 __ mflo(scratch2);
3936 __ And(scratch3, scratch2, Operand(0x80000000)); 3931 __ SmiUntag(string_length);
3937 __ Branch(&bailout, ne, scratch3, Operand(zero_reg));
3938 __ AdduAndCheckForOverflow(string_length, string_length, scratch2, scratch3); 3932 __ AdduAndCheckForOverflow(string_length, string_length, scratch2, scratch3);
3939 __ BranchOnOverflow(&bailout, scratch3); 3933 __ BranchOnOverflow(&bailout, scratch3);
3940 __ SmiUntag(string_length);
3941 3934
3942 // Get first element in the array to free up the elements register to be used 3935 // Get first element in the array to free up the elements register to be used
3943 // for the result. 3936 // for the result.
3944 __ Addu(element, 3937 __ Daddu(element,
3945 elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 3938 elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
3946 result = elements; // End of live range for elements. 3939 result = elements; // End of live range for elements.
3947 elements = no_reg; 3940 elements = no_reg;
3948 // Live values in registers: 3941 // Live values in registers:
3949 // element: First array element 3942 // element: First array element
3950 // separator: Separator string 3943 // separator: Separator string
3951 // string_length: Length of result string (not smi) 3944 // string_length: Length of result string (not smi)
3952 // array_length: Length of the array. 3945 // array_length: Length of the array.
3953 __ AllocateAsciiString(result, 3946 __ AllocateAsciiString(result,
3954 string_length, 3947 string_length,
3955 scratch1, 3948 scratch1,
3956 scratch2, 3949 scratch2,
3957 elements_end, 3950 elements_end,
3958 &bailout); 3951 &bailout);
3959 // Prepare for looping. Set up elements_end to end of the array. Set 3952 // Prepare for looping. Set up elements_end to end of the array. Set
3960 // result_pos to the position of the result where to write the first 3953 // result_pos to the position of the result where to write the first
3961 // character. 3954 // character.
3962 __ sll(elements_end, array_length, kPointerSizeLog2); 3955 __ dsll(elements_end, array_length, kPointerSizeLog2);
3963 __ Addu(elements_end, element, elements_end); 3956 __ Daddu(elements_end, element, elements_end);
3964 result_pos = array_length; // End of live range for array_length. 3957 result_pos = array_length; // End of live range for array_length.
3965 array_length = no_reg; 3958 array_length = no_reg;
3966 __ Addu(result_pos, 3959 __ Daddu(result_pos,
3967 result, 3960 result,
3968 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 3961 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
3969 3962
3970 // Check the length of the separator. 3963 // Check the length of the separator.
3971 __ lw(scratch1, FieldMemOperand(separator, SeqOneByteString::kLengthOffset)); 3964 __ ld(scratch1, FieldMemOperand(separator, SeqOneByteString::kLengthOffset));
3972 __ li(at, Operand(Smi::FromInt(1))); 3965 __ li(at, Operand(Smi::FromInt(1)));
3973 __ Branch(&one_char_separator, eq, scratch1, Operand(at)); 3966 __ Branch(&one_char_separator, eq, scratch1, Operand(at));
3974 __ Branch(&long_separator, gt, scratch1, Operand(at)); 3967 __ Branch(&long_separator, gt, scratch1, Operand(at));
3975 3968
3976 // Empty separator case. 3969 // Empty separator case.
3977 __ bind(&empty_separator_loop); 3970 __ bind(&empty_separator_loop);
3978 // Live values in registers: 3971 // Live values in registers:
3979 // result_pos: the position to which we are currently copying characters. 3972 // result_pos: the position to which we are currently copying characters.
3980 // element: Current array element. 3973 // element: Current array element.
3981 // elements_end: Array end. 3974 // elements_end: Array end.
3982 3975
3983 // Copy next array element to the result. 3976 // Copy next array element to the result.
3984 __ lw(string, MemOperand(element)); 3977 __ ld(string, MemOperand(element));
3985 __ Addu(element, element, kPointerSize); 3978 __ Daddu(element, element, kPointerSize);
3986 __ lw(string_length, FieldMemOperand(string, String::kLengthOffset)); 3979 __ ld(string_length, FieldMemOperand(string, String::kLengthOffset));
3987 __ SmiUntag(string_length); 3980 __ SmiUntag(string_length);
3988 __ Addu(string, string, SeqOneByteString::kHeaderSize - kHeapObjectTag); 3981 __ Daddu(string, string, SeqOneByteString::kHeaderSize - kHeapObjectTag);
3989 __ CopyBytes(string, result_pos, string_length, scratch1); 3982 __ CopyBytes(string, result_pos, string_length, scratch1);
3990 // End while (element < elements_end). 3983 // End while (element < elements_end).
3991 __ Branch(&empty_separator_loop, lt, element, Operand(elements_end)); 3984 __ Branch(&empty_separator_loop, lt, element, Operand(elements_end));
3992 ASSERT(result.is(v0)); 3985 ASSERT(result.is(v0));
3993 __ Branch(&done); 3986 __ Branch(&done);
3994 3987
3995 // One-character separator case. 3988 // One-character separator case.
3996 __ bind(&one_char_separator); 3989 __ bind(&one_char_separator);
3997 // Replace separator with its ASCII character value. 3990 // Replace separator with its ASCII character value.
3998 __ lbu(separator, FieldMemOperand(separator, SeqOneByteString::kHeaderSize)); 3991 __ lbu(separator, FieldMemOperand(separator, SeqOneByteString::kHeaderSize));
3999 // Jump into the loop after the code that copies the separator, so the first 3992 // Jump into the loop after the code that copies the separator, so the first
4000 // element is not preceded by a separator. 3993 // element is not preceded by a separator.
4001 __ jmp(&one_char_separator_loop_entry); 3994 __ jmp(&one_char_separator_loop_entry);
4002 3995
4003 __ bind(&one_char_separator_loop); 3996 __ bind(&one_char_separator_loop);
4004 // Live values in registers: 3997 // Live values in registers:
4005 // result_pos: the position to which we are currently copying characters. 3998 // result_pos: the position to which we are currently copying characters.
4006 // element: Current array element. 3999 // element: Current array element.
4007 // elements_end: Array end. 4000 // elements_end: Array end.
4008 // separator: Single separator ASCII char (in lower byte). 4001 // separator: Single separator ASCII char (in lower byte).
4009 4002
4010 // Copy the separator character to the result. 4003 // Copy the separator character to the result.
4011 __ sb(separator, MemOperand(result_pos)); 4004 __ sb(separator, MemOperand(result_pos));
4012 __ Addu(result_pos, result_pos, 1); 4005 __ Daddu(result_pos, result_pos, 1);
4013 4006
4014 // Copy next array element to the result. 4007 // Copy next array element to the result.
4015 __ bind(&one_char_separator_loop_entry); 4008 __ bind(&one_char_separator_loop_entry);
4016 __ lw(string, MemOperand(element)); 4009 __ ld(string, MemOperand(element));
4017 __ Addu(element, element, kPointerSize); 4010 __ Daddu(element, element, kPointerSize);
4018 __ lw(string_length, FieldMemOperand(string, String::kLengthOffset)); 4011 __ ld(string_length, FieldMemOperand(string, String::kLengthOffset));
4019 __ SmiUntag(string_length); 4012 __ SmiUntag(string_length);
4020 __ Addu(string, string, SeqOneByteString::kHeaderSize - kHeapObjectTag); 4013 __ Daddu(string, string, SeqOneByteString::kHeaderSize - kHeapObjectTag);
4021 __ CopyBytes(string, result_pos, string_length, scratch1); 4014 __ CopyBytes(string, result_pos, string_length, scratch1);
4022 // End while (element < elements_end). 4015 // End while (element < elements_end).
4023 __ Branch(&one_char_separator_loop, lt, element, Operand(elements_end)); 4016 __ Branch(&one_char_separator_loop, lt, element, Operand(elements_end));
4024 ASSERT(result.is(v0)); 4017 ASSERT(result.is(v0));
4025 __ Branch(&done); 4018 __ Branch(&done);
4026 4019
4027 // Long separator case (separator is more than one character). Entry is at the 4020 // Long separator case (separator is more than one character). Entry is at the
4028 // label long_separator below. 4021 // label long_separator below.
4029 __ bind(&long_separator_loop); 4022 __ bind(&long_separator_loop);
4030 // Live values in registers: 4023 // Live values in registers:
4031 // result_pos: the position to which we are currently copying characters. 4024 // result_pos: the position to which we are currently copying characters.
4032 // element: Current array element. 4025 // element: Current array element.
4033 // elements_end: Array end. 4026 // elements_end: Array end.
4034 // separator: Separator string. 4027 // separator: Separator string.
4035 4028
4036 // Copy the separator to the result. 4029 // Copy the separator to the result.
4037 __ lw(string_length, FieldMemOperand(separator, String::kLengthOffset)); 4030 __ ld(string_length, FieldMemOperand(separator, String::kLengthOffset));
4038 __ SmiUntag(string_length); 4031 __ SmiUntag(string_length);
4039 __ Addu(string, 4032 __ Daddu(string,
4040 separator, 4033 separator,
4041 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 4034 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
4042 __ CopyBytes(string, result_pos, string_length, scratch1); 4035 __ CopyBytes(string, result_pos, string_length, scratch1);
4043 4036
4044 __ bind(&long_separator); 4037 __ bind(&long_separator);
4045 __ lw(string, MemOperand(element)); 4038 __ ld(string, MemOperand(element));
4046 __ Addu(element, element, kPointerSize); 4039 __ Daddu(element, element, kPointerSize);
4047 __ lw(string_length, FieldMemOperand(string, String::kLengthOffset)); 4040 __ ld(string_length, FieldMemOperand(string, String::kLengthOffset));
4048 __ SmiUntag(string_length); 4041 __ SmiUntag(string_length);
4049 __ Addu(string, string, SeqOneByteString::kHeaderSize - kHeapObjectTag); 4042 __ Daddu(string, string, SeqOneByteString::kHeaderSize - kHeapObjectTag);
4050 __ CopyBytes(string, result_pos, string_length, scratch1); 4043 __ CopyBytes(string, result_pos, string_length, scratch1);
4051 // End while (element < elements_end). 4044 // End while (element < elements_end).
4052 __ Branch(&long_separator_loop, lt, element, Operand(elements_end)); 4045 __ Branch(&long_separator_loop, lt, element, Operand(elements_end));
4053 ASSERT(result.is(v0)); 4046 ASSERT(result.is(v0));
4054 __ Branch(&done); 4047 __ Branch(&done);
4055 4048
4056 __ bind(&bailout); 4049 __ bind(&bailout);
4057 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); 4050 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex);
4058 __ bind(&done); 4051 __ bind(&done);
4059 context()->Plug(v0); 4052 context()->Plug(v0);
4060 } 4053 }
4061 4054
4062 4055
4063 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { 4056 void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
4064 ASSERT(expr->arguments()->length() == 0); 4057 ASSERT(expr->arguments()->length() == 0);
4065 ExternalReference debug_is_active = 4058 ExternalReference debug_is_active =
4066 ExternalReference::debug_is_active_address(isolate()); 4059 ExternalReference::debug_is_active_address(isolate());
4067 __ li(at, Operand(debug_is_active)); 4060 __ li(at, Operand(debug_is_active));
4068 __ lb(v0, MemOperand(at)); 4061 __ lbu(v0, MemOperand(at));
4069 __ SmiTag(v0); 4062 __ SmiTag(v0);
4070 context()->Plug(v0); 4063 context()->Plug(v0);
4071 } 4064 }
4072 4065
4073 4066
4074 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 4067 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
4075 if (expr->function() != NULL && 4068 if (expr->function() != NULL &&
4076 expr->function()->intrinsic_type == Runtime::INLINE) { 4069 expr->function()->intrinsic_type == Runtime::INLINE) {
4077 Comment cmnt(masm_, "[ InlineRuntimeCall"); 4070 Comment cmnt(masm_, "[ InlineRuntimeCall");
4078 EmitInlineRuntimeCall(expr); 4071 EmitInlineRuntimeCall(expr);
4079 return; 4072 return;
4080 } 4073 }
4081 4074
4082 Comment cmnt(masm_, "[ CallRuntime"); 4075 Comment cmnt(masm_, "[ CallRuntime");
4083 ZoneList<Expression*>* args = expr->arguments(); 4076 ZoneList<Expression*>* args = expr->arguments();
4084 int arg_count = args->length(); 4077 int arg_count = args->length();
4085 4078
4086 if (expr->is_jsruntime()) { 4079 if (expr->is_jsruntime()) {
4087 // Push the builtins object as the receiver. 4080 // Push the builtins object as the receiver.
4088 Register receiver = LoadIC::ReceiverRegister(); 4081 Register receiver = LoadIC::ReceiverRegister();
4089 __ lw(receiver, GlobalObjectOperand()); 4082 __ ld(receiver, GlobalObjectOperand());
4090 __ lw(receiver, FieldMemOperand(receiver, GlobalObject::kBuiltinsOffset)); 4083 __ ld(receiver, FieldMemOperand(receiver, GlobalObject::kBuiltinsOffset));
4091 __ push(receiver); 4084 __ push(receiver);
4092 4085
4093 // Load the function from the receiver. 4086 // Load the function from the receiver.
4094 __ li(LoadIC::NameRegister(), Operand(expr->name())); 4087 __ li(LoadIC::NameRegister(), Operand(expr->name()));
4095 CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); 4088 CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
4096 4089
4097 // Push the target function under the receiver. 4090 // Push the target function under the receiver.
4098 __ lw(at, MemOperand(sp, 0)); 4091 __ ld(at, MemOperand(sp, 0));
4099 __ push(at); 4092 __ push(at);
4100 __ sw(v0, MemOperand(sp, kPointerSize)); 4093 __ sd(v0, MemOperand(sp, kPointerSize));
4101 4094
4102 // Push the arguments ("left-to-right"). 4095 // Push the arguments ("left-to-right").
4103 int arg_count = args->length(); 4096 int arg_count = args->length();
4104 for (int i = 0; i < arg_count; i++) { 4097 for (int i = 0; i < arg_count; i++) {
4105 VisitForStackValue(args->at(i)); 4098 VisitForStackValue(args->at(i));
4106 } 4099 }
4107 4100
4108 // Record source position of the IC call. 4101 // Record source position of the IC call.
4109 SetSourcePosition(expr->position()); 4102 SetSourcePosition(expr->position());
4110 CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS); 4103 CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
4111 __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize)); 4104 __ ld(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
4112 __ CallStub(&stub); 4105 __ CallStub(&stub);
4113 4106
4114 // Restore context register. 4107 // Restore context register.
4115 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 4108 __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
4116 4109
4117 context()->DropAndPlug(1, v0); 4110 context()->DropAndPlug(1, v0);
4118 } else { 4111 } else {
4119 // Push the arguments ("left-to-right"). 4112 // Push the arguments ("left-to-right").
4120 for (int i = 0; i < arg_count; i++) { 4113 for (int i = 0; i < arg_count; i++) {
4121 VisitForStackValue(args->at(i)); 4114 VisitForStackValue(args->at(i));
4122 } 4115 }
4123 4116
4124 // Call the C runtime function. 4117 // Call the C runtime function.
4125 __ CallRuntime(expr->function(), arg_count); 4118 __ CallRuntime(expr->function(), arg_count);
(...skipping 15 matching lines...) Expand all
4141 __ li(a1, Operand(Smi::FromInt(strict_mode()))); 4134 __ li(a1, Operand(Smi::FromInt(strict_mode())));
4142 __ push(a1); 4135 __ push(a1);
4143 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 4136 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
4144 context()->Plug(v0); 4137 context()->Plug(v0);
4145 } else if (proxy != NULL) { 4138 } else if (proxy != NULL) {
4146 Variable* var = proxy->var(); 4139 Variable* var = proxy->var();
4147 // Delete of an unqualified identifier is disallowed in strict mode 4140 // Delete of an unqualified identifier is disallowed in strict mode
4148 // but "delete this" is allowed. 4141 // but "delete this" is allowed.
4149 ASSERT(strict_mode() == SLOPPY || var->is_this()); 4142 ASSERT(strict_mode() == SLOPPY || var->is_this());
4150 if (var->IsUnallocated()) { 4143 if (var->IsUnallocated()) {
4151 __ lw(a2, GlobalObjectOperand()); 4144 __ ld(a2, GlobalObjectOperand());
4152 __ li(a1, Operand(var->name())); 4145 __ li(a1, Operand(var->name()));
4153 __ li(a0, Operand(Smi::FromInt(SLOPPY))); 4146 __ li(a0, Operand(Smi::FromInt(SLOPPY)));
4154 __ Push(a2, a1, a0); 4147 __ Push(a2, a1, a0);
4155 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 4148 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
4156 context()->Plug(v0); 4149 context()->Plug(v0);
4157 } else if (var->IsStackAllocated() || var->IsContextSlot()) { 4150 } else if (var->IsStackAllocated() || var->IsContextSlot()) {
4158 // Result of deleting non-global, non-dynamic variables is false. 4151 // Result of deleting non-global, non-dynamic variables is false.
4159 // The subexpression does not have side effects. 4152 // The subexpression does not have side effects.
4160 context()->Plug(var->is_this()); 4153 context()->Plug(var->is_this());
4161 } else { 4154 } else {
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
4263 EmitVariableLoad(expr->expression()->AsVariableProxy()); 4256 EmitVariableLoad(expr->expression()->AsVariableProxy());
4264 } else { 4257 } else {
4265 // Reserve space for result of postfix operation. 4258 // Reserve space for result of postfix operation.
4266 if (expr->is_postfix() && !context()->IsEffect()) { 4259 if (expr->is_postfix() && !context()->IsEffect()) {
4267 __ li(at, Operand(Smi::FromInt(0))); 4260 __ li(at, Operand(Smi::FromInt(0)));
4268 __ push(at); 4261 __ push(at);
4269 } 4262 }
4270 if (assign_type == NAMED_PROPERTY) { 4263 if (assign_type == NAMED_PROPERTY) {
4271 // Put the object both on the stack and in the register. 4264 // Put the object both on the stack and in the register.
4272 VisitForStackValue(prop->obj()); 4265 VisitForStackValue(prop->obj());
4273 __ lw(LoadIC::ReceiverRegister(), MemOperand(sp, 0)); 4266 __ ld(LoadIC::ReceiverRegister(), MemOperand(sp, 0));
4274 EmitNamedPropertyLoad(prop); 4267 EmitNamedPropertyLoad(prop);
4275 } else { 4268 } else {
4276 VisitForStackValue(prop->obj()); 4269 VisitForStackValue(prop->obj());
4277 VisitForStackValue(prop->key()); 4270 VisitForStackValue(prop->key());
4278 __ lw(LoadIC::ReceiverRegister(), MemOperand(sp, 1 * kPointerSize)); 4271 __ ld(LoadIC::ReceiverRegister(), MemOperand(sp, 1 * kPointerSize));
4279 __ lw(LoadIC::NameRegister(), MemOperand(sp, 0)); 4272 __ ld(LoadIC::NameRegister(), MemOperand(sp, 0));
4280 EmitKeyedPropertyLoad(prop); 4273 EmitKeyedPropertyLoad(prop);
4281 } 4274 }
4282 } 4275 }
4283 4276
4284 // We need a second deoptimization point after loading the value 4277 // We need a second deoptimization point after loading the value
4285 // in case evaluating the property load my have a side effect. 4278 // in case evaluating the property load my have a side effect.
4286 if (assign_type == VARIABLE) { 4279 if (assign_type == VARIABLE) {
4287 PrepareForBailout(expr->expression(), TOS_REG); 4280 PrepareForBailout(expr->expression(), TOS_REG);
4288 } else { 4281 } else {
4289 PrepareForBailoutForId(prop->LoadId(), TOS_REG); 4282 PrepareForBailoutForId(prop->LoadId(), TOS_REG);
(...skipping 13 matching lines...) Expand all
4303 if (expr->is_postfix()) { 4296 if (expr->is_postfix()) {
4304 if (!context()->IsEffect()) { 4297 if (!context()->IsEffect()) {
4305 // Save the result on the stack. If we have a named or keyed property 4298 // Save the result on the stack. If we have a named or keyed property
4306 // we store the result under the receiver that is currently on top 4299 // we store the result under the receiver that is currently on top
4307 // of the stack. 4300 // of the stack.
4308 switch (assign_type) { 4301 switch (assign_type) {
4309 case VARIABLE: 4302 case VARIABLE:
4310 __ push(v0); 4303 __ push(v0);
4311 break; 4304 break;
4312 case NAMED_PROPERTY: 4305 case NAMED_PROPERTY:
4313 __ sw(v0, MemOperand(sp, kPointerSize)); 4306 __ sd(v0, MemOperand(sp, kPointerSize));
4314 break; 4307 break;
4315 case KEYED_PROPERTY: 4308 case KEYED_PROPERTY:
4316 __ sw(v0, MemOperand(sp, 2 * kPointerSize)); 4309 __ sd(v0, MemOperand(sp, 2 * kPointerSize));
4317 break; 4310 break;
4318 } 4311 }
4319 } 4312 }
4320 } 4313 }
4321 4314
4322 Register scratch1 = a1; 4315 Register scratch1 = a1;
4323 Register scratch2 = t0; 4316 Register scratch2 = a4;
4324 __ li(scratch1, Operand(Smi::FromInt(count_value))); 4317 __ li(scratch1, Operand(Smi::FromInt(count_value)));
4325 __ AdduAndCheckForOverflow(v0, v0, scratch1, scratch2); 4318 __ AdduAndCheckForOverflow(v0, v0, scratch1, scratch2);
4326 __ BranchOnNoOverflow(&done, scratch2); 4319 __ BranchOnNoOverflow(&done, scratch2);
4327 // Call stub. Undo operation first. 4320 // Call stub. Undo operation first.
4328 __ Move(v0, a0); 4321 __ Move(v0, a0);
4329 __ jmp(&stub_call); 4322 __ jmp(&stub_call);
4330 __ bind(&slow); 4323 __ bind(&slow);
4331 } 4324 }
4332 ToNumberStub convert_stub(isolate()); 4325 ToNumberStub convert_stub(isolate());
4333 __ CallStub(&convert_stub); 4326 __ CallStub(&convert_stub);
4334 4327
4335 // Save result for postfix expressions. 4328 // Save result for postfix expressions.
4336 if (expr->is_postfix()) { 4329 if (expr->is_postfix()) {
4337 if (!context()->IsEffect()) { 4330 if (!context()->IsEffect()) {
4338 // Save the result on the stack. If we have a named or keyed property 4331 // Save the result on the stack. If we have a named or keyed property
4339 // we store the result under the receiver that is currently on top 4332 // we store the result under the receiver that is currently on top
4340 // of the stack. 4333 // of the stack.
4341 switch (assign_type) { 4334 switch (assign_type) {
4342 case VARIABLE: 4335 case VARIABLE:
4343 __ push(v0); 4336 __ push(v0);
4344 break; 4337 break;
4345 case NAMED_PROPERTY: 4338 case NAMED_PROPERTY:
4346 __ sw(v0, MemOperand(sp, kPointerSize)); 4339 __ sd(v0, MemOperand(sp, kPointerSize));
4347 break; 4340 break;
4348 case KEYED_PROPERTY: 4341 case KEYED_PROPERTY:
4349 __ sw(v0, MemOperand(sp, 2 * kPointerSize)); 4342 __ sd(v0, MemOperand(sp, 2 * kPointerSize));
4350 break; 4343 break;
4351 } 4344 }
4352 } 4345 }
4353 } 4346 }
4354 4347
4355 __ bind(&stub_call); 4348 __ bind(&stub_call);
4356 __ mov(a1, v0); 4349 __ mov(a1, v0);
4357 __ li(a0, Operand(Smi::FromInt(count_value))); 4350 __ li(a0, Operand(Smi::FromInt(count_value)));
4358 4351
4359 // Record position before stub call. 4352 // Record position before stub call.
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
4421 } 4414 }
4422 } 4415 }
4423 4416
4424 4417
4425 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { 4418 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
4426 ASSERT(!context()->IsEffect()); 4419 ASSERT(!context()->IsEffect());
4427 ASSERT(!context()->IsTest()); 4420 ASSERT(!context()->IsTest());
4428 VariableProxy* proxy = expr->AsVariableProxy(); 4421 VariableProxy* proxy = expr->AsVariableProxy();
4429 if (proxy != NULL && proxy->var()->IsUnallocated()) { 4422 if (proxy != NULL && proxy->var()->IsUnallocated()) {
4430 Comment cmnt(masm_, "[ Global variable"); 4423 Comment cmnt(masm_, "[ Global variable");
4431 __ lw(LoadIC::ReceiverRegister(), GlobalObjectOperand()); 4424 __ ld(LoadIC::ReceiverRegister(), GlobalObjectOperand());
4432 __ li(LoadIC::NameRegister(), Operand(proxy->name())); 4425 __ li(LoadIC::NameRegister(), Operand(proxy->name()));
4433 // Use a regular load, not a contextual load, to avoid a reference 4426 // Use a regular load, not a contextual load, to avoid a reference
4434 // error. 4427 // error.
4435 CallLoadIC(NOT_CONTEXTUAL); 4428 CallLoadIC(NOT_CONTEXTUAL);
4436 PrepareForBailout(expr, TOS_REG); 4429 PrepareForBailout(expr, TOS_REG);
4437 context()->Plug(v0); 4430 context()->Plug(v0);
4438 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { 4431 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
4439 Comment cmnt(masm_, "[ Lookup slot"); 4432 Comment cmnt(masm_, "[ Lookup slot");
4440 Label done, slow; 4433 Label done, slow;
4441 4434
(...skipping 26 matching lines...) Expand all
4468 &if_true, &if_false, &fall_through); 4461 &if_true, &if_false, &fall_through);
4469 4462
4470 { AccumulatorValueContext context(this); 4463 { AccumulatorValueContext context(this);
4471 VisitForTypeofValue(sub_expr); 4464 VisitForTypeofValue(sub_expr);
4472 } 4465 }
4473 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 4466 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4474 4467
4475 Factory* factory = isolate()->factory(); 4468 Factory* factory = isolate()->factory();
4476 if (String::Equals(check, factory->number_string())) { 4469 if (String::Equals(check, factory->number_string())) {
4477 __ JumpIfSmi(v0, if_true); 4470 __ JumpIfSmi(v0, if_true);
4478 __ lw(v0, FieldMemOperand(v0, HeapObject::kMapOffset)); 4471 __ ld(v0, FieldMemOperand(v0, HeapObject::kMapOffset));
4479 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); 4472 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
4480 Split(eq, v0, Operand(at), if_true, if_false, fall_through); 4473 Split(eq, v0, Operand(at), if_true, if_false, fall_through);
4481 } else if (String::Equals(check, factory->string_string())) { 4474 } else if (String::Equals(check, factory->string_string())) {
4482 __ JumpIfSmi(v0, if_false); 4475 __ JumpIfSmi(v0, if_false);
4483 // Check for undetectable objects => false. 4476 // Check for undetectable objects => false.
4484 __ GetObjectType(v0, v0, a1); 4477 __ GetObjectType(v0, v0, a1);
4485 __ Branch(if_false, ge, a1, Operand(FIRST_NONSTRING_TYPE)); 4478 __ Branch(if_false, ge, a1, Operand(FIRST_NONSTRING_TYPE));
4486 __ lbu(a1, FieldMemOperand(v0, Map::kBitFieldOffset)); 4479 __ lbu(a1, FieldMemOperand(v0, Map::kBitFieldOffset));
4487 __ And(a1, a1, Operand(1 << Map::kIsUndetectable)); 4480 __ And(a1, a1, Operand(1 << Map::kIsUndetectable));
4488 Split(eq, a1, Operand(zero_reg), 4481 Split(eq, a1, Operand(zero_reg),
4489 if_true, if_false, fall_through); 4482 if_true, if_false, fall_through);
4490 } else if (String::Equals(check, factory->symbol_string())) { 4483 } else if (String::Equals(check, factory->symbol_string())) {
4491 __ JumpIfSmi(v0, if_false); 4484 __ JumpIfSmi(v0, if_false);
4492 __ GetObjectType(v0, v0, a1); 4485 __ GetObjectType(v0, v0, a1);
4493 Split(eq, a1, Operand(SYMBOL_TYPE), if_true, if_false, fall_through); 4486 Split(eq, a1, Operand(SYMBOL_TYPE), if_true, if_false, fall_through);
4494 } else if (String::Equals(check, factory->boolean_string())) { 4487 } else if (String::Equals(check, factory->boolean_string())) {
4495 __ LoadRoot(at, Heap::kTrueValueRootIndex); 4488 __ LoadRoot(at, Heap::kTrueValueRootIndex);
4496 __ Branch(if_true, eq, v0, Operand(at)); 4489 __ Branch(if_true, eq, v0, Operand(at));
4497 __ LoadRoot(at, Heap::kFalseValueRootIndex); 4490 __ LoadRoot(at, Heap::kFalseValueRootIndex);
4498 Split(eq, v0, Operand(at), if_true, if_false, fall_through); 4491 Split(eq, v0, Operand(at), if_true, if_false, fall_through);
4499 } else if (FLAG_harmony_typeof && 4492 } else if (FLAG_harmony_typeof &&
4500 String::Equals(check, factory->null_string())) { 4493 String::Equals(check, factory->null_string())) {
4501 __ LoadRoot(at, Heap::kNullValueRootIndex); 4494 __ LoadRoot(at, Heap::kNullValueRootIndex);
4502 Split(eq, v0, Operand(at), if_true, if_false, fall_through); 4495 Split(eq, v0, Operand(at), if_true, if_false, fall_through);
4503 } else if (String::Equals(check, factory->undefined_string())) { 4496 } else if (String::Equals(check, factory->undefined_string())) {
4504 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); 4497 __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
4505 __ Branch(if_true, eq, v0, Operand(at)); 4498 __ Branch(if_true, eq, v0, Operand(at));
4506 __ JumpIfSmi(v0, if_false); 4499 __ JumpIfSmi(v0, if_false);
4507 // Check for undetectable objects => true. 4500 // Check for undetectable objects => true.
4508 __ lw(v0, FieldMemOperand(v0, HeapObject::kMapOffset)); 4501 __ ld(v0, FieldMemOperand(v0, HeapObject::kMapOffset));
4509 __ lbu(a1, FieldMemOperand(v0, Map::kBitFieldOffset)); 4502 __ lbu(a1, FieldMemOperand(v0, Map::kBitFieldOffset));
4510 __ And(a1, a1, Operand(1 << Map::kIsUndetectable)); 4503 __ And(a1, a1, Operand(1 << Map::kIsUndetectable));
4511 Split(ne, a1, Operand(zero_reg), if_true, if_false, fall_through); 4504 Split(ne, a1, Operand(zero_reg), if_true, if_false, fall_through);
4512 } else if (String::Equals(check, factory->function_string())) { 4505 } else if (String::Equals(check, factory->function_string())) {
4513 __ JumpIfSmi(v0, if_false); 4506 __ JumpIfSmi(v0, if_false);
4514 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); 4507 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
4515 __ GetObjectType(v0, v0, a1); 4508 __ GetObjectType(v0, v0, a1);
4516 __ Branch(if_true, eq, a1, Operand(JS_FUNCTION_TYPE)); 4509 __ Branch(if_true, eq, a1, Operand(JS_FUNCTION_TYPE));
4517 Split(eq, a1, Operand(JS_FUNCTION_PROXY_TYPE), 4510 Split(eq, a1, Operand(JS_FUNCTION_PROXY_TYPE),
4518 if_true, if_false, fall_through); 4511 if_true, if_false, fall_through);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
4555 context()->PrepareTest(&materialize_true, &materialize_false, 4548 context()->PrepareTest(&materialize_true, &materialize_false,
4556 &if_true, &if_false, &fall_through); 4549 &if_true, &if_false, &fall_through);
4557 4550
4558 Token::Value op = expr->op(); 4551 Token::Value op = expr->op();
4559 VisitForStackValue(expr->left()); 4552 VisitForStackValue(expr->left());
4560 switch (op) { 4553 switch (op) {
4561 case Token::IN: 4554 case Token::IN:
4562 VisitForStackValue(expr->right()); 4555 VisitForStackValue(expr->right());
4563 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 4556 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
4564 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); 4557 PrepareForBailoutBeforeSplit(expr, false, NULL, NULL);
4565 __ LoadRoot(t0, Heap::kTrueValueRootIndex); 4558 __ LoadRoot(a4, Heap::kTrueValueRootIndex);
4566 Split(eq, v0, Operand(t0), if_true, if_false, fall_through); 4559 Split(eq, v0, Operand(a4), if_true, if_false, fall_through);
4567 break; 4560 break;
4568 4561
4569 case Token::INSTANCEOF: { 4562 case Token::INSTANCEOF: {
4570 VisitForStackValue(expr->right()); 4563 VisitForStackValue(expr->right());
4571 InstanceofStub stub(isolate(), InstanceofStub::kNoFlags); 4564 InstanceofStub stub(isolate(), InstanceofStub::kNoFlags);
4572 __ CallStub(&stub); 4565 __ CallStub(&stub);
4573 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 4566 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4574 // The stub returns 0 for true. 4567 // The stub returns 0 for true.
4575 Split(eq, v0, Operand(zero_reg), if_true, if_false, fall_through); 4568 Split(eq, v0, Operand(zero_reg), if_true, if_false, fall_through);
4576 break; 4569 break;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
4629 } else { 4622 } else {
4630 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); 4623 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil);
4631 CallIC(ic, expr->CompareOperationFeedbackId()); 4624 CallIC(ic, expr->CompareOperationFeedbackId());
4632 Split(ne, v0, Operand(zero_reg), if_true, if_false, fall_through); 4625 Split(ne, v0, Operand(zero_reg), if_true, if_false, fall_through);
4633 } 4626 }
4634 context()->Plug(if_true, if_false); 4627 context()->Plug(if_true, if_false);
4635 } 4628 }
4636 4629
4637 4630
4638 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { 4631 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
4639 __ lw(v0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 4632 __ ld(v0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
4640 context()->Plug(v0); 4633 context()->Plug(v0);
4641 } 4634 }
4642 4635
4643 4636
4644 Register FullCodeGenerator::result_register() { 4637 Register FullCodeGenerator::result_register() {
4645 return v0; 4638 return v0;
4646 } 4639 }
4647 4640
4648 4641
4649 Register FullCodeGenerator::context_register() { 4642 Register FullCodeGenerator::context_register() {
4650 return cp; 4643 return cp;
4651 } 4644 }
4652 4645
4653 4646
4654 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 4647 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
4655 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); 4648 // ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
4656 __ sw(value, MemOperand(fp, frame_offset)); 4649 ASSERT(IsAligned(frame_offset, kPointerSize));
4650 // __ sw(value, MemOperand(fp, frame_offset));
4651 __ sd(value, MemOperand(fp, frame_offset));
4657 } 4652 }
4658 4653
4659 4654
4660 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { 4655 void FullCodeGenerator::LoadContextField(Register dst, int context_index) {
4661 __ lw(dst, ContextOperand(cp, context_index)); 4656 __ ld(dst, ContextOperand(cp, context_index));
4662 } 4657 }
4663 4658
4664 4659
4665 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() { 4660 void FullCodeGenerator::PushFunctionArgumentForContextAllocation() {
4666 Scope* declaration_scope = scope()->DeclarationScope(); 4661 Scope* declaration_scope = scope()->DeclarationScope();
4667 if (declaration_scope->is_global_scope() || 4662 if (declaration_scope->is_global_scope() ||
4668 declaration_scope->is_module_scope()) { 4663 declaration_scope->is_module_scope()) {
4669 // Contexts nested in the native context have a canonical empty function 4664 // Contexts nested in the native context have a canonical empty function
4670 // as their closure, not the anonymous closure containing the global 4665 // as their closure, not the anonymous closure containing the global
4671 // code. Pass a smi sentinel and let the runtime look up the empty 4666 // code. Pass a smi sentinel and let the runtime look up the empty
4672 // function. 4667 // function.
4673 __ li(at, Operand(Smi::FromInt(0))); 4668 __ li(at, Operand(Smi::FromInt(0)));
4674 } else if (declaration_scope->is_eval_scope()) { 4669 } else if (declaration_scope->is_eval_scope()) {
4675 // Contexts created by a call to eval have the same closure as the 4670 // Contexts created by a call to eval have the same closure as the
4676 // context calling eval, not the anonymous closure containing the eval 4671 // context calling eval, not the anonymous closure containing the eval
4677 // code. Fetch it from the context. 4672 // code. Fetch it from the context.
4678 __ lw(at, ContextOperand(cp, Context::CLOSURE_INDEX)); 4673 __ ld(at, ContextOperand(cp, Context::CLOSURE_INDEX));
4679 } else { 4674 } else {
4680 ASSERT(declaration_scope->is_function_scope()); 4675 ASSERT(declaration_scope->is_function_scope());
4681 __ lw(at, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 4676 __ ld(at, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
4682 } 4677 }
4683 __ push(at); 4678 __ push(at);
4684 } 4679 }
4685 4680
4686 4681
4687 // ---------------------------------------------------------------------------- 4682 // ----------------------------------------------------------------------------
4688 // Non-local control flow support. 4683 // Non-local control flow support.
4689 4684
4690 void FullCodeGenerator::EnterFinallyBlock() { 4685 void FullCodeGenerator::EnterFinallyBlock() {
4691 ASSERT(!result_register().is(a1)); 4686 ASSERT(!result_register().is(a1));
4692 // Store result register while executing finally block. 4687 // Store result register while executing finally block.
4693 __ push(result_register()); 4688 __ push(result_register());
4694 // Cook return address in link register to stack (smi encoded Code* delta). 4689 // Cook return address in link register to stack (smi encoded Code* delta).
4695 __ Subu(a1, ra, Operand(masm_->CodeObject())); 4690 __ Dsubu(a1, ra, Operand(masm_->CodeObject()));
4696 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); 4691 __ SmiTag(a1);
4697 STATIC_ASSERT(0 == kSmiTag);
4698 __ Addu(a1, a1, Operand(a1)); // Convert to smi.
4699 4692
4700 // Store result register while executing finally block. 4693 // Store result register while executing finally block.
4701 __ push(a1); 4694 __ push(a1);
4702 4695
4703 // Store pending message while executing finally block. 4696 // Store pending message while executing finally block.
4704 ExternalReference pending_message_obj = 4697 ExternalReference pending_message_obj =
4705 ExternalReference::address_of_pending_message_obj(isolate()); 4698 ExternalReference::address_of_pending_message_obj(isolate());
4706 __ li(at, Operand(pending_message_obj)); 4699 __ li(at, Operand(pending_message_obj));
4707 __ lw(a1, MemOperand(at)); 4700 __ ld(a1, MemOperand(at));
4708 __ push(a1); 4701 __ push(a1);
4709 4702
4710 ExternalReference has_pending_message = 4703 ExternalReference has_pending_message =
4711 ExternalReference::address_of_has_pending_message(isolate()); 4704 ExternalReference::address_of_has_pending_message(isolate());
4712 __ li(at, Operand(has_pending_message)); 4705 __ li(at, Operand(has_pending_message));
4713 __ lw(a1, MemOperand(at)); 4706 __ ld(a1, MemOperand(at));
4714 __ SmiTag(a1); 4707 __ SmiTag(a1);
4715 __ push(a1); 4708 __ push(a1);
4716 4709
4717 ExternalReference pending_message_script = 4710 ExternalReference pending_message_script =
4718 ExternalReference::address_of_pending_message_script(isolate()); 4711 ExternalReference::address_of_pending_message_script(isolate());
4719 __ li(at, Operand(pending_message_script)); 4712 __ li(at, Operand(pending_message_script));
4720 __ lw(a1, MemOperand(at)); 4713 __ ld(a1, MemOperand(at));
4721 __ push(a1); 4714 __ push(a1);
4722 } 4715 }
4723 4716
4724 4717
4725 void FullCodeGenerator::ExitFinallyBlock() { 4718 void FullCodeGenerator::ExitFinallyBlock() {
4726 ASSERT(!result_register().is(a1)); 4719 ASSERT(!result_register().is(a1));
4727 // Restore pending message from stack. 4720 // Restore pending message from stack.
4728 __ pop(a1); 4721 __ pop(a1);
4729 ExternalReference pending_message_script = 4722 ExternalReference pending_message_script =
4730 ExternalReference::address_of_pending_message_script(isolate()); 4723 ExternalReference::address_of_pending_message_script(isolate());
4731 __ li(at, Operand(pending_message_script)); 4724 __ li(at, Operand(pending_message_script));
4732 __ sw(a1, MemOperand(at)); 4725 __ sd(a1, MemOperand(at));
4733 4726
4734 __ pop(a1); 4727 __ pop(a1);
4735 __ SmiUntag(a1); 4728 __ SmiUntag(a1);
4736 ExternalReference has_pending_message = 4729 ExternalReference has_pending_message =
4737 ExternalReference::address_of_has_pending_message(isolate()); 4730 ExternalReference::address_of_has_pending_message(isolate());
4738 __ li(at, Operand(has_pending_message)); 4731 __ li(at, Operand(has_pending_message));
4739 __ sw(a1, MemOperand(at)); 4732 __ sd(a1, MemOperand(at));
4740 4733
4741 __ pop(a1); 4734 __ pop(a1);
4742 ExternalReference pending_message_obj = 4735 ExternalReference pending_message_obj =
4743 ExternalReference::address_of_pending_message_obj(isolate()); 4736 ExternalReference::address_of_pending_message_obj(isolate());
4744 __ li(at, Operand(pending_message_obj)); 4737 __ li(at, Operand(pending_message_obj));
4745 __ sw(a1, MemOperand(at)); 4738 __ sd(a1, MemOperand(at));
4746 4739
4747 // Restore result register from stack. 4740 // Restore result register from stack.
4748 __ pop(a1); 4741 __ pop(a1);
4749 4742
4750 // Uncook return address and return. 4743 // Uncook return address and return.
4751 __ pop(result_register()); 4744 __ pop(result_register());
4752 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); 4745
4753 __ sra(a1, a1, 1); // Un-smi-tag value. 4746 __ SmiUntag(a1);
4754 __ Addu(at, a1, Operand(masm_->CodeObject())); 4747 __ Daddu(at, a1, Operand(masm_->CodeObject()));
4755 __ Jump(at); 4748 __ Jump(at);
4756 } 4749 }
4757 4750
4758 4751
4759 #undef __ 4752 #undef __
4760 4753
4761 #define __ ACCESS_MASM(masm()) 4754 #define __ ACCESS_MASM(masm())
4762 4755
4763 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit( 4756 FullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit(
4764 int* stack_depth, 4757 int* stack_depth,
4765 int* context_length) { 4758 int* context_length) {
4766 // The macros used here must preserve the result register. 4759 // The macros used here must preserve the result register.
4767 4760
4768 // Because the handler block contains the context of the finally 4761 // Because the handler block contains the context of the finally
4769 // code, we can restore it directly from there for the finally code 4762 // code, we can restore it directly from there for the finally code
4770 // rather than iteratively unwinding contexts via their previous 4763 // rather than iteratively unwinding contexts via their previous
4771 // links. 4764 // links.
4772 __ Drop(*stack_depth); // Down to the handler block. 4765 __ Drop(*stack_depth); // Down to the handler block.
4773 if (*context_length > 0) { 4766 if (*context_length > 0) {
4774 // Restore the context to its dedicated register and the stack. 4767 // Restore the context to its dedicated register and the stack.
4775 __ lw(cp, MemOperand(sp, StackHandlerConstants::kContextOffset)); 4768 __ ld(cp, MemOperand(sp, StackHandlerConstants::kContextOffset));
4776 __ sw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 4769 __ sd(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
4777 } 4770 }
4778 __ PopTryHandler(); 4771 __ PopTryHandler();
4779 __ Call(finally_entry_); 4772 __ Call(finally_entry_);
4780 4773
4781 *stack_depth = 0; 4774 *stack_depth = 0;
4782 *context_length = 0; 4775 *context_length = 0;
4783 return previous_; 4776 return previous_;
4784 } 4777 }
4785 4778
4786 4779
4787 #undef __ 4780 #undef __
4788 4781
4789 4782
4790 void BackEdgeTable::PatchAt(Code* unoptimized_code, 4783 void BackEdgeTable::PatchAt(Code* unoptimized_code,
4791 Address pc, 4784 Address pc,
4792 BackEdgeState target_state, 4785 BackEdgeState target_state,
4793 Code* replacement_code) { 4786 Code* replacement_code) {
4794 static const int kInstrSize = Assembler::kInstrSize; 4787 static const int kInstrSize = Assembler::kInstrSize;
4795 Address branch_address = pc - 6 * kInstrSize; 4788 Address branch_address = pc - 8 * kInstrSize;
4796 CodePatcher patcher(branch_address, 1); 4789 CodePatcher patcher(branch_address, 1);
4797 4790
4798 switch (target_state) { 4791 switch (target_state) {
4799 case INTERRUPT: 4792 case INTERRUPT:
4800 // slt at, a3, zero_reg (in case of count based interrupts) 4793 // slt at, a3, zero_reg (in case of count based interrupts)
4801 // beq at, zero_reg, ok 4794 // beq at, zero_reg, ok
4802 // lui t9, <interrupt stub address> upper 4795 // lui t9, <interrupt stub address> upper
4803 // ori t9, <interrupt stub address> lower 4796 // ori t9, <interrupt stub address> u-middle
4797 // dsll t9, t9, 16
4798 // ori t9, <interrupt stub address> lower
4804 // jalr t9 4799 // jalr t9
4805 // nop 4800 // nop
4806 // ok-label ----- pc_after points here 4801 // ok-label ----- pc_after points here
4807 patcher.masm()->slt(at, a3, zero_reg); 4802 patcher.masm()->slt(at, a3, zero_reg);
4808 break; 4803 break;
4809 case ON_STACK_REPLACEMENT: 4804 case ON_STACK_REPLACEMENT:
4810 case OSR_AFTER_STACK_CHECK: 4805 case OSR_AFTER_STACK_CHECK:
4811 // addiu at, zero_reg, 1 4806 // addiu at, zero_reg, 1
4812 // beq at, zero_reg, ok ;; Not changed 4807 // beq at, zero_reg, ok ;; Not changed
4813 // lui t9, <on-stack replacement address> upper 4808 // lui t9, <on-stack replacement address> upper
4814 // ori t9, <on-stack replacement address> lower 4809 // ori t9, <on-stack replacement address> middle
4810 // dsll t9, t9, 16
4811 // ori t9, <on-stack replacement address> lower
4815 // jalr t9 ;; Not changed 4812 // jalr t9 ;; Not changed
4816 // nop ;; Not changed 4813 // nop ;; Not changed
4817 // ok-label ----- pc_after points here 4814 // ok-label ----- pc_after points here
4818 patcher.masm()->addiu(at, zero_reg, 1); 4815 patcher.masm()->daddiu(at, zero_reg, 1);
4819 break; 4816 break;
4820 } 4817 }
4821 Address pc_immediate_load_address = pc - 4 * kInstrSize; 4818 Address pc_immediate_load_address = pc - 6 * kInstrSize;
4822 // Replace the stack check address in the load-immediate (lui/ori pair) 4819 // Replace the stack check address in the load-immediate (6-instr sequence)
4823 // with the entry address of the replacement code. 4820 // with the entry address of the replacement code.
4824 Assembler::set_target_address_at(pc_immediate_load_address, 4821 Assembler::set_target_address_at(pc_immediate_load_address,
4825 replacement_code->entry()); 4822 replacement_code->entry());
4826 4823
4827 unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch( 4824 unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
4828 unoptimized_code, pc_immediate_load_address, replacement_code); 4825 unoptimized_code, pc_immediate_load_address, replacement_code);
4829 } 4826 }
4830 4827
4831 4828
4832 BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState( 4829 BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState(
4833 Isolate* isolate, 4830 Isolate* isolate,
4834 Code* unoptimized_code, 4831 Code* unoptimized_code,
4835 Address pc) { 4832 Address pc) {
4836 static const int kInstrSize = Assembler::kInstrSize; 4833 static const int kInstrSize = Assembler::kInstrSize;
4837 Address branch_address = pc - 6 * kInstrSize; 4834 Address branch_address = pc - 8 * kInstrSize;
4838 Address pc_immediate_load_address = pc - 4 * kInstrSize; 4835 Address pc_immediate_load_address = pc - 6 * kInstrSize;
4839 4836
4840 ASSERT(Assembler::IsBeq(Assembler::instr_at(pc - 5 * kInstrSize))); 4837 ASSERT(Assembler::IsBeq(Assembler::instr_at(pc - 7 * kInstrSize)));
4841 if (!Assembler::IsAddImmediate(Assembler::instr_at(branch_address))) { 4838 if (!Assembler::IsAddImmediate(Assembler::instr_at(branch_address))) {
4842 ASSERT(reinterpret_cast<uint32_t>( 4839 ASSERT(reinterpret_cast<uint64_t>(
4843 Assembler::target_address_at(pc_immediate_load_address)) == 4840 Assembler::target_address_at(pc_immediate_load_address)) ==
4844 reinterpret_cast<uint32_t>( 4841 reinterpret_cast<uint64_t>(
4845 isolate->builtins()->InterruptCheck()->entry())); 4842 isolate->builtins()->InterruptCheck()->entry()));
4846 return INTERRUPT; 4843 return INTERRUPT;
4847 } 4844 }
4848 4845
4849 ASSERT(Assembler::IsAddImmediate(Assembler::instr_at(branch_address))); 4846 ASSERT(Assembler::IsAddImmediate(Assembler::instr_at(branch_address)));
4850 4847
4851 if (reinterpret_cast<uint32_t>( 4848 if (reinterpret_cast<uint64_t>(
4852 Assembler::target_address_at(pc_immediate_load_address)) == 4849 Assembler::target_address_at(pc_immediate_load_address)) ==
4853 reinterpret_cast<uint32_t>( 4850 reinterpret_cast<uint64_t>(
4854 isolate->builtins()->OnStackReplacement()->entry())) { 4851 isolate->builtins()->OnStackReplacement()->entry())) {
4855 return ON_STACK_REPLACEMENT; 4852 return ON_STACK_REPLACEMENT;
4856 } 4853 }
4857 4854
4858 ASSERT(reinterpret_cast<uint32_t>( 4855 ASSERT(reinterpret_cast<uint64_t>(
4859 Assembler::target_address_at(pc_immediate_load_address)) == 4856 Assembler::target_address_at(pc_immediate_load_address)) ==
4860 reinterpret_cast<uint32_t>( 4857 reinterpret_cast<uint64_t>(
4861 isolate->builtins()->OsrAfterStackCheck()->entry())); 4858 isolate->builtins()->OsrAfterStackCheck()->entry()));
4862 return OSR_AFTER_STACK_CHECK; 4859 return OSR_AFTER_STACK_CHECK;
4863 } 4860 }
4864 4861
4865 4862
4866 } } // namespace v8::internal 4863 } } // namespace v8::internal
4867 4864
4868 #endif // V8_TARGET_ARCH_MIPS 4865 #endif // V8_TARGET_ARCH_MIPS64
OLDNEW
« no previous file with comments | « src/mips64/frames-mips64.cc ('k') | src/mips64/ic-mips64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698