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

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

Issue 555073: Merge r3610, r3611, r3612, r3630, r3636, r3640, and r3664... (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: Created 10 years, 11 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 | « no previous file | src/ast.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 // mode 1 instruction where there are restrictions on which immediate values 207 // mode 1 instruction where there are restrictions on which immediate values
208 // can be encoded in the instruction and which immediate values requires 208 // can be encoded in the instruction and which immediate values requires
209 // use of an additional instruction for moving the immediate to a temporary 209 // use of an additional instruction for moving the immediate to a temporary
210 // register. 210 // register.
211 ASSERT_EQ(return_sequence_length, 211 ASSERT_EQ(return_sequence_length,
212 masm_->InstructionsGeneratedSince(&check_exit_codesize)); 212 masm_->InstructionsGeneratedSince(&check_exit_codesize));
213 } 213 }
214 } 214 }
215 215
216 216
217 void FastCodeGenerator::Apply(Expression::Context context, 217 void FastCodeGenerator::Apply(Expression::Context context, Register reg) {
218 Slot* slot, 218 switch (context) {
219 Register scratch) { 219 case Expression::kUninitialized:
220 UNREACHABLE();
221
222 case Expression::kEffect:
223 // Nothing to do.
224 break;
225
226 case Expression::kValue:
227 // Move value into place.
228 switch (location_) {
229 case kAccumulator:
230 if (!reg.is(result_register())) __ mov(result_register(), reg);
231 break;
232 case kStack:
233 __ push(reg);
234 break;
235 }
236 break;
237
238 case Expression::kValueTest:
239 case Expression::kTestValue:
240 // Push an extra copy of the value in case it's needed.
241 __ push(reg);
242 // Fall through.
243
244 case Expression::kTest:
245 // We always call the runtime on ARM, so push the value as argument.
246 __ push(reg);
247 DoTest(context);
248 break;
249 }
250 }
251
252
253 void FastCodeGenerator::Apply(Expression::Context context, Slot* slot) {
220 switch (context) { 254 switch (context) {
221 case Expression::kUninitialized: 255 case Expression::kUninitialized:
222 UNREACHABLE(); 256 UNREACHABLE();
223 case Expression::kEffect: 257 case Expression::kEffect:
258 // Nothing to do.
224 break; 259 break;
225 case Expression::kValue: 260 case Expression::kValue:
226 case Expression::kTest: 261 case Expression::kTest:
227 case Expression::kValueTest: 262 case Expression::kValueTest:
228 case Expression::kTestValue: 263 case Expression::kTestValue:
229 Move(scratch, slot); 264 // On ARM we have to move the value into a register to do anything
230 Apply(context, scratch); 265 // with it.
266 Move(result_register(), slot);
267 Apply(context, result_register());
231 break; 268 break;
232 } 269 }
233 } 270 }
234 271
235 272
236 void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) { 273 void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) {
237 switch (context) { 274 switch (context) {
238 case Expression::kUninitialized: 275 case Expression::kUninitialized:
239 UNREACHABLE(); 276 UNREACHABLE();
240 case Expression::kEffect: 277 case Expression::kEffect:
241 break; 278 break;
279 // Nothing to do.
242 case Expression::kValue: 280 case Expression::kValue:
243 case Expression::kTest: 281 case Expression::kTest:
244 case Expression::kValueTest: 282 case Expression::kValueTest:
245 case Expression::kTestValue: 283 case Expression::kTestValue:
246 __ mov(ip, Operand(lit->handle())); 284 // On ARM we have to move the value into a register to do anything
247 Apply(context, ip); 285 // with it.
286 __ mov(result_register(), Operand(lit->handle()));
287 Apply(context, result_register());
248 break; 288 break;
249 } 289 }
250 } 290 }
251 291
252 292
253 void FastCodeGenerator::ApplyTOS(Expression::Context context) { 293 void FastCodeGenerator::ApplyTOS(Expression::Context context) {
254 switch (context) { 294 switch (context) {
255 case Expression::kUninitialized: 295 case Expression::kUninitialized:
256 UNREACHABLE(); 296 UNREACHABLE();
297
257 case Expression::kEffect: 298 case Expression::kEffect:
258 __ Drop(1); 299 __ Drop(1);
259 break; 300 break;
301
260 case Expression::kValue: 302 case Expression::kValue:
303 switch (location_) {
304 case kAccumulator:
305 __ pop(result_register());
306 break;
307 case kStack:
308 break;
309 }
261 break; 310 break;
311
312 case Expression::kValueTest:
313 case Expression::kTestValue:
314 // Duplicate the value on the stack in case it's needed.
315 __ ldr(ip, MemOperand(sp));
316 __ push(ip);
317 // Fall through.
318
262 case Expression::kTest: 319 case Expression::kTest:
263 __ pop(r0); 320 DoTest(context);
264 TestAndBranch(r0, true_label_, false_label_);
265 break; 321 break;
266 case Expression::kValueTest: {
267 Label discard;
268 __ ldr(r0, MemOperand(sp, 0));
269 TestAndBranch(r0, true_label_, &discard);
270 __ bind(&discard);
271 __ Drop(1);
272 __ jmp(false_label_);
273 break;
274 }
275 case Expression::kTestValue: {
276 Label discard;
277 __ ldr(r0, MemOperand(sp, 0));
278 TestAndBranch(r0, &discard, false_label_);
279 __ bind(&discard);
280 __ Drop(1);
281 __ jmp(true_label_);
282 }
283 } 322 }
284 } 323 }
285 324
286 325
287 void FastCodeGenerator::DropAndApply(int count, 326 void FastCodeGenerator::DropAndApply(int count,
288 Expression::Context context, 327 Expression::Context context,
289 Register reg) { 328 Register reg) {
290 ASSERT(count > 0); 329 ASSERT(count > 0);
291 ASSERT(!reg.is(sp)); 330 ASSERT(!reg.is(sp));
292 switch (context) { 331 switch (context) {
293 case Expression::kUninitialized: 332 case Expression::kUninitialized:
294 UNREACHABLE(); 333 UNREACHABLE();
334
295 case Expression::kEffect: 335 case Expression::kEffect:
296 __ Drop(count); 336 __ Drop(count);
297 break; 337 break;
338
298 case Expression::kValue: 339 case Expression::kValue:
340 switch (location_) {
341 case kAccumulator:
342 __ Drop(count);
343 if (!reg.is(result_register())) __ mov(result_register(), reg);
344 break;
345 case kStack:
346 if (count > 1) __ Drop(count - 1);
347 __ str(reg, MemOperand(sp));
348 break;
349 }
350 break;
351
352 case Expression::kTest:
299 if (count > 1) __ Drop(count - 1); 353 if (count > 1) __ Drop(count - 1);
300 __ str(reg, MemOperand(sp)); 354 __ str(reg, MemOperand(sp));
355 DoTest(context);
301 break; 356 break;
357
358 case Expression::kValueTest:
359 case Expression::kTestValue:
360 if (count == 1) {
361 __ str(reg, MemOperand(sp));
362 __ push(reg);
363 } else { // count > 1
364 __ Drop(count - 2);
365 __ str(reg, MemOperand(sp, kPointerSize));
366 __ str(reg, MemOperand(sp));
367 }
368 DoTest(context);
369 break;
370 }
371 }
372
373
374 void FastCodeGenerator::Apply(Expression::Context context,
375 Label* materialize_true,
376 Label* materialize_false) {
377 switch (context) {
378 case Expression::kUninitialized:
379
380 case Expression::kEffect:
381 ASSERT_EQ(materialize_true, materialize_false);
382 __ bind(materialize_true);
383 break;
384
385 case Expression::kValue: {
386 Label done;
387 __ bind(materialize_true);
388 __ mov(result_register(), Operand(Factory::true_value()));
389 __ jmp(&done);
390 __ bind(materialize_false);
391 __ mov(result_register(), Operand(Factory::false_value()));
392 __ bind(&done);
393 switch (location_) {
394 case kAccumulator:
395 break;
396 case kStack:
397 __ push(result_register());
398 break;
399 }
400 break;
401 }
402
302 case Expression::kTest: 403 case Expression::kTest:
303 __ Drop(count);
304 TestAndBranch(reg, true_label_, false_label_);
305 break; 404 break;
405
406 case Expression::kValueTest:
407 __ bind(materialize_true);
408 __ mov(result_register(), Operand(Factory::true_value()));
409 switch (location_) {
410 case kAccumulator:
411 break;
412 case kStack:
413 __ push(result_register());
414 break;
415 }
416 __ jmp(true_label_);
417 break;
418
419 case Expression::kTestValue:
420 __ bind(materialize_false);
421 __ mov(result_register(), Operand(Factory::false_value()));
422 switch (location_) {
423 case kAccumulator:
424 break;
425 case kStack:
426 __ push(result_register());
427 break;
428 }
429 __ jmp(false_label_);
430 break;
431 }
432 }
433
434
435 void FastCodeGenerator::DoTest(Expression::Context context) {
436 // The value to test is pushed on the stack, and duplicated on the stack
437 // if necessary (for value/test and test/value contexts).
438 ASSERT_NE(NULL, true_label_);
439 ASSERT_NE(NULL, false_label_);
440
441 // Call the runtime to find the boolean value of the source and then
442 // translate it into control flow to the pair of labels.
443 __ CallRuntime(Runtime::kToBool, 1);
444 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
445 __ cmp(r0, ip);
446
447 // Complete based on the context.
448 switch (context) {
449 case Expression::kUninitialized:
450 case Expression::kEffect:
451 case Expression::kValue:
452 UNREACHABLE();
453
454 case Expression::kTest:
455 __ b(eq, true_label_);
456 __ jmp(false_label_);
457 break;
458
306 case Expression::kValueTest: { 459 case Expression::kValueTest: {
307 Label discard; 460 Label discard;
308 if (count > 1) __ Drop(count - 1); 461 switch (location_) {
309 __ str(reg, MemOperand(sp)); 462 case kAccumulator:
310 TestAndBranch(reg, true_label_, &discard); 463 __ b(ne, &discard);
464 __ pop(result_register());
465 __ jmp(true_label_);
466 break;
467 case kStack:
468 __ b(eq, true_label_);
469 break;
470 }
311 __ bind(&discard); 471 __ bind(&discard);
312 __ Drop(1); 472 __ Drop(1);
313 __ jmp(false_label_); 473 __ jmp(false_label_);
314 break; 474 break;
315 } 475 }
476
316 case Expression::kTestValue: { 477 case Expression::kTestValue: {
317 Label discard; 478 Label discard;
318 if (count > 1) __ Drop(count - 1); 479 switch (location_) {
319 __ str(reg, MemOperand(sp)); 480 case kAccumulator:
320 TestAndBranch(reg, &discard, false_label_); 481 __ b(eq, &discard);
482 __ pop(result_register());
483 __ jmp(false_label_);
484 break;
485 case kStack:
486 __ b(ne, false_label_);
487 break;
488 }
321 __ bind(&discard); 489 __ bind(&discard);
322 __ Drop(1); 490 __ Drop(1);
323 __ jmp(true_label_); 491 __ jmp(true_label_);
324 break; 492 break;
325 } 493 }
326 } 494 }
327 } 495 }
328 496
329 497
330 MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { 498 MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
(...skipping 10 matching lines...) Expand all
341 case Slot::LOOKUP: 509 case Slot::LOOKUP:
342 UNREACHABLE(); 510 UNREACHABLE();
343 } 511 }
344 UNREACHABLE(); 512 UNREACHABLE();
345 return MemOperand(r0, 0); 513 return MemOperand(r0, 0);
346 } 514 }
347 515
348 516
349 void FastCodeGenerator::Move(Register destination, Slot* source) { 517 void FastCodeGenerator::Move(Register destination, Slot* source) {
350 // Use destination as scratch. 518 // Use destination as scratch.
351 MemOperand location = EmitSlotSearch(source, destination); 519 MemOperand slot_operand = EmitSlotSearch(source, destination);
352 __ ldr(destination, location); 520 __ ldr(destination, slot_operand);
353 } 521 }
354 522
355 523
356
357 void FastCodeGenerator::Move(Slot* dst, 524 void FastCodeGenerator::Move(Slot* dst,
358 Register src, 525 Register src,
359 Register scratch1, 526 Register scratch1,
360 Register scratch2) { 527 Register scratch2) {
361 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. 528 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented.
362 ASSERT(!scratch1.is(src) && !scratch2.is(src)); 529 ASSERT(!scratch1.is(src) && !scratch2.is(src));
363 MemOperand location = EmitSlotSearch(dst, scratch1); 530 MemOperand location = EmitSlotSearch(dst, scratch1);
364 __ str(src, location); 531 __ str(src, location);
365 // Emit the write barrier code if the location is in the heap. 532 // Emit the write barrier code if the location is in the heap.
366 if (dst->type() == Slot::CONTEXT) { 533 if (dst->type() == Slot::CONTEXT) {
367 __ mov(scratch2, Operand(Context::SlotOffset(dst->index()))); 534 __ mov(scratch2, Operand(Context::SlotOffset(dst->index())));
368 __ RecordWrite(scratch1, scratch2, src); 535 __ RecordWrite(scratch1, scratch2, src);
369 } 536 }
370 } 537 }
371 538
372 539
373
374 void FastCodeGenerator::TestAndBranch(Register source,
375 Label* true_label,
376 Label* false_label) {
377 ASSERT_NE(NULL, true_label);
378 ASSERT_NE(NULL, false_label);
379 // Call the runtime to find the boolean value of the source and then
380 // translate it into control flow to the pair of labels.
381 __ push(source);
382 __ CallRuntime(Runtime::kToBool, 1);
383 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
384 __ cmp(r0, ip);
385 __ b(eq, true_label);
386 __ jmp(false_label);
387 }
388
389
390 void FastCodeGenerator::VisitDeclaration(Declaration* decl) { 540 void FastCodeGenerator::VisitDeclaration(Declaration* decl) {
391 Comment cmnt(masm_, "[ Declaration"); 541 Comment cmnt(masm_, "[ Declaration");
392 Variable* var = decl->proxy()->var(); 542 Variable* var = decl->proxy()->var();
393 ASSERT(var != NULL); // Must have been resolved. 543 ASSERT(var != NULL); // Must have been resolved.
394 Slot* slot = var->slot(); 544 Slot* slot = var->slot();
395 Property* prop = var->AsProperty(); 545 Property* prop = var->AsProperty();
396 546
397 if (slot != NULL) { 547 if (slot != NULL) {
398 switch (slot->type()) { 548 switch (slot->type()) {
399 case Slot::PARAMETER: 549 case Slot::PARAMETER:
400 case Slot::LOCAL: 550 case Slot::LOCAL:
401 if (decl->mode() == Variable::CONST) { 551 if (decl->mode() == Variable::CONST) {
402 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 552 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
403 __ str(ip, MemOperand(fp, SlotOffset(slot))); 553 __ str(ip, MemOperand(fp, SlotOffset(slot)));
404 } else if (decl->fun() != NULL) { 554 } else if (decl->fun() != NULL) {
405 Visit(decl->fun()); 555 VisitForValue(decl->fun(), kAccumulator);
406 __ pop(ip); 556 __ str(result_register(), MemOperand(fp, SlotOffset(slot)));
407 __ str(ip, MemOperand(fp, SlotOffset(slot)));
408 } 557 }
409 break; 558 break;
410 559
411 case Slot::CONTEXT: 560 case Slot::CONTEXT:
412 // We bypass the general EmitSlotSearch because we know more about 561 // We bypass the general EmitSlotSearch because we know more about
413 // this specific context. 562 // this specific context.
414 563
415 // The variable in the decl always resides in the current context. 564 // The variable in the decl always resides in the current context.
416 ASSERT_EQ(0, function_->scope()->ContextChainLength(var->scope())); 565 ASSERT_EQ(0, function_->scope()->ContextChainLength(var->scope()));
417 if (FLAG_debug_code) { 566 if (FLAG_debug_code) {
418 // Check if we have the correct context pointer. 567 // Check if we have the correct context pointer.
419 __ ldr(r1, 568 __ ldr(r1,
420 CodeGenerator::ContextOperand(cp, Context::FCONTEXT_INDEX)); 569 CodeGenerator::ContextOperand(cp, Context::FCONTEXT_INDEX));
421 __ cmp(r1, cp); 570 __ cmp(r1, cp);
422 __ Check(eq, "Unexpected declaration in current context."); 571 __ Check(eq, "Unexpected declaration in current context.");
423 } 572 }
424 if (decl->mode() == Variable::CONST) { 573 if (decl->mode() == Variable::CONST) {
425 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 574 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
426 __ str(ip, CodeGenerator::ContextOperand(cp, slot->index())); 575 __ str(ip, CodeGenerator::ContextOperand(cp, slot->index()));
427 // No write barrier since the_hole_value is in old space. 576 // No write barrier since the_hole_value is in old space.
428 } else if (decl->fun() != NULL) { 577 } else if (decl->fun() != NULL) {
429 Visit(decl->fun()); 578 VisitForValue(decl->fun(), kAccumulator);
430 __ pop(r0); 579 __ str(result_register(),
431 __ str(r0, CodeGenerator::ContextOperand(cp, slot->index())); 580 CodeGenerator::ContextOperand(cp, slot->index()));
432 int offset = Context::SlotOffset(slot->index()); 581 int offset = Context::SlotOffset(slot->index());
433 __ mov(r2, Operand(offset)); 582 __ mov(r2, Operand(offset));
434 // We know that we have written a function, which is not a smi. 583 // We know that we have written a function, which is not a smi.
435 __ RecordWrite(cp, r2, r0); 584 __ RecordWrite(cp, r2, result_register());
436 } 585 }
437 break; 586 break;
438 587
439 case Slot::LOOKUP: { 588 case Slot::LOOKUP: {
440 __ mov(r2, Operand(var->name())); 589 __ mov(r2, Operand(var->name()));
441 // Declaration nodes are always introduced in one of two modes. 590 // Declaration nodes are always introduced in one of two modes.
442 ASSERT(decl->mode() == Variable::VAR || 591 ASSERT(decl->mode() == Variable::VAR ||
443 decl->mode() == Variable::CONST); 592 decl->mode() == Variable::CONST);
444 PropertyAttributes attr = 593 PropertyAttributes attr =
445 (decl->mode() == Variable::VAR) ? NONE : READ_ONLY; 594 (decl->mode() == Variable::VAR) ? NONE : READ_ONLY;
446 __ mov(r1, Operand(Smi::FromInt(attr))); 595 __ mov(r1, Operand(Smi::FromInt(attr)));
447 // Push initial value, if any. 596 // Push initial value, if any.
448 // Note: For variables we must not push an initial value (such as 597 // Note: For variables we must not push an initial value (such as
449 // 'undefined') because we may have a (legal) redeclaration and we 598 // 'undefined') because we may have a (legal) redeclaration and we
450 // must not destroy the current value. 599 // must not destroy the current value.
451 if (decl->mode() == Variable::CONST) { 600 if (decl->mode() == Variable::CONST) {
452 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); 601 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex);
453 __ stm(db_w, sp, cp.bit() | r2.bit() | r1.bit() | r0.bit()); 602 __ stm(db_w, sp, cp.bit() | r2.bit() | r1.bit() | r0.bit());
454 } else if (decl->fun() != NULL) { 603 } else if (decl->fun() != NULL) {
455 __ stm(db_w, sp, cp.bit() | r2.bit() | r1.bit()); 604 __ stm(db_w, sp, cp.bit() | r2.bit() | r1.bit());
456 Visit(decl->fun()); // Initial value for function decl. 605 // Push initial value for function declaration.
606 VisitForValue(decl->fun(), kStack);
457 } else { 607 } else {
458 __ mov(r0, Operand(Smi::FromInt(0))); // No initial value! 608 __ mov(r0, Operand(Smi::FromInt(0))); // No initial value!
459 __ stm(db_w, sp, cp.bit() | r2.bit() | r1.bit() | r0.bit()); 609 __ stm(db_w, sp, cp.bit() | r2.bit() | r1.bit() | r0.bit());
460 } 610 }
461 __ CallRuntime(Runtime::kDeclareContextSlot, 4); 611 __ CallRuntime(Runtime::kDeclareContextSlot, 4);
462 break; 612 break;
463 } 613 }
464 } 614 }
465 615
466 } else if (prop != NULL) { 616 } else if (prop != NULL) {
467 if (decl->fun() != NULL || decl->mode() == Variable::CONST) { 617 if (decl->fun() != NULL || decl->mode() == Variable::CONST) {
468 // We are declaring a function or constant that rewrites to a 618 // We are declaring a function or constant that rewrites to a
469 // property. Use (keyed) IC to set the initial value. 619 // property. Use (keyed) IC to set the initial value.
470 ASSERT_EQ(Expression::kValue, prop->obj()->context()); 620 VisitForValue(prop->obj(), kStack);
471 Visit(prop->obj()); 621 VisitForValue(prop->key(), kStack);
472 ASSERT_EQ(Expression::kValue, prop->key()->context());
473 Visit(prop->key());
474 622
475 if (decl->fun() != NULL) { 623 if (decl->fun() != NULL) {
476 ASSERT_EQ(Expression::kValue, decl->fun()->context()); 624 VisitForValue(decl->fun(), kAccumulator);
477 Visit(decl->fun());
478 __ pop(r0);
479 } else { 625 } else {
480 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); 626 __ LoadRoot(result_register(), Heap::kTheHoleValueRootIndex);
481 } 627 }
482 628
483 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 629 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
484 __ Call(ic, RelocInfo::CODE_TARGET); 630 __ Call(ic, RelocInfo::CODE_TARGET);
485 631
486 // Value in r0 is ignored (declarations are statements). Receiver 632 // Value in r0 is ignored (declarations are statements). Receiver
487 // and key on stack are discarded. 633 // and key on stack are discarded.
488 __ Drop(2); 634 __ Drop(2);
489 } 635 }
490 } 636 }
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
551 } 697 }
552 case Slot::CONTEXT: { 698 case Slot::CONTEXT: {
553 Comment cmnt(masm_, "Context slot"); 699 Comment cmnt(masm_, "Context slot");
554 break; 700 break;
555 } 701 }
556 case Slot::LOOKUP: 702 case Slot::LOOKUP:
557 UNIMPLEMENTED(); 703 UNIMPLEMENTED();
558 break; 704 break;
559 } 705 }
560 } 706 }
561 Apply(context, slot, r0); 707 Apply(context, slot);
562 } else { 708 } else {
563 Comment cmnt(masm_, "Variable rewritten to property"); 709 Comment cmnt(masm_, "Variable rewritten to property");
564 // A variable has been rewritten into an explicit access to an object 710 // A variable has been rewritten into an explicit access to an object
565 // property. 711 // property.
566 Property* property = rewrite->AsProperty(); 712 Property* property = rewrite->AsProperty();
567 ASSERT_NOT_NULL(property); 713 ASSERT_NOT_NULL(property);
568 714
569 // The only property expressions that can occur are of the form 715 // The only property expressions that can occur are of the form
570 // "slot[literal]". 716 // "slot[literal]".
571 717
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
632 __ ldr(r2, FieldMemOperand(r2, JSFunction::kLiteralsOffset)); 778 __ ldr(r2, FieldMemOperand(r2, JSFunction::kLiteralsOffset));
633 __ mov(r1, Operand(Smi::FromInt(expr->literal_index()))); 779 __ mov(r1, Operand(Smi::FromInt(expr->literal_index())));
634 __ mov(r0, Operand(expr->constant_properties())); 780 __ mov(r0, Operand(expr->constant_properties()));
635 __ stm(db_w, sp, r2.bit() | r1.bit() | r0.bit()); 781 __ stm(db_w, sp, r2.bit() | r1.bit() | r0.bit());
636 if (expr->depth() > 1) { 782 if (expr->depth() > 1) {
637 __ CallRuntime(Runtime::kCreateObjectLiteral, 3); 783 __ CallRuntime(Runtime::kCreateObjectLiteral, 3);
638 } else { 784 } else {
639 __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 3); 785 __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 3);
640 } 786 }
641 787
642 // If result_saved == true: The result is saved on top of the 788 // If result_saved is true the result is on top of the stack. If
643 // stack and in r0. 789 // result_saved is false the result is in r0.
644 // If result_saved == false: The result not on the stack, just in r0.
645 bool result_saved = false; 790 bool result_saved = false;
646 791
647 for (int i = 0; i < expr->properties()->length(); i++) { 792 for (int i = 0; i < expr->properties()->length(); i++) {
648 ObjectLiteral::Property* property = expr->properties()->at(i); 793 ObjectLiteral::Property* property = expr->properties()->at(i);
649 if (property->IsCompileTimeValue()) continue; 794 if (property->IsCompileTimeValue()) continue;
650 795
651 Literal* key = property->key(); 796 Literal* key = property->key();
652 Expression* value = property->value(); 797 Expression* value = property->value();
653 if (!result_saved) { 798 if (!result_saved) {
654 __ push(r0); // Save result on stack 799 __ push(r0); // Save result on stack
655 result_saved = true; 800 result_saved = true;
656 } 801 }
657 switch (property->kind()) { 802 switch (property->kind()) {
658 case ObjectLiteral::Property::CONSTANT: 803 case ObjectLiteral::Property::CONSTANT:
659 UNREACHABLE(); 804 UNREACHABLE();
660 805 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
661 case ObjectLiteral::Property::MATERIALIZED_LITERAL: // Fall through.
662 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); 806 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value()));
807 // Fall through.
663 case ObjectLiteral::Property::COMPUTED: 808 case ObjectLiteral::Property::COMPUTED:
664 if (key->handle()->IsSymbol()) { 809 if (key->handle()->IsSymbol()) {
665 Visit(value); 810 VisitForValue(value, kAccumulator);
666 ASSERT_EQ(Expression::kValue, value->context());
667 __ pop(r0);
668 __ mov(r2, Operand(key->handle())); 811 __ mov(r2, Operand(key->handle()));
669 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 812 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
670 __ Call(ic, RelocInfo::CODE_TARGET); 813 __ Call(ic, RelocInfo::CODE_TARGET);
671 // StoreIC leaves the receiver on the stack. 814 // StoreIC leaves the receiver on the stack.
672 __ ldr(r0, MemOperand(sp)); // Restore result into r0.
673 break; 815 break;
674 } 816 }
675 // Fall through. 817 // Fall through.
676
677 case ObjectLiteral::Property::PROTOTYPE: 818 case ObjectLiteral::Property::PROTOTYPE:
819 // Duplicate receiver on stack.
820 __ ldr(r0, MemOperand(sp));
678 __ push(r0); 821 __ push(r0);
679 Visit(key); 822 VisitForValue(key, kStack);
680 ASSERT_EQ(Expression::kValue, key->context()); 823 VisitForValue(value, kStack);
681 Visit(value);
682 ASSERT_EQ(Expression::kValue, value->context());
683 __ CallRuntime(Runtime::kSetProperty, 3); 824 __ CallRuntime(Runtime::kSetProperty, 3);
684 __ ldr(r0, MemOperand(sp)); // Restore result into r0.
685 break; 825 break;
686
687 case ObjectLiteral::Property::GETTER: 826 case ObjectLiteral::Property::GETTER:
688 case ObjectLiteral::Property::SETTER: 827 case ObjectLiteral::Property::SETTER:
828 // Duplicate receiver on stack.
829 __ ldr(r0, MemOperand(sp));
689 __ push(r0); 830 __ push(r0);
690 Visit(key); 831 VisitForValue(key, kStack);
691 ASSERT_EQ(Expression::kValue, key->context());
692 __ mov(r1, Operand(property->kind() == ObjectLiteral::Property::SETTER ? 832 __ mov(r1, Operand(property->kind() == ObjectLiteral::Property::SETTER ?
693 Smi::FromInt(1) : 833 Smi::FromInt(1) :
694 Smi::FromInt(0))); 834 Smi::FromInt(0)));
695 __ push(r1); 835 __ push(r1);
696 Visit(value); 836 VisitForValue(value, kStack);
697 ASSERT_EQ(Expression::kValue, value->context());
698 __ CallRuntime(Runtime::kDefineAccessor, 4); 837 __ CallRuntime(Runtime::kDefineAccessor, 4);
699 __ ldr(r0, MemOperand(sp)); // Restore result into r0
700 break; 838 break;
701 } 839 }
702 } 840 }
703 switch (expr->context()) { 841
704 case Expression::kUninitialized: 842 if (result_saved) {
705 UNREACHABLE(); 843 ApplyTOS(expr->context());
706 case Expression::kEffect: 844 } else {
707 if (result_saved) __ Drop(1); 845 Apply(expr->context(), r0);
708 break;
709 case Expression::kValue:
710 if (!result_saved) __ push(r0);
711 break;
712 case Expression::kTest:
713 if (result_saved) __ pop(r0);
714 TestAndBranch(r0, true_label_, false_label_);
715 break;
716 case Expression::kValueTest: {
717 Label discard;
718 if (!result_saved) __ push(r0);
719 TestAndBranch(r0, true_label_, &discard);
720 __ bind(&discard);
721 __ Drop(1);
722 __ jmp(false_label_);
723 break;
724 }
725 case Expression::kTestValue: {
726 Label discard;
727 if (!result_saved) __ push(r0);
728 TestAndBranch(r0, &discard, false_label_);
729 __ bind(&discard);
730 __ Drop(1);
731 __ jmp(true_label_);
732 break;
733 }
734 } 846 }
735 } 847 }
736 848
737 849
738 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 850 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
739 Comment cmnt(masm_, "[ ArrayLiteral"); 851 Comment cmnt(masm_, "[ ArrayLiteral");
740 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 852 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
741 __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); 853 __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
742 __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); 854 __ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
743 __ mov(r1, Operand(expr->constant_elements())); 855 __ mov(r1, Operand(expr->constant_elements()));
(...skipping 15 matching lines...) Expand all
759 // is already set in the cloned array. 871 // is already set in the cloned array.
760 if (subexpr->AsLiteral() != NULL || 872 if (subexpr->AsLiteral() != NULL ||
761 CompileTimeValue::IsCompileTimeValue(subexpr)) { 873 CompileTimeValue::IsCompileTimeValue(subexpr)) {
762 continue; 874 continue;
763 } 875 }
764 876
765 if (!result_saved) { 877 if (!result_saved) {
766 __ push(r0); 878 __ push(r0);
767 result_saved = true; 879 result_saved = true;
768 } 880 }
769 Visit(subexpr); 881 VisitForValue(subexpr, kAccumulator);
770 ASSERT_EQ(Expression::kValue, subexpr->context());
771 882
772 // Store the subexpression value in the array's elements. 883 // Store the subexpression value in the array's elements.
773 __ pop(r0); // Subexpression value.
774 __ ldr(r1, MemOperand(sp)); // Copy of array literal. 884 __ ldr(r1, MemOperand(sp)); // Copy of array literal.
775 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); 885 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset));
776 int offset = FixedArray::kHeaderSize + (i * kPointerSize); 886 int offset = FixedArray::kHeaderSize + (i * kPointerSize);
777 __ str(r0, FieldMemOperand(r1, offset)); 887 __ str(result_register(), FieldMemOperand(r1, offset));
778 888
779 // Update the write barrier for the array store with r0 as the scratch 889 // Update the write barrier for the array store with r0 as the scratch
780 // register. 890 // register.
781 __ mov(r2, Operand(offset)); 891 __ mov(r2, Operand(offset));
782 __ RecordWrite(r1, r2, r0); 892 __ RecordWrite(r1, r2, result_register());
783 } 893 }
784 894
785 switch (expr->context()) { 895 if (result_saved) {
786 case Expression::kUninitialized: 896 ApplyTOS(expr->context());
787 UNREACHABLE(); 897 } else {
788 case Expression::kEffect: 898 Apply(expr->context(), r0);
789 if (result_saved) __ Drop(1);
790 break;
791 case Expression::kValue:
792 if (!result_saved) __ push(r0);
793 break;
794 case Expression::kTest:
795 if (result_saved) __ pop(r0);
796 TestAndBranch(r0, true_label_, false_label_);
797 break;
798 case Expression::kValueTest: {
799 Label discard;
800 if (!result_saved) __ push(r0);
801 TestAndBranch(r0, true_label_, &discard);
802 __ bind(&discard);
803 __ Drop(1);
804 __ jmp(false_label_);
805 break;
806 }
807 case Expression::kTestValue: {
808 Label discard;
809 if (!result_saved) __ push(r0);
810 TestAndBranch(r0, &discard, false_label_);
811 __ bind(&discard);
812 __ Drop(1);
813 __ jmp(true_label_);
814 break;
815 }
816 } 899 }
817 } 900 }
818 901
819 902
820 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop, 903 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
821 Expression::Context context) {
822 SetSourcePosition(prop->position()); 904 SetSourcePosition(prop->position());
823 Literal* key = prop->key()->AsLiteral(); 905 Literal* key = prop->key()->AsLiteral();
824 __ mov(r2, Operand(key->handle())); 906 __ mov(r2, Operand(key->handle()));
825 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 907 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
826 __ Call(ic, RelocInfo::CODE_TARGET); 908 __ Call(ic, RelocInfo::CODE_TARGET);
827 Apply(context, r0);
828 } 909 }
829 910
830 911
831 void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop, 912 void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
832 Expression::Context context) {
833 SetSourcePosition(prop->position()); 913 SetSourcePosition(prop->position());
834 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 914 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
835 __ Call(ic, RelocInfo::CODE_TARGET); 915 __ Call(ic, RelocInfo::CODE_TARGET);
836 Apply(context, r0);
837 } 916 }
838 917
839 918
840 void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op, 919 void FastCodeGenerator::EmitBinaryOp(Token::Value op,
841 Expression::Context context) { 920 Expression::Context context) {
842 __ pop(r0);
843 __ pop(r1); 921 __ pop(r1);
844 GenericBinaryOpStub stub(op, 922 GenericBinaryOpStub stub(op, NO_OVERWRITE);
845 NO_OVERWRITE);
846 __ CallStub(&stub); 923 __ CallStub(&stub);
847 Apply(context, r0); 924 Apply(context, r0);
848 } 925 }
849 926
850 927
851 void FastCodeGenerator::EmitVariableAssignment(Variable* var, 928 void FastCodeGenerator::EmitVariableAssignment(Variable* var,
852 Expression::Context context) { 929 Expression::Context context) {
853 ASSERT(var != NULL); 930 ASSERT(var != NULL);
854 ASSERT(var->is_global() || var->slot() != NULL); 931 ASSERT(var->is_global() || var->slot() != NULL);
855 if (var->is_global()) { 932 if (var->is_global()) {
856 // Assignment to a global variable. Use inline caching for the 933 // Assignment to a global variable. Use inline caching for the
857 // assignment. Right-hand-side value is passed in r0, variable name in 934 // assignment. Right-hand-side value is passed in r0, variable name in
858 // r2, and the global object on the stack. 935 // r2, and the global object on the stack.
859 __ pop(r0);
860 __ mov(r2, Operand(var->name())); 936 __ mov(r2, Operand(var->name()));
861 __ ldr(ip, CodeGenerator::GlobalObject()); 937 __ ldr(ip, CodeGenerator::GlobalObject());
862 __ push(ip); 938 __ push(ip);
863 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 939 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
864 __ Call(ic, RelocInfo::CODE_TARGET); 940 __ Call(ic, RelocInfo::CODE_TARGET);
865 // Overwrite the global object on the stack with the result if needed. 941 // Overwrite the global object on the stack with the result if needed.
866 DropAndApply(1, context, r0); 942 DropAndApply(1, context, r0);
867 943
868 } else if (var->slot() != NULL) { 944 } else if (var->slot() != NULL) {
869 Slot* slot = var->slot(); 945 Slot* slot = var->slot();
870 switch (slot->type()) { 946 switch (slot->type()) {
871 case Slot::LOCAL: 947 case Slot::LOCAL:
872 case Slot::PARAMETER: { 948 case Slot::PARAMETER:
873 MemOperand target = MemOperand(fp, SlotOffset(slot)); 949 __ str(result_register(), MemOperand(fp, SlotOffset(slot)));
874 switch (context) { 950 break;
875 case Expression::kUninitialized: 951
876 UNREACHABLE(); 952 case Slot::CONTEXT: {
877 case Expression::kEffect: 953 MemOperand target = EmitSlotSearch(slot, r1);
878 // Perform assignment and discard value. 954 __ str(result_register(), target);
879 __ pop(r0); 955
880 __ str(r0, target); 956 // RecordWrite may destroy all its register arguments.
881 break; 957 __ mov(r3, result_register());
882 case Expression::kValue: 958 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
883 // Perform assignment and preserve value. 959
884 __ ldr(r0, MemOperand(sp)); 960 __ mov(r2, Operand(offset));
885 __ str(r0, target); 961 __ RecordWrite(r1, r2, r3);
886 break;
887 case Expression::kTest:
888 // Perform assignment and test (and discard) value.
889 __ pop(r0);
890 __ str(r0, target);
891 TestAndBranch(r0, true_label_, false_label_);
892 break;
893 case Expression::kValueTest: {
894 Label discard;
895 __ ldr(r0, MemOperand(sp));
896 __ str(r0, target);
897 TestAndBranch(r0, true_label_, &discard);
898 __ bind(&discard);
899 __ Drop(1);
900 __ jmp(false_label_);
901 break;
902 }
903 case Expression::kTestValue: {
904 Label discard;
905 __ ldr(r0, MemOperand(sp));
906 __ str(r0, target);
907 TestAndBranch(r0, &discard, false_label_);
908 __ bind(&discard);
909 __ Drop(1);
910 __ jmp(true_label_);
911 break;
912 }
913 }
914 break; 962 break;
915 } 963 }
916 964
917 case Slot::CONTEXT: {
918 MemOperand target = EmitSlotSearch(slot, r1);
919 __ pop(r0);
920 __ str(r0, target);
921
922 // RecordWrite may destroy all its register arguments.
923 if (context == Expression::kValue) {
924 __ push(r0);
925 } else if (context != Expression::kEffect) {
926 __ mov(r3, r0);
927 }
928 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
929
930 // Update the write barrier for the array store with r0 as the scratch
931 // register. Skip the write barrier if the value written (r1) is a smi.
932 // The smi test is part of RecordWrite on other platforms, not on arm.
933 Label exit;
934 __ tst(r0, Operand(kSmiTagMask));
935 __ b(eq, &exit);
936
937 __ mov(r2, Operand(offset));
938 __ RecordWrite(r1, r2, r0);
939 __ bind(&exit);
940 if (context != Expression::kEffect && context != Expression::kValue) {
941 Apply(context, r3);
942 }
943 break;
944 }
945
946 case Slot::LOOKUP: 965 case Slot::LOOKUP:
947 UNREACHABLE(); 966 UNREACHABLE();
948 break; 967 break;
949 } 968 }
969 Apply(context, result_register());
950 } else { 970 } else {
951 // Variables rewritten as properties are not treated as variables in 971 // Variables rewritten as properties are not treated as variables in
952 // assignments. 972 // assignments.
953 UNREACHABLE(); 973 UNREACHABLE();
954 } 974 }
955 } 975 }
956 976
957 977
958 void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 978 void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
959 // Assignment to a property, using a named store IC. 979 // Assignment to a property, using a named store IC.
960 Property* prop = expr->target()->AsProperty(); 980 Property* prop = expr->target()->AsProperty();
961 ASSERT(prop != NULL); 981 ASSERT(prop != NULL);
962 ASSERT(prop->key()->AsLiteral() != NULL); 982 ASSERT(prop->key()->AsLiteral() != NULL);
963 983
964 // If the assignment starts a block of assignments to the same object, 984 // If the assignment starts a block of assignments to the same object,
965 // change to slow case to avoid the quadratic behavior of repeatedly 985 // change to slow case to avoid the quadratic behavior of repeatedly
966 // adding fast properties. 986 // adding fast properties.
967 if (expr->starts_initialization_block()) { 987 if (expr->starts_initialization_block()) {
968 __ ldr(ip, MemOperand(sp, kPointerSize)); // Receiver is under value. 988 __ push(result_register());
989 __ ldr(ip, MemOperand(sp, kPointerSize)); // Receiver is now under value.
969 __ push(ip); 990 __ push(ip);
970 __ CallRuntime(Runtime::kToSlowProperties, 1); 991 __ CallRuntime(Runtime::kToSlowProperties, 1);
992 __ pop(result_register());
971 } 993 }
972 994
973 __ pop(r0); 995 // Record source code position before IC call.
996 SetSourcePosition(expr->position());
974 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); 997 __ mov(r2, Operand(prop->key()->AsLiteral()->handle()));
975 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 998 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
976 __ Call(ic, RelocInfo::CODE_TARGET); 999 __ Call(ic, RelocInfo::CODE_TARGET);
977 1000
978 // If the assignment ends an initialization block, revert to fast case. 1001 // If the assignment ends an initialization block, revert to fast case.
979 if (expr->ends_initialization_block()) { 1002 if (expr->ends_initialization_block()) {
980 __ push(r0); // Result of assignment, saved even if not needed. 1003 __ push(r0); // Result of assignment, saved even if not needed.
981 __ ldr(ip, MemOperand(sp, kPointerSize)); // Receiver is under value. 1004 __ ldr(ip, MemOperand(sp, kPointerSize)); // Receiver is under value.
982 __ push(ip); 1005 __ push(ip);
983 __ CallRuntime(Runtime::kToFastProperties, 1); 1006 __ CallRuntime(Runtime::kToFastProperties, 1);
984 __ pop(r0); 1007 __ pop(r0);
985 } 1008 }
986 1009
987 DropAndApply(1, expr->context(), r0); 1010 DropAndApply(1, expr->context(), r0);
988 } 1011 }
989 1012
990 1013
991 void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 1014 void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
992 // Assignment to a property, using a keyed store IC. 1015 // Assignment to a property, using a keyed store IC.
993 1016
994 // If the assignment starts a block of assignments to the same object, 1017 // If the assignment starts a block of assignments to the same object,
995 // change to slow case to avoid the quadratic behavior of repeatedly 1018 // change to slow case to avoid the quadratic behavior of repeatedly
996 // adding fast properties. 1019 // adding fast properties.
997 if (expr->starts_initialization_block()) { 1020 if (expr->starts_initialization_block()) {
998 // Receiver is under the key and value. 1021 __ push(result_register());
1022 // Receiver is now under the key and value.
999 __ ldr(ip, MemOperand(sp, 2 * kPointerSize)); 1023 __ ldr(ip, MemOperand(sp, 2 * kPointerSize));
1000 __ push(ip); 1024 __ push(ip);
1001 __ CallRuntime(Runtime::kToSlowProperties, 1); 1025 __ CallRuntime(Runtime::kToSlowProperties, 1);
1026 __ pop(result_register());
1002 } 1027 }
1003 1028
1004 __ pop(r0); 1029 // Record source code position before IC call.
1030 SetSourcePosition(expr->position());
1005 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 1031 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
1006 __ Call(ic, RelocInfo::CODE_TARGET); 1032 __ Call(ic, RelocInfo::CODE_TARGET);
1007 1033
1008 // If the assignment ends an initialization block, revert to fast case. 1034 // If the assignment ends an initialization block, revert to fast case.
1009 if (expr->ends_initialization_block()) { 1035 if (expr->ends_initialization_block()) {
1010 __ push(r0); // Result of assignment, saved even if not needed. 1036 __ push(r0); // Result of assignment, saved even if not needed.
1011 // Reciever is under the key and value. 1037 // Receiver is under the key and value.
1012 __ ldr(ip, MemOperand(sp, 2 * kPointerSize)); 1038 __ ldr(ip, MemOperand(sp, 2 * kPointerSize));
1013 __ push(ip); 1039 __ push(ip);
1014 __ CallRuntime(Runtime::kToFastProperties, 1); 1040 __ CallRuntime(Runtime::kToFastProperties, 1);
1015 __ pop(r0); 1041 __ pop(r0);
1016 } 1042 }
1017 1043
1018 // Receiver and key are still on stack. 1044 // Receiver and key are still on stack.
1019 DropAndApply(2, expr->context(), r0); 1045 DropAndApply(2, expr->context(), r0);
1020 } 1046 }
1021 1047
1022 1048
1023 void FastCodeGenerator::VisitProperty(Property* expr) { 1049 void FastCodeGenerator::VisitProperty(Property* expr) {
1024 Comment cmnt(masm_, "[ Property"); 1050 Comment cmnt(masm_, "[ Property");
1025 Expression* key = expr->key(); 1051 Expression* key = expr->key();
1026 1052
1027 // Record the source position for the property load.
1028 SetSourcePosition(expr->position());
1029
1030 // Evaluate receiver. 1053 // Evaluate receiver.
1031 Visit(expr->obj()); 1054 VisitForValue(expr->obj(), kStack);
1032 1055
1033 if (key->IsPropertyName()) { 1056 if (key->IsPropertyName()) {
1034 // Do a named property load. The IC expects the property name in r2 and 1057 EmitNamedPropertyLoad(expr);
1035 // the receiver on the stack. 1058 // Drop receiver left on the stack by IC.
1036 __ mov(r2, Operand(key->AsLiteral()->handle()));
1037 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
1038 __ Call(ic, RelocInfo::CODE_TARGET);
1039 DropAndApply(1, expr->context(), r0); 1059 DropAndApply(1, expr->context(), r0);
1040 } else { 1060 } else {
1041 // Do a keyed property load. 1061 VisitForValue(expr->key(), kStack);
1042 Visit(expr->key()); 1062 EmitKeyedPropertyLoad(expr);
1043 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1044 __ Call(ic, RelocInfo::CODE_TARGET);
1045 // Drop key and receiver left on the stack by IC. 1063 // Drop key and receiver left on the stack by IC.
1046 DropAndApply(2, expr->context(), r0); 1064 DropAndApply(2, expr->context(), r0);
1047 } 1065 }
1048 } 1066 }
1049 1067
1050 void FastCodeGenerator::EmitCallWithIC(Call* expr, 1068 void FastCodeGenerator::EmitCallWithIC(Call* expr,
1051 Handle<Object> ignored, 1069 Handle<Object> ignored,
1052 RelocInfo::Mode mode) { 1070 RelocInfo::Mode mode) {
1053 // Code common for calls using the IC. 1071 // Code common for calls using the IC.
1054 ZoneList<Expression*>* args = expr->arguments(); 1072 ZoneList<Expression*>* args = expr->arguments();
1055 int arg_count = args->length(); 1073 int arg_count = args->length();
1056 for (int i = 0; i < arg_count; i++) { 1074 for (int i = 0; i < arg_count; i++) {
1057 Visit(args->at(i)); 1075 VisitForValue(args->at(i), kStack);
1058 ASSERT_EQ(Expression::kValue, args->at(i)->context());
1059 } 1076 }
1060 // Record source position for debugger. 1077 // Record source position for debugger.
1061 SetSourcePosition(expr->position()); 1078 SetSourcePosition(expr->position());
1062 // Call the IC initialization code. 1079 // Call the IC initialization code.
1063 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, 1080 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
1064 NOT_IN_LOOP); 1081 NOT_IN_LOOP);
1065 __ Call(ic, mode); 1082 __ Call(ic, mode);
1066 // Restore context register. 1083 // Restore context register.
1067 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 1084 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
1068 // Discard the function left on TOS. 1085 // Discard the function left on TOS.
1069 DropAndApply(1, expr->context(), r0); 1086 DropAndApply(1, expr->context(), r0);
1070 } 1087 }
1071 1088
1072 1089
1073 void FastCodeGenerator::EmitCallWithStub(Call* expr) { 1090 void FastCodeGenerator::EmitCallWithStub(Call* expr) {
1074 // Code common for calls using the call stub. 1091 // Code common for calls using the call stub.
1075 ZoneList<Expression*>* args = expr->arguments(); 1092 ZoneList<Expression*>* args = expr->arguments();
1076 int arg_count = args->length(); 1093 int arg_count = args->length();
1077 for (int i = 0; i < arg_count; i++) { 1094 for (int i = 0; i < arg_count; i++) {
1078 Visit(args->at(i)); 1095 VisitForValue(args->at(i), kStack);
1079 } 1096 }
1080 // Record source position for debugger. 1097 // Record source position for debugger.
1081 SetSourcePosition(expr->position()); 1098 SetSourcePosition(expr->position());
1082 CallFunctionStub stub(arg_count, NOT_IN_LOOP); 1099 CallFunctionStub stub(arg_count, NOT_IN_LOOP);
1083 __ CallStub(&stub); 1100 __ CallStub(&stub);
1084 // Restore context register. 1101 // Restore context register.
1085 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 1102 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
1086 // Discard the function left on TOS. 1103 // Discard the function left on TOS.
1087 DropAndApply(1, expr->context(), r0); 1104 DropAndApply(1, expr->context(), r0);
1088 } 1105 }
(...skipping 19 matching lines...) Expand all
1108 // Call to a lookup slot. 1125 // Call to a lookup slot.
1109 UNREACHABLE(); 1126 UNREACHABLE();
1110 } else if (fun->AsProperty() != NULL) { 1127 } else if (fun->AsProperty() != NULL) {
1111 // Call to an object property. 1128 // Call to an object property.
1112 Property* prop = fun->AsProperty(); 1129 Property* prop = fun->AsProperty();
1113 Literal* key = prop->key()->AsLiteral(); 1130 Literal* key = prop->key()->AsLiteral();
1114 if (key != NULL && key->handle()->IsSymbol()) { 1131 if (key != NULL && key->handle()->IsSymbol()) {
1115 // Call to a named property, use call IC. 1132 // Call to a named property, use call IC.
1116 __ mov(r0, Operand(key->handle())); 1133 __ mov(r0, Operand(key->handle()));
1117 __ push(r0); 1134 __ push(r0);
1118 Visit(prop->obj()); 1135 VisitForValue(prop->obj(), kStack);
1119 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); 1136 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
1120 } else { 1137 } else {
1121 // Call to a keyed property, use keyed load IC followed by function 1138 // Call to a keyed property, use keyed load IC followed by function
1122 // call. 1139 // call.
1123 Visit(prop->obj()); 1140 VisitForValue(prop->obj(), kStack);
1124 Visit(prop->key()); 1141 VisitForValue(prop->key(), kStack);
1125 // Record source code position for IC call. 1142 // Record source code position for IC call.
1126 SetSourcePosition(prop->position()); 1143 SetSourcePosition(prop->position());
1127 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 1144 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1128 __ Call(ic, RelocInfo::CODE_TARGET); 1145 __ Call(ic, RelocInfo::CODE_TARGET);
1129 // Load receiver object into r1. 1146 // Load receiver object into r1.
1130 if (prop->is_synthetic()) { 1147 if (prop->is_synthetic()) {
1131 __ ldr(r1, CodeGenerator::GlobalObject()); 1148 __ ldr(r1, CodeGenerator::GlobalObject());
1132 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); 1149 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
1133 } else { 1150 } else {
1134 __ ldr(r1, MemOperand(sp, kPointerSize)); 1151 __ ldr(r1, MemOperand(sp, kPointerSize));
1135 } 1152 }
1136 // Overwrite (object, key) with (function, receiver). 1153 // Overwrite (object, key) with (function, receiver).
1137 __ str(r0, MemOperand(sp, kPointerSize)); 1154 __ str(r0, MemOperand(sp, kPointerSize));
1138 __ str(r1, MemOperand(sp)); 1155 __ str(r1, MemOperand(sp));
1139 EmitCallWithStub(expr); 1156 EmitCallWithStub(expr);
1140 } 1157 }
1141 } else { 1158 } else {
1142 // Call to some other expression. If the expression is an anonymous 1159 // Call to some other expression. If the expression is an anonymous
1143 // function literal not called in a loop, mark it as one that should 1160 // function literal not called in a loop, mark it as one that should
1144 // also use the fast code generator. 1161 // also use the fast code generator.
1145 FunctionLiteral* lit = fun->AsFunctionLiteral(); 1162 FunctionLiteral* lit = fun->AsFunctionLiteral();
1146 if (lit != NULL && 1163 if (lit != NULL &&
1147 lit->name()->Equals(Heap::empty_string()) && 1164 lit->name()->Equals(Heap::empty_string()) &&
1148 loop_depth() == 0) { 1165 loop_depth() == 0) {
1149 lit->set_try_fast_codegen(true); 1166 lit->set_try_fast_codegen(true);
1150 } 1167 }
1151 Visit(fun); 1168 VisitForValue(fun, kStack);
1152 // Load global receiver object. 1169 // Load global receiver object.
1153 __ ldr(r1, CodeGenerator::GlobalObject()); 1170 __ ldr(r1, CodeGenerator::GlobalObject());
1154 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); 1171 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
1155 __ push(r1); 1172 __ push(r1);
1156 // Emit function call. 1173 // Emit function call.
1157 EmitCallWithStub(expr); 1174 EmitCallWithStub(expr);
1158 } 1175 }
1159 } 1176 }
1160 1177
1161 1178
1162 void FastCodeGenerator::VisitCallNew(CallNew* expr) { 1179 void FastCodeGenerator::VisitCallNew(CallNew* expr) {
1163 Comment cmnt(masm_, "[ CallNew"); 1180 Comment cmnt(masm_, "[ CallNew");
1164 // According to ECMA-262, section 11.2.2, page 44, the function 1181 // According to ECMA-262, section 11.2.2, page 44, the function
1165 // expression in new calls must be evaluated before the 1182 // expression in new calls must be evaluated before the
1166 // arguments. 1183 // arguments.
1167 // Push function on the stack. 1184 // Push function on the stack.
1168 Visit(expr->expression()); 1185 VisitForValue(expr->expression(), kStack);
1169 ASSERT_EQ(Expression::kValue, expr->expression()->context());
1170 1186
1171 // Push global object (receiver). 1187 // Push global object (receiver).
1172 __ ldr(r0, CodeGenerator::GlobalObject()); 1188 __ ldr(r0, CodeGenerator::GlobalObject());
1173 __ push(r0); 1189 __ push(r0);
1174 // Push the arguments ("left-to-right") on the stack. 1190 // Push the arguments ("left-to-right") on the stack.
1175 ZoneList<Expression*>* args = expr->arguments(); 1191 ZoneList<Expression*>* args = expr->arguments();
1176 int arg_count = args->length(); 1192 int arg_count = args->length();
1177 for (int i = 0; i < arg_count; i++) { 1193 for (int i = 0; i < arg_count; i++) {
1178 Visit(args->at(i)); 1194 VisitForValue(args->at(i), kStack);
1179 ASSERT_EQ(Expression::kValue, args->at(i)->context());
1180 // If location is value, it is already on the stack,
1181 // so nothing to do here.
1182 } 1195 }
1183 1196
1184 // Call the construct call builtin that handles allocation and 1197 // Call the construct call builtin that handles allocation and
1185 // constructor invocation. 1198 // constructor invocation.
1186 SetSourcePosition(expr->position()); 1199 SetSourcePosition(expr->position());
1187 1200
1188 // Load function, arg_count into r1 and r0. 1201 // Load function, arg_count into r1 and r0.
1189 __ mov(r0, Operand(arg_count)); 1202 __ mov(r0, Operand(arg_count));
1190 // Function is in sp[arg_count + 1]. 1203 // Function is in sp[arg_count + 1].
1191 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); 1204 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
(...skipping 14 matching lines...) Expand all
1206 // Prepare for calling JS runtime function. 1219 // Prepare for calling JS runtime function.
1207 __ mov(r1, Operand(expr->name())); 1220 __ mov(r1, Operand(expr->name()));
1208 __ ldr(r0, CodeGenerator::GlobalObject()); 1221 __ ldr(r0, CodeGenerator::GlobalObject());
1209 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset)); 1222 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset));
1210 __ stm(db_w, sp, r1.bit() | r0.bit()); 1223 __ stm(db_w, sp, r1.bit() | r0.bit());
1211 } 1224 }
1212 1225
1213 // Push the arguments ("left-to-right"). 1226 // Push the arguments ("left-to-right").
1214 int arg_count = args->length(); 1227 int arg_count = args->length();
1215 for (int i = 0; i < arg_count; i++) { 1228 for (int i = 0; i < arg_count; i++) {
1216 Visit(args->at(i)); 1229 VisitForValue(args->at(i), kStack);
1217 ASSERT_EQ(Expression::kValue, args->at(i)->context());
1218 } 1230 }
1219 1231
1220 if (expr->is_jsruntime()) { 1232 if (expr->is_jsruntime()) {
1221 // Call the JS runtime function. 1233 // Call the JS runtime function.
1222 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, 1234 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
1223 NOT_IN_LOOP); 1235 NOT_IN_LOOP);
1224 __ Call(ic, RelocInfo::CODE_TARGET); 1236 __ Call(ic, RelocInfo::CODE_TARGET);
1225 // Restore context register. 1237 // Restore context register.
1226 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 1238 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
1227 // Discard the function left on TOS. 1239 // Discard the function left on TOS.
1228 DropAndApply(1, expr->context(), r0); 1240 DropAndApply(1, expr->context(), r0);
1229 } else { 1241 } else {
1230 // Call the C runtime function. 1242 // Call the C runtime function.
1231 __ CallRuntime(expr->function(), arg_count); 1243 __ CallRuntime(expr->function(), arg_count);
1232 Apply(expr->context(), r0); 1244 Apply(expr->context(), r0);
1233 } 1245 }
1234 } 1246 }
1235 1247
1236 1248
1237 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 1249 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
1238 switch (expr->op()) { 1250 switch (expr->op()) {
1239 case Token::VOID: { 1251 case Token::VOID: {
1240 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); 1252 Comment cmnt(masm_, "[ UnaryOperation (VOID)");
1253 ASSERT_EQ(Expression::kEffect, expr->expression()->context());
1241 Visit(expr->expression()); 1254 Visit(expr->expression());
1242 ASSERT_EQ(Expression::kEffect, expr->expression()->context());
1243 switch (expr->context()) { 1255 switch (expr->context()) {
1244 case Expression::kUninitialized: 1256 case Expression::kUninitialized:
1245 UNREACHABLE(); 1257 UNREACHABLE();
1246 break; 1258 break;
1247 case Expression::kEffect: 1259 case Expression::kEffect:
1248 break; 1260 break;
1249 case Expression::kValue: 1261 case Expression::kValue:
1250 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 1262 __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex);
1251 __ push(ip); 1263 switch (location_) {
1264 case kAccumulator:
1265 break;
1266 case kStack:
1267 __ push(result_register());
1268 break;
1269 }
1252 break; 1270 break;
1253 case Expression::kTestValue: 1271 case Expression::kTestValue:
1254 // Value is false so it's needed. 1272 // Value is false so it's needed.
1255 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 1273 __ LoadRoot(result_register(), Heap::kUndefinedValueRootIndex);
1256 __ push(ip); 1274 switch (location_) {
1275 case kAccumulator:
1276 break;
1277 case kStack:
1278 __ push(result_register());
1279 break;
1280 }
1281 // Fall through.
1257 case Expression::kTest: 1282 case Expression::kTest:
1258 case Expression::kValueTest: 1283 case Expression::kValueTest:
1259 __ jmp(false_label_); 1284 __ jmp(false_label_);
1260 break; 1285 break;
1261 } 1286 }
1262 break; 1287 break;
1263 } 1288 }
1264 1289
1265 case Token::NOT: { 1290 case Token::NOT: {
1266 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 1291 Comment cmnt(masm_, "[ UnaryOperation (NOT)");
1267 ASSERT_EQ(Expression::kTest, expr->expression()->context()); 1292 ASSERT_EQ(Expression::kTest, expr->expression()->context());
1268 1293
1269 Label push_true, push_false, done; 1294 Label materialize_true, materialize_false, done;
1295 // Initially assume a pure test context. Notice that the labels are
1296 // swapped.
1297 Label* if_true = false_label_;
1298 Label* if_false = true_label_;
1270 switch (expr->context()) { 1299 switch (expr->context()) {
1271 case Expression::kUninitialized: 1300 case Expression::kUninitialized:
1272 UNREACHABLE(); 1301 UNREACHABLE();
1273 break; 1302 break;
1274
1275 case Expression::kEffect: 1303 case Expression::kEffect:
1276 VisitForControl(expr->expression(), &done, &done); 1304 if_true = &done;
1277 __ bind(&done); 1305 if_false = &done;
1278 break; 1306 break;
1279
1280 case Expression::kValue: 1307 case Expression::kValue:
1281 VisitForControl(expr->expression(), &push_false, &push_true); 1308 if_true = &materialize_false;
1282 __ bind(&push_true); 1309 if_false = &materialize_true;
1283 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
1284 __ push(ip);
1285 __ jmp(&done);
1286 __ bind(&push_false);
1287 __ LoadRoot(ip, Heap::kFalseValueRootIndex);
1288 __ push(ip);
1289 __ bind(&done);
1290 break; 1310 break;
1291
1292 case Expression::kTest: 1311 case Expression::kTest:
1293 VisitForControl(expr->expression(), false_label_, true_label_);
1294 break; 1312 break;
1295
1296 case Expression::kValueTest: 1313 case Expression::kValueTest:
1297 VisitForControl(expr->expression(), false_label_, &push_true); 1314 if_false = &materialize_true;
1298 __ bind(&push_true);
1299 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
1300 __ push(ip);
1301 __ jmp(true_label_);
1302 break; 1315 break;
1303
1304 case Expression::kTestValue: 1316 case Expression::kTestValue:
1305 VisitForControl(expr->expression(), &push_false, true_label_); 1317 if_true = &materialize_false;
1306 __ bind(&push_false);
1307 __ LoadRoot(ip, Heap::kFalseValueRootIndex);
1308 __ push(ip);
1309 __ jmp(false_label_);
1310 break; 1318 break;
1311 } 1319 }
1320 VisitForControl(expr->expression(), if_true, if_false);
1321 Apply(expr->context(), if_false, if_true); // Labels swapped.
1312 break; 1322 break;
1313 } 1323 }
1314 1324
1315 case Token::TYPEOF: { 1325 case Token::TYPEOF: {
1316 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 1326 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
1317 ASSERT_EQ(Expression::kValue, expr->expression()->context()); 1327 ASSERT_EQ(Expression::kValue, expr->expression()->context());
1318 1328
1319 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 1329 VariableProxy* proxy = expr->expression()->AsVariableProxy();
1320 if (proxy != NULL && 1330 if (proxy != NULL &&
1321 !proxy->var()->is_this() && 1331 !proxy->var()->is_this() &&
1322 proxy->var()->is_global()) { 1332 proxy->var()->is_global()) {
1323 Comment cmnt(masm_, "Global variable"); 1333 Comment cmnt(masm_, "Global variable");
1324 __ ldr(r0, CodeGenerator::GlobalObject()); 1334 __ ldr(r0, CodeGenerator::GlobalObject());
1325 __ push(r0); 1335 __ push(r0);
1326 __ mov(r2, Operand(proxy->name())); 1336 __ mov(r2, Operand(proxy->name()));
1327 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 1337 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
1328 // Use a regular load, not a contextual load, to avoid a reference 1338 // Use a regular load, not a contextual load, to avoid a reference
1329 // error. 1339 // error.
1330 __ Call(ic, RelocInfo::CODE_TARGET); 1340 __ Call(ic, RelocInfo::CODE_TARGET);
1331 __ str(r0, MemOperand(sp)); 1341 __ str(r0, MemOperand(sp));
1332 } else if (proxy != NULL && 1342 } else if (proxy != NULL &&
1333 proxy->var()->slot() != NULL && 1343 proxy->var()->slot() != NULL &&
1334 proxy->var()->slot()->type() == Slot::LOOKUP) { 1344 proxy->var()->slot()->type() == Slot::LOOKUP) {
1335 __ mov(r0, Operand(proxy->name())); 1345 __ mov(r0, Operand(proxy->name()));
1336 __ stm(db_w, sp, cp.bit() | r0.bit()); 1346 __ stm(db_w, sp, cp.bit() | r0.bit());
1337 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 1347 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
1338 __ push(r0); 1348 __ push(r0);
1339 } else { 1349 } else {
1340 // This expression cannot throw a reference error at the top level. 1350 // This expression cannot throw a reference error at the top level.
1341 Visit(expr->expression()); 1351 VisitForValue(expr->expression(), kStack);
1342 } 1352 }
1343 1353
1344 __ CallRuntime(Runtime::kTypeof, 1); 1354 __ CallRuntime(Runtime::kTypeof, 1);
1345 Apply(expr->context(), r0); 1355 Apply(expr->context(), r0);
1346 break; 1356 break;
1347 } 1357 }
1348 1358
1349 default: 1359 default:
1350 UNREACHABLE(); 1360 UNREACHABLE();
1351 } 1361 }
(...skipping 12 matching lines...) Expand all
1364 // of the key to detect a named property. 1374 // of the key to detect a named property.
1365 if (prop != NULL) { 1375 if (prop != NULL) {
1366 assign_type = (prop->key()->context() == Expression::kUninitialized) 1376 assign_type = (prop->key()->context() == Expression::kUninitialized)
1367 ? NAMED_PROPERTY 1377 ? NAMED_PROPERTY
1368 : KEYED_PROPERTY; 1378 : KEYED_PROPERTY;
1369 } 1379 }
1370 1380
1371 // Evaluate expression and get value. 1381 // Evaluate expression and get value.
1372 if (assign_type == VARIABLE) { 1382 if (assign_type == VARIABLE) {
1373 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); 1383 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
1384 Location saved_location = location_;
1385 location_ = kStack;
1374 EmitVariableLoad(expr->expression()->AsVariableProxy()->var(), 1386 EmitVariableLoad(expr->expression()->AsVariableProxy()->var(),
1375 Expression::kValue); 1387 Expression::kValue);
1388 location_ = saved_location;
1376 } else { 1389 } else {
1377 // Reserve space for result of postfix operation. 1390 // Reserve space for result of postfix operation.
1378 if (expr->is_postfix() && expr->context() != Expression::kEffect) { 1391 if (expr->is_postfix() && expr->context() != Expression::kEffect) {
1379 ASSERT(expr->context() != Expression::kUninitialized); 1392 ASSERT(expr->context() != Expression::kUninitialized);
1380 __ mov(ip, Operand(Smi::FromInt(0))); 1393 __ mov(ip, Operand(Smi::FromInt(0)));
1381 __ push(ip); 1394 __ push(ip);
1382 } 1395 }
1383 Visit(prop->obj()); 1396 VisitForValue(prop->obj(), kStack);
1384 ASSERT_EQ(Expression::kValue, prop->obj()->context());
1385 if (assign_type == NAMED_PROPERTY) { 1397 if (assign_type == NAMED_PROPERTY) {
1386 EmitNamedPropertyLoad(prop, Expression::kValue); 1398 EmitNamedPropertyLoad(prop);
1387 } else { 1399 } else {
1388 Visit(prop->key()); 1400 VisitForValue(prop->key(), kStack);
1389 ASSERT_EQ(Expression::kValue, prop->key()->context()); 1401 EmitKeyedPropertyLoad(prop);
1390 EmitKeyedPropertyLoad(prop, Expression::kValue);
1391 } 1402 }
1403 __ push(r0);
1392 } 1404 }
1393 1405
1394 // Convert to number. 1406 // Convert to number.
1395 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS); 1407 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS);
1396 1408
1397 // Save result for postfix expressions. 1409 // Save result for postfix expressions.
1398 if (expr->is_postfix()) { 1410 if (expr->is_postfix()) {
1399 switch (expr->context()) { 1411 switch (expr->context()) {
1400 case Expression::kUninitialized: 1412 case Expression::kUninitialized:
1401 UNREACHABLE(); 1413 UNREACHABLE();
1402 case Expression::kEffect: 1414 case Expression::kEffect:
1403 // Do not save result. 1415 // Do not save result.
1404 break; 1416 break;
1405 case Expression::kValue: 1417 case Expression::kValue:
1406 case Expression::kTest: 1418 case Expression::kTest:
1419 case Expression::kValueTest:
1407 case Expression::kTestValue: 1420 case Expression::kTestValue:
1408 case Expression::kValueTest:
1409 // Save the result on the stack. If we have a named or keyed property 1421 // Save the result on the stack. If we have a named or keyed property
1410 // we store the result under the receiver that is currently on top 1422 // we store the result under the receiver that is currently on top
1411 // of the stack. 1423 // of the stack.
1412 switch (assign_type) { 1424 switch (assign_type) {
1413 case VARIABLE: 1425 case VARIABLE:
1414 __ push(r0); 1426 __ push(r0);
1415 break; 1427 break;
1416 case NAMED_PROPERTY: 1428 case NAMED_PROPERTY:
1417 __ str(r0, MemOperand(sp, kPointerSize)); 1429 __ str(r0, MemOperand(sp, kPointerSize));
1418 break; 1430 break;
1419 case KEYED_PROPERTY: 1431 case KEYED_PROPERTY:
1420 __ str(r0, MemOperand(sp, 2 * kPointerSize)); 1432 __ str(r0, MemOperand(sp, 2 * kPointerSize));
1421 break; 1433 break;
1422 } 1434 }
1423 break; 1435 break;
1424 } 1436 }
1425 } 1437 }
1426 1438
1427 // Call runtime for +1/-1. 1439 // Call stub for +1/-1.
1428 if (expr->op() == Token::INC) { 1440 __ mov(r1, Operand(expr->op() == Token::INC
1429 __ mov(ip, Operand(Smi::FromInt(1))); 1441 ? Smi::FromInt(1)
1430 } else { 1442 : Smi::FromInt(-1)));
1431 __ mov(ip, Operand(Smi::FromInt(-1))); 1443 GenericBinaryOpStub stub(Token::ADD, NO_OVERWRITE);
1432 } 1444 __ CallStub(&stub);
1433 __ stm(db_w, sp, ip.bit() | r0.bit());
1434 __ CallRuntime(Runtime::kNumberAdd, 2);
1435 1445
1436 // Store the value returned in r0. 1446 // Store the value returned in r0.
1437 switch (assign_type) { 1447 switch (assign_type) {
1438 case VARIABLE: 1448 case VARIABLE:
1439 __ push(r0);
1440 if (expr->is_postfix()) { 1449 if (expr->is_postfix()) {
1441 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 1450 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
1442 Expression::kEffect); 1451 Expression::kEffect);
1443 // For all contexts except kEffect: We have the result on 1452 // For all contexts except kEffect: We have the result on
1444 // top of the stack. 1453 // top of the stack.
1445 if (expr->context() != Expression::kEffect) { 1454 if (expr->context() != Expression::kEffect) {
1446 ApplyTOS(expr->context()); 1455 ApplyTOS(expr->context());
1447 } 1456 }
1448 } else { 1457 } else {
1449 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 1458 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1499 case Token::ADD: 1508 case Token::ADD:
1500 case Token::SUB: 1509 case Token::SUB:
1501 case Token::DIV: 1510 case Token::DIV:
1502 case Token::MOD: 1511 case Token::MOD:
1503 case Token::MUL: 1512 case Token::MUL:
1504 case Token::BIT_OR: 1513 case Token::BIT_OR:
1505 case Token::BIT_AND: 1514 case Token::BIT_AND:
1506 case Token::BIT_XOR: 1515 case Token::BIT_XOR:
1507 case Token::SHL: 1516 case Token::SHL:
1508 case Token::SHR: 1517 case Token::SHR:
1509 case Token::SAR: { 1518 case Token::SAR:
1510 ASSERT_EQ(Expression::kValue, expr->left()->context()); 1519 VisitForValue(expr->left(), kStack);
1511 ASSERT_EQ(Expression::kValue, expr->right()->context()); 1520 VisitForValue(expr->right(), kAccumulator);
1521 EmitBinaryOp(expr->op(), expr->context());
1522 break;
1512 1523
1513 Visit(expr->left());
1514 Visit(expr->right());
1515 __ pop(r0);
1516 __ pop(r1);
1517 GenericBinaryOpStub stub(expr->op(),
1518 NO_OVERWRITE);
1519 __ CallStub(&stub);
1520 Apply(expr->context(), r0);
1521
1522 break;
1523 }
1524 default: 1524 default:
1525 UNREACHABLE(); 1525 UNREACHABLE();
1526 } 1526 }
1527 } 1527 }
1528 1528
1529 1529
1530 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 1530 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
1531 Comment cmnt(masm_, "[ CompareOperation"); 1531 Comment cmnt(masm_, "[ CompareOperation");
1532 ASSERT_EQ(Expression::kValue, expr->left()->context());
1533 ASSERT_EQ(Expression::kValue, expr->right()->context());
1534 Visit(expr->left());
1535 Visit(expr->right());
1536 1532
1537 // Always perform the comparison for its control flow. Pack the result 1533 // Always perform the comparison for its control flow. Pack the result
1538 // into the expression's context after the comparison is performed. 1534 // into the expression's context after the comparison is performed.
1539 Label push_true, push_false, done; 1535 Label materialize_true, materialize_false, done;
1540 // Initially assume we are in a test context. 1536 // Initially assume we are in a test context.
1541 Label* if_true = true_label_; 1537 Label* if_true = true_label_;
1542 Label* if_false = false_label_; 1538 Label* if_false = false_label_;
1543 switch (expr->context()) { 1539 switch (expr->context()) {
1544 case Expression::kUninitialized: 1540 case Expression::kUninitialized:
1545 UNREACHABLE(); 1541 UNREACHABLE();
1546 break; 1542 break;
1547 case Expression::kEffect: 1543 case Expression::kEffect:
1548 if_true = &done; 1544 if_true = &done;
1549 if_false = &done; 1545 if_false = &done;
1550 break; 1546 break;
1551 case Expression::kValue: 1547 case Expression::kValue:
1552 if_true = &push_true; 1548 if_true = &materialize_true;
1553 if_false = &push_false; 1549 if_false = &materialize_false;
1554 break; 1550 break;
1555 case Expression::kTest: 1551 case Expression::kTest:
1556 break; 1552 break;
1557 case Expression::kValueTest: 1553 case Expression::kValueTest:
1558 if_true = &push_true; 1554 if_true = &materialize_true;
1559 break; 1555 break;
1560 case Expression::kTestValue: 1556 case Expression::kTestValue:
1561 if_false = &push_false; 1557 if_false = &materialize_false;
1562 break; 1558 break;
1563 } 1559 }
1564 1560
1561 VisitForValue(expr->left(), kStack);
1565 switch (expr->op()) { 1562 switch (expr->op()) {
1566 case Token::IN: { 1563 case Token::IN:
1564 VisitForValue(expr->right(), kStack);
1567 __ InvokeBuiltin(Builtins::IN, CALL_JS); 1565 __ InvokeBuiltin(Builtins::IN, CALL_JS);
1568 __ LoadRoot(ip, Heap::kTrueValueRootIndex); 1566 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
1569 __ cmp(r0, ip); 1567 __ cmp(r0, ip);
1570 __ b(eq, if_true); 1568 __ b(eq, if_true);
1571 __ jmp(if_false); 1569 __ jmp(if_false);
1572 break; 1570 break;
1573 }
1574 1571
1575 case Token::INSTANCEOF: { 1572 case Token::INSTANCEOF: {
1573 VisitForValue(expr->right(), kStack);
1576 InstanceofStub stub; 1574 InstanceofStub stub;
1577 __ CallStub(&stub); 1575 __ CallStub(&stub);
1578 __ tst(r0, r0); 1576 __ tst(r0, r0);
1579 __ b(eq, if_true); // The stub returns 0 for true. 1577 __ b(eq, if_true); // The stub returns 0 for true.
1580 __ jmp(if_false); 1578 __ jmp(if_false);
1581 break; 1579 break;
1582 } 1580 }
1583 1581
1584 default: { 1582 default: {
1583 VisitForValue(expr->right(), kAccumulator);
1585 Condition cc = eq; 1584 Condition cc = eq;
1586 bool strict = false; 1585 bool strict = false;
1587 switch (expr->op()) { 1586 switch (expr->op()) {
1588 case Token::EQ_STRICT: 1587 case Token::EQ_STRICT:
1589 strict = true; 1588 strict = true;
1590 // Fall through 1589 // Fall through
1591 case Token::EQ: 1590 case Token::EQ:
1592 cc = eq; 1591 cc = eq;
1593 __ pop(r0);
1594 __ pop(r1); 1592 __ pop(r1);
1595 break; 1593 break;
1596 case Token::LT: 1594 case Token::LT:
1597 cc = lt; 1595 cc = lt;
1598 __ pop(r0);
1599 __ pop(r1); 1596 __ pop(r1);
1600 break; 1597 break;
1601 case Token::GT: 1598 case Token::GT:
1602 // Reverse left and right sizes to obtain ECMA-262 conversion order. 1599 // Reverse left and right sizes to obtain ECMA-262 conversion order.
1603 cc = lt; 1600 cc = lt;
1604 __ pop(r1); 1601 __ mov(r1, result_register());
1605 __ pop(r0); 1602 __ pop(r0);
1606 break; 1603 break;
1607 case Token::LTE: 1604 case Token::LTE:
1608 // Reverse left and right sizes to obtain ECMA-262 conversion order. 1605 // Reverse left and right sizes to obtain ECMA-262 conversion order.
1609 cc = ge; 1606 cc = ge;
1610 __ pop(r1); 1607 __ mov(r1, result_register());
1611 __ pop(r0); 1608 __ pop(r0);
1612 break; 1609 break;
1613 case Token::GTE: 1610 case Token::GTE:
1614 cc = ge; 1611 cc = ge;
1615 __ pop(r0);
1616 __ pop(r1); 1612 __ pop(r1);
1617 break; 1613 break;
1618 case Token::IN: 1614 case Token::IN:
1619 case Token::INSTANCEOF: 1615 case Token::INSTANCEOF:
1620 default: 1616 default:
1621 UNREACHABLE(); 1617 UNREACHABLE();
1622 } 1618 }
1623 1619
1624 // The comparison stub expects the smi vs. smi case to be handled 1620 // The comparison stub expects the smi vs. smi case to be handled
1625 // before it is called. 1621 // before it is called.
1626 Label slow_case; 1622 Label slow_case;
1627 __ orr(r2, r0, Operand(r1)); 1623 __ orr(r2, r0, Operand(r1));
1628 __ tst(r2, Operand(kSmiTagMask)); 1624 __ tst(r2, Operand(kSmiTagMask));
1629 __ b(ne, &slow_case); 1625 __ b(ne, &slow_case);
1630 __ cmp(r1, r0); 1626 __ cmp(r1, r0);
1631 __ b(cc, if_true); 1627 __ b(cc, if_true);
1632 __ jmp(if_false); 1628 __ jmp(if_false);
1633 1629
1634 __ bind(&slow_case); 1630 __ bind(&slow_case);
1635 CompareStub stub(cc, strict); 1631 CompareStub stub(cc, strict);
1636 __ CallStub(&stub); 1632 __ CallStub(&stub);
1637 __ tst(r0, r0); 1633 __ tst(r0, r0);
1638 __ b(cc, if_true); 1634 __ b(cc, if_true);
1639 __ jmp(if_false); 1635 __ jmp(if_false);
1640 } 1636 }
1641 } 1637 }
1642 1638
1643 // Convert the result of the comparison into one expected for this 1639 // Convert the result of the comparison into one expected for this
1644 // expression's context. 1640 // expression's context.
1645 switch (expr->context()) { 1641 Apply(expr->context(), if_true, if_false);
1646 case Expression::kUninitialized:
1647 UNREACHABLE();
1648 break;
1649
1650 case Expression::kEffect:
1651 __ bind(&done);
1652 break;
1653
1654 case Expression::kValue:
1655 __ bind(&push_true);
1656 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
1657 __ push(ip);
1658 __ jmp(&done);
1659 __ bind(&push_false);
1660 __ LoadRoot(ip, Heap::kFalseValueRootIndex);
1661 __ push(ip);
1662 __ bind(&done);
1663 break;
1664
1665 case Expression::kTest:
1666 break;
1667
1668 case Expression::kValueTest:
1669 __ bind(&push_true);
1670 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
1671 __ push(ip);
1672 __ jmp(true_label_);
1673 break;
1674
1675 case Expression::kTestValue:
1676 __ bind(&push_false);
1677 __ LoadRoot(ip, Heap::kFalseValueRootIndex);
1678 __ push(ip);
1679 __ jmp(false_label_);
1680 break;
1681 }
1682 } 1642 }
1683 1643
1684 1644
1685 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { 1645 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) {
1686 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 1646 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
1687 Apply(expr->context(), r0); 1647 Apply(expr->context(), r0);
1688 } 1648 }
1689 1649
1690 1650
1691 Register FastCodeGenerator::result_register() { return r0; } 1651 Register FastCodeGenerator::result_register() { return r0; }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1729 __ pop(result_register()); 1689 __ pop(result_register());
1730 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); 1690 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize);
1731 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. 1691 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value.
1732 __ add(pc, r1, Operand(masm_->CodeObject())); 1692 __ add(pc, r1, Operand(masm_->CodeObject()));
1733 } 1693 }
1734 1694
1735 1695
1736 #undef __ 1696 #undef __
1737 1697
1738 } } // namespace v8::internal 1698 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/ast.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698