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

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

Issue 546006: Some cleanup of the toplevel code generator:... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
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
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 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 } 195 }
196 // Check that the size of the code used for returning matches what is 196 // Check that the size of the code used for returning matches what is
197 // expected by the debugger. 197 // expected by the debugger.
198 ASSERT_EQ(Assembler::kJSReturnSequenceLength, 198 ASSERT_EQ(Assembler::kJSReturnSequenceLength,
199 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); 199 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
200 #endif 200 #endif
201 } 201 }
202 } 202 }
203 203
204 204
205 void FastCodeGenerator::Move(Expression::Context context, Register source) { 205 void FastCodeGenerator::Apply(Expression::Context context,
206 Slot* slot,
207 Register scratch) {
208 switch (context) {
209 case Expression::kUninitialized:
210 UNREACHABLE();
211 case Expression::kEffect:
212 break;
213 case Expression::kValue: {
214 MemOperand location = EmitSlotSearch(slot, scratch);
215 __ push(location);
216 break;
217 }
218 case Expression::kTest:
219 case Expression::kValueTest:
220 case Expression::kTestValue:
221 Move(scratch, slot);
222 Apply(context, scratch);
223 break;
224 }
225 }
226
227
228 void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) {
206 switch (context) { 229 switch (context) {
207 case Expression::kUninitialized: 230 case Expression::kUninitialized:
208 UNREACHABLE(); 231 UNREACHABLE();
209 case Expression::kEffect: 232 case Expression::kEffect:
210 break; 233 break;
211 case Expression::kValue: 234 case Expression::kValue:
212 __ push(source); 235 __ Push(lit->handle());
213 break; 236 break;
214 case Expression::kTest: 237 case Expression::kTest:
215 TestAndBranch(source, true_label_, false_label_); 238 case Expression::kValueTest:
239 case Expression::kTestValue:
240 __ Move(rax, lit->handle());
241 Apply(context, rax);
216 break; 242 break;
217 case Expression::kValueTest: {
218 Label discard;
219 __ push(source);
220 TestAndBranch(source, true_label_, &discard);
221 __ bind(&discard);
222 __ addq(rsp, Immediate(kPointerSize));
223 __ jmp(false_label_);
224 break;
225 }
226 case Expression::kTestValue: {
227 Label discard;
228 __ push(source);
229 TestAndBranch(source, &discard, false_label_);
230 __ bind(&discard);
231 __ addq(rsp, Immediate(kPointerSize));
232 __ jmp(true_label_);
233 break;
234 }
235 } 243 }
236 } 244 }
237 245
238 246
239 void FastCodeGenerator::MoveTOS(Expression::Context context) { 247 void FastCodeGenerator::ApplyTOS(Expression::Context context) {
240 switch (context) { 248 switch (context) {
241 case Expression::kUninitialized: 249 case Expression::kUninitialized:
242 UNREACHABLE(); 250 UNREACHABLE();
243 case Expression::kEffect: 251 case Expression::kEffect:
244 __ Drop(1); 252 __ Drop(1);
245 break; 253 break;
246 case Expression::kValue: 254 case Expression::kValue:
247 break; 255 break;
248 case Expression::kTest: 256 case Expression::kTest:
249 __ pop(rax); 257 __ pop(rax);
250 TestAndBranch(rax, true_label_, false_label_); 258 TestAndBranch(rax, true_label_, false_label_);
251 break; 259 break;
252 case Expression::kValueTest: { 260 case Expression::kValueTest: {
253 Label discard; 261 Label discard;
254 __ movq(rax, Operand(rsp, 0)); 262 __ movq(rax, Operand(rsp, 0));
255 TestAndBranch(rax, true_label_, &discard); 263 TestAndBranch(rax, true_label_, &discard);
256 __ bind(&discard); 264 __ bind(&discard);
257 __ Drop(1); 265 __ Drop(1);
258 __ jmp(false_label_); 266 __ jmp(false_label_);
267 break;
268 }
269 case Expression::kTestValue: {
270 Label discard;
271 __ movq(rax, Operand(rsp, 0));
272 TestAndBranch(rax, &discard, false_label_);
273 __ bind(&discard);
274 __ Drop(1);
275 __ jmp(true_label_);
276 }
277 }
278 }
279
280
281 void FastCodeGenerator::DropAndApply(int count,
282 Expression::Context context,
283 Register reg) {
284 ASSERT(count > 0);
285 ASSERT(!reg.is(rsp));
286 switch (context) {
287 case Expression::kUninitialized:
288 UNREACHABLE();
289 case Expression::kEffect:
290 __ Drop(count);
291 break;
292 case Expression::kValue:
293 if (count > 1) __ Drop(count - 1);
294 __ movq(Operand(rsp, 0), reg);
295 break;
296 case Expression::kTest:
297 __ Drop(count);
298 TestAndBranch(reg, true_label_, false_label_);
299 break;
300 case Expression::kValueTest: {
301 Label discard;
302 if (count > 1) __ Drop(count - 1);
303 __ movq(Operand(rsp, 0), reg);
304 TestAndBranch(reg, true_label_, &discard);
305 __ bind(&discard);
306 __ Drop(1);
307 __ jmp(false_label_);
259 break; 308 break;
260 } 309 }
261 case Expression::kTestValue: { 310 case Expression::kTestValue: {
262 Label discard; 311 Label discard;
263 __ movq(rax, Operand(rsp, 0)); 312 if (count > 1) __ Drop(count - 1);
264 TestAndBranch(rax, &discard, false_label_); 313 __ movq(Operand(rsp, 0), reg);
314 TestAndBranch(reg, &discard, false_label_);
265 __ bind(&discard); 315 __ bind(&discard);
266 __ Drop(1); 316 __ Drop(1);
267 __ jmp(true_label_); 317 __ jmp(true_label_);
318 break;
268 } 319 }
269 } 320 }
270 } 321 }
271 322
272 323
273 MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { 324 MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
274 switch (slot->type()) { 325 switch (slot->type()) {
275 case Slot::PARAMETER: 326 case Slot::PARAMETER:
276 case Slot::LOCAL: 327 case Slot::LOCAL:
277 return Operand(rbp, SlotOffset(slot)); 328 return Operand(rbp, SlotOffset(slot));
(...skipping 10 matching lines...) Expand all
288 return Operand(rax, 0); 339 return Operand(rax, 0);
289 } 340 }
290 341
291 342
292 void FastCodeGenerator::Move(Register destination, Slot* source) { 343 void FastCodeGenerator::Move(Register destination, Slot* source) {
293 MemOperand location = EmitSlotSearch(source, destination); 344 MemOperand location = EmitSlotSearch(source, destination);
294 __ movq(destination, location); 345 __ movq(destination, location);
295 } 346 }
296 347
297 348
298 void FastCodeGenerator::Move(Expression::Context context,
299 Slot* source,
300 Register scratch) {
301 switch (context) {
302 case Expression::kUninitialized:
303 UNREACHABLE();
304 case Expression::kEffect:
305 break;
306 case Expression::kValue: {
307 MemOperand location = EmitSlotSearch(source, scratch);
308 __ push(location);
309 break;
310 }
311 case Expression::kTest:
312 case Expression::kValueTest:
313 case Expression::kTestValue:
314 Move(scratch, source);
315 Move(context, scratch);
316 break;
317 }
318 }
319
320
321 void FastCodeGenerator::Move(Expression::Context context, Literal* expr) {
322 switch (context) {
323 case Expression::kUninitialized:
324 UNREACHABLE();
325 case Expression::kEffect:
326 break;
327 case Expression::kValue:
328 __ Push(expr->handle());
329 break;
330 case Expression::kTest:
331 case Expression::kValueTest:
332 case Expression::kTestValue:
333 __ Move(rax, expr->handle());
334 Move(context, rax);
335 break;
336 }
337 }
338
339
340 void FastCodeGenerator::Move(Slot* dst, 349 void FastCodeGenerator::Move(Slot* dst,
341 Register src, 350 Register src,
342 Register scratch1, 351 Register scratch1,
343 Register scratch2) { 352 Register scratch2) {
344 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. 353 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented.
345 ASSERT(!scratch1.is(src) && !scratch2.is(src)); 354 ASSERT(!scratch1.is(src) && !scratch2.is(src));
346 MemOperand location = EmitSlotSearch(dst, scratch1); 355 MemOperand location = EmitSlotSearch(dst, scratch1);
347 __ movq(location, src); 356 __ movq(location, src);
348 // Emit the write barrier code if the location is in the heap. 357 // Emit the write barrier code if the location is in the heap.
349 if (dst->type() == Slot::CONTEXT) { 358 if (dst->type() == Slot::CONTEXT) {
350 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; 359 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize;
351 __ RecordWrite(scratch1, offset, src, scratch2); 360 __ RecordWrite(scratch1, offset, src, scratch2);
352 } 361 }
353 } 362 }
354 363
355 364
356 void FastCodeGenerator::DropAndMove(Expression::Context context,
357 Register source,
358 int drop_count) {
359 ASSERT(drop_count > 0);
360 switch (context) {
361 case Expression::kUninitialized:
362 UNREACHABLE();
363 case Expression::kEffect:
364 __ addq(rsp, Immediate(drop_count * kPointerSize));
365 break;
366 case Expression::kValue:
367 if (drop_count > 1) {
368 __ addq(rsp, Immediate((drop_count - 1) * kPointerSize));
369 }
370 __ movq(Operand(rsp, 0), source);
371 break;
372 case Expression::kTest:
373 ASSERT(!source.is(rsp));
374 __ addq(rsp, Immediate(drop_count * kPointerSize));
375 TestAndBranch(source, true_label_, false_label_);
376 break;
377 case Expression::kValueTest: {
378 Label discard;
379 if (drop_count > 1) {
380 __ addq(rsp, Immediate((drop_count - 1) * kPointerSize));
381 }
382 __ movq(Operand(rsp, 0), source);
383 TestAndBranch(source, true_label_, &discard);
384 __ bind(&discard);
385 __ addq(rsp, Immediate(kPointerSize));
386 __ jmp(false_label_);
387 break;
388 }
389 case Expression::kTestValue: {
390 Label discard;
391 __ movq(Operand(rsp, 0), source);
392 TestAndBranch(source, &discard, false_label_);
393 __ bind(&discard);
394 __ addq(rsp, Immediate(kPointerSize));
395 __ jmp(true_label_);
396 break;
397 }
398 }
399 }
400
401
402 void FastCodeGenerator::TestAndBranch(Register source, 365 void FastCodeGenerator::TestAndBranch(Register source,
403 Label* true_label, 366 Label* true_label,
404 Label* false_label) { 367 Label* false_label) {
405 ASSERT_NE(NULL, true_label); 368 ASSERT_NE(NULL, true_label);
406 ASSERT_NE(NULL, false_label); 369 ASSERT_NE(NULL, false_label);
407 // Use the shared ToBoolean stub to compile the value in the register into 370 // Use the shared ToBoolean stub to compile the value in the register into
408 // control flow to the code generator's true and false labels. Perform 371 // control flow to the code generator's true and false labels. Perform
409 // the fast checks assumed by the stub. 372 // the fast checks assumed by the stub.
410 373
411 // The undefined value is false. 374 // The undefined value is false.
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
521 } 484 }
522 485
523 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 486 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
524 __ call(ic, RelocInfo::CODE_TARGET); 487 __ call(ic, RelocInfo::CODE_TARGET);
525 488
526 // Absence of a test rax instruction following the call 489 // Absence of a test rax instruction following the call
527 // indicates that none of the load was inlined. 490 // indicates that none of the load was inlined.
528 491
529 // Value in rax is ignored (declarations are statements). Receiver 492 // Value in rax is ignored (declarations are statements). Receiver
530 // and key on stack are discarded. 493 // and key on stack are discarded.
531 __ addq(rsp, Immediate(2 * kPointerSize)); 494 __ Drop(2);
532 } 495 }
533 } 496 }
534 } 497 }
535 498
536 499
537 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 500 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
538 // Call the runtime to declare the globals. 501 // Call the runtime to declare the globals.
539 __ push(rsi); // The context is the first argument. 502 __ push(rsi); // The context is the first argument.
540 __ Push(pairs); 503 __ Push(pairs);
541 __ Push(Smi::FromInt(is_eval_ ? 1 : 0)); 504 __ Push(Smi::FromInt(is_eval_ ? 1 : 0));
542 __ CallRuntime(Runtime::kDeclareGlobals, 3); 505 __ CallRuntime(Runtime::kDeclareGlobals, 3);
543 // Return value is ignored. 506 // Return value is ignored.
544 } 507 }
545 508
546 509
547 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { 510 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
548 Comment cmnt(masm_, "[ FunctionLiteral"); 511 Comment cmnt(masm_, "[ FunctionLiteral");
549 512
550 // Build the function boilerplate and instantiate it. 513 // Build the function boilerplate and instantiate it.
551 Handle<JSFunction> boilerplate = 514 Handle<JSFunction> boilerplate =
552 Compiler::BuildBoilerplate(expr, script_, this); 515 Compiler::BuildBoilerplate(expr, script_, this);
553 if (HasStackOverflow()) return; 516 if (HasStackOverflow()) return;
554 517
555 ASSERT(boilerplate->IsBoilerplate()); 518 ASSERT(boilerplate->IsBoilerplate());
556 519
557 // Create a new closure. 520 // Create a new closure.
558 __ push(rsi); 521 __ push(rsi);
559 __ Push(boilerplate); 522 __ Push(boilerplate);
560 __ CallRuntime(Runtime::kNewClosure, 2); 523 __ CallRuntime(Runtime::kNewClosure, 2);
561 Move(expr->context(), rax); 524 Apply(expr->context(), rax);
562 } 525 }
563 526
564 527
565 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 528 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
566 Comment cmnt(masm_, "[ VariableProxy"); 529 Comment cmnt(masm_, "[ VariableProxy");
567 EmitVariableLoad(expr->var(), expr->context()); 530 EmitVariableLoad(expr->var(), expr->context());
568 } 531 }
569 532
570 533
571 void FastCodeGenerator::EmitVariableLoad(Variable* var, 534 void FastCodeGenerator::EmitVariableLoad(Variable* var,
572 Expression::Context context) { 535 Expression::Context context) {
573 Expression* rewrite = var->rewrite(); 536 Expression* rewrite = var->rewrite();
574 if (rewrite == NULL) { 537 if (rewrite == NULL) {
575 ASSERT(var->is_global()); 538 ASSERT(var->is_global());
576 Comment cmnt(masm_, "Global variable"); 539 Comment cmnt(masm_, "Global variable");
577 // Use inline caching. Variable name is passed in rcx and the global 540 // Use inline caching. Variable name is passed in rcx and the global
578 // object on the stack. 541 // object on the stack.
579 __ push(CodeGenerator::GlobalObject()); 542 __ push(CodeGenerator::GlobalObject());
580 __ Move(rcx, var->name()); 543 __ Move(rcx, var->name());
581 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 544 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
582 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); 545 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
583 // A test rax instruction following the call is used by the IC to 546 // A test rax instruction following the call is used by the IC to
584 // indicate that the inobject property case was inlined. Ensure there 547 // indicate that the inobject property case was inlined. Ensure there
585 // is no test rax instruction here. 548 // is no test rax instruction here.
586 __ nop(); 549 __ nop();
587 550
588 DropAndMove(context, rax); 551 DropAndApply(1, context, rax);
589 } else if (rewrite->AsSlot() != NULL) { 552 } else if (rewrite->AsSlot() != NULL) {
590 Slot* slot = rewrite->AsSlot(); 553 Slot* slot = rewrite->AsSlot();
591 if (FLAG_debug_code) { 554 if (FLAG_debug_code) {
592 switch (slot->type()) { 555 switch (slot->type()) {
593 case Slot::LOCAL: 556 case Slot::LOCAL:
594 case Slot::PARAMETER: { 557 case Slot::PARAMETER: {
595 Comment cmnt(masm_, "Stack slot"); 558 Comment cmnt(masm_, "Stack slot");
596 break; 559 break;
597 } 560 }
598 case Slot::CONTEXT: { 561 case Slot::CONTEXT: {
599 Comment cmnt(masm_, "Context slot"); 562 Comment cmnt(masm_, "Context slot");
600 break; 563 break;
601 } 564 }
602 case Slot::LOOKUP: 565 case Slot::LOOKUP:
603 UNIMPLEMENTED(); 566 UNIMPLEMENTED();
604 break; 567 break;
605 } 568 }
606 } 569 }
607 Move(context, slot, rax); 570 Apply(context, slot, rax);
608 } else { 571 } else {
609 // A variable has been rewritten into an explicit access to 572 Comment cmnt(masm_, "Variable rewritten to property");
610 // an object property. 573 // A variable has been rewritten into an explicit access to an object
574 // property.
611 Property* property = rewrite->AsProperty(); 575 Property* property = rewrite->AsProperty();
612 ASSERT_NOT_NULL(property); 576 ASSERT_NOT_NULL(property);
613 577
614 // Currently the only parameter expressions that can occur are 578 // The only property expressions that can occur are of the form
615 // on the form "slot[literal]". 579 // "slot[literal]".
616 580
617 // Check that the object is in a slot. 581 // Assert that the object is in a slot.
618 Variable* object = property->obj()->AsVariableProxy()->AsVariable(); 582 Variable* object = property->obj()->AsVariableProxy()->AsVariable();
619 ASSERT_NOT_NULL(object); 583 ASSERT_NOT_NULL(object);
620 Slot* object_slot = object->slot(); 584 Slot* object_slot = object->slot();
621 ASSERT_NOT_NULL(object_slot); 585 ASSERT_NOT_NULL(object_slot);
622 586
623 // Load the object. 587 // Load the object.
624 Move(Expression::kValue, object_slot, rax); 588 MemOperand object_loc = EmitSlotSearch(object_slot, rax);
589 __ push(object_loc);
625 590
626 // Check that the key is a smi. 591 // Assert that the key is a smi.
627 Literal* key_literal = property->key()->AsLiteral(); 592 Literal* key_literal = property->key()->AsLiteral();
628 ASSERT_NOT_NULL(key_literal); 593 ASSERT_NOT_NULL(key_literal);
629 ASSERT(key_literal->handle()->IsSmi()); 594 ASSERT(key_literal->handle()->IsSmi());
630 595
631 // Load the key. 596 // Load the key.
632 Move(Expression::kValue, key_literal); 597 __ Push(key_literal->handle());
633 598
634 // Do a KEYED property load. 599 // Do a keyed property load.
635 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 600 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
636 __ call(ic, RelocInfo::CODE_TARGET); 601 __ call(ic, RelocInfo::CODE_TARGET);
637 // Notice: We must not have a "test rax, ..." instruction after 602 // Notice: We must not have a "test rax, ..." instruction after the
638 // the call. It is treated specially by the LoadIC code. 603 // call. It is treated specially by the LoadIC code.
639 604
640 // Drop key and object left on the stack by IC, and push the result. 605 // Drop key and object left on the stack by IC, and push the result.
641 DropAndMove(context, rax, 2); 606 DropAndApply(2, context, rax);
642 } 607 }
643 } 608 }
644 609
645 610
646 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 611 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
647 Comment cmnt(masm_, "[ RegExpLiteral"); 612 Comment cmnt(masm_, "[ RegExpLiteral");
648 Label done; 613 Label done;
649 // Registers will be used as follows: 614 // Registers will be used as follows:
650 // rdi = JS function. 615 // rdi = JS function.
651 // rbx = literals array. 616 // rbx = literals array.
652 // rax = regexp literal. 617 // rax = regexp literal.
653 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 618 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
654 __ movq(rbx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); 619 __ movq(rbx, FieldOperand(rdi, JSFunction::kLiteralsOffset));
655 int literal_offset = 620 int literal_offset =
656 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; 621 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
657 __ movq(rax, FieldOperand(rbx, literal_offset)); 622 __ movq(rax, FieldOperand(rbx, literal_offset));
658 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 623 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
659 __ j(not_equal, &done); 624 __ j(not_equal, &done);
660 // Create regexp literal using runtime function 625 // Create regexp literal using runtime function
661 // Result will be in rax. 626 // Result will be in rax.
662 __ push(rbx); 627 __ push(rbx);
663 __ Push(Smi::FromInt(expr->literal_index())); 628 __ Push(Smi::FromInt(expr->literal_index()));
664 __ Push(expr->pattern()); 629 __ Push(expr->pattern());
665 __ Push(expr->flags()); 630 __ Push(expr->flags());
666 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 631 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
667 // Label done: 632 // Label done:
668 __ bind(&done); 633 __ bind(&done);
669 Move(expr->context(), rax); 634 Apply(expr->context(), rax);
670 } 635 }
671 636
672 637
673 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 638 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
674 Comment cmnt(masm_, "[ ObjectLiteral"); 639 Comment cmnt(masm_, "[ ObjectLiteral");
675 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 640 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
676 __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset)); 641 __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset));
677 __ Push(Smi::FromInt(expr->literal_index())); 642 __ Push(Smi::FromInt(expr->literal_index()));
678 __ Push(expr->constant_properties()); 643 __ Push(expr->constant_properties());
679 if (expr->depth() > 1) { 644 if (expr->depth() > 1) {
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
735 __ CallRuntime(Runtime::kDefineAccessor, 4); 700 __ CallRuntime(Runtime::kDefineAccessor, 4);
736 __ movq(rax, Operand(rsp, 0)); // Restore result into rax. 701 __ movq(rax, Operand(rsp, 0)); // Restore result into rax.
737 break; 702 break;
738 default: UNREACHABLE(); 703 default: UNREACHABLE();
739 } 704 }
740 } 705 }
741 switch (expr->context()) { 706 switch (expr->context()) {
742 case Expression::kUninitialized: 707 case Expression::kUninitialized:
743 UNREACHABLE(); 708 UNREACHABLE();
744 case Expression::kEffect: 709 case Expression::kEffect:
745 if (result_saved) __ addq(rsp, Immediate(kPointerSize)); 710 if (result_saved) __ Drop(1);
746 break; 711 break;
747 case Expression::kValue: 712 case Expression::kValue:
748 if (!result_saved) __ push(rax); 713 if (!result_saved) __ push(rax);
749 break; 714 break;
750 case Expression::kTest: 715 case Expression::kTest:
751 if (result_saved) __ pop(rax); 716 if (result_saved) __ pop(rax);
752 TestAndBranch(rax, true_label_, false_label_); 717 TestAndBranch(rax, true_label_, false_label_);
753 break; 718 break;
754 case Expression::kValueTest: { 719 case Expression::kValueTest: {
755 Label discard; 720 Label discard;
756 if (!result_saved) __ push(rax); 721 if (!result_saved) __ push(rax);
757 TestAndBranch(rax, true_label_, &discard); 722 TestAndBranch(rax, true_label_, &discard);
758 __ bind(&discard); 723 __ bind(&discard);
759 __ addq(rsp, Immediate(kPointerSize)); 724 __ Drop(1);
760 __ jmp(false_label_); 725 __ jmp(false_label_);
761 break; 726 break;
762 } 727 }
763 case Expression::kTestValue: { 728 case Expression::kTestValue: {
764 Label discard; 729 Label discard;
765 if (!result_saved) __ push(rax); 730 if (!result_saved) __ push(rax);
766 TestAndBranch(rax, &discard, false_label_); 731 TestAndBranch(rax, &discard, false_label_);
767 __ bind(&discard); 732 __ bind(&discard);
768 __ addq(rsp, Immediate(kPointerSize)); 733 __ Drop(1);
769 __ jmp(true_label_); 734 __ jmp(true_label_);
770 break; 735 break;
771 } 736 }
772 } 737 }
773 } 738 }
774 739
775 740
776 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 741 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
777 Comment cmnt(masm_, "[ ArrayLiteral"); 742 Comment cmnt(masm_, "[ ArrayLiteral");
778 __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 743 __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
814 __ movq(FieldOperand(rbx, offset), rax); 779 __ movq(FieldOperand(rbx, offset), rax);
815 780
816 // Update the write barrier for the array store. 781 // Update the write barrier for the array store.
817 __ RecordWrite(rbx, offset, rax, rcx); 782 __ RecordWrite(rbx, offset, rax, rcx);
818 } 783 }
819 784
820 switch (expr->context()) { 785 switch (expr->context()) {
821 case Expression::kUninitialized: 786 case Expression::kUninitialized:
822 UNREACHABLE(); 787 UNREACHABLE();
823 case Expression::kEffect: 788 case Expression::kEffect:
824 if (result_saved) __ addq(rsp, Immediate(kPointerSize)); 789 if (result_saved) __ Drop(1);
825 break; 790 break;
826 case Expression::kValue: 791 case Expression::kValue:
827 if (!result_saved) __ push(rax); 792 if (!result_saved) __ push(rax);
828 break; 793 break;
829 case Expression::kTest: 794 case Expression::kTest:
830 if (result_saved) __ pop(rax); 795 if (result_saved) __ pop(rax);
831 TestAndBranch(rax, true_label_, false_label_); 796 TestAndBranch(rax, true_label_, false_label_);
832 break; 797 break;
833 case Expression::kValueTest: { 798 case Expression::kValueTest: {
834 Label discard; 799 Label discard;
835 if (!result_saved) __ push(rax); 800 if (!result_saved) __ push(rax);
836 TestAndBranch(rax, true_label_, &discard); 801 TestAndBranch(rax, true_label_, &discard);
837 __ bind(&discard); 802 __ bind(&discard);
838 __ addq(rsp, Immediate(kPointerSize)); 803 __ Drop(1);
839 __ jmp(false_label_); 804 __ jmp(false_label_);
840 break; 805 break;
841 } 806 }
842 case Expression::kTestValue: { 807 case Expression::kTestValue: {
843 Label discard; 808 Label discard;
844 if (!result_saved) __ push(rax); 809 if (!result_saved) __ push(rax);
845 TestAndBranch(rax, &discard, false_label_); 810 TestAndBranch(rax, &discard, false_label_);
846 __ bind(&discard); 811 __ bind(&discard);
847 __ addq(rsp, Immediate(kPointerSize)); 812 __ Drop(1);
848 __ jmp(true_label_); 813 __ jmp(true_label_);
849 break; 814 break;
850 } 815 }
851 } 816 }
852 } 817 }
853 818
854 819
855 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop, 820 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop,
856 Expression::Context context) { 821 Expression::Context context) {
857 SetSourcePosition(prop->position()); 822 SetSourcePosition(prop->position());
858 Literal* key = prop->key()->AsLiteral(); 823 Literal* key = prop->key()->AsLiteral();
859 __ Move(rcx, key->handle()); 824 __ Move(rcx, key->handle());
860 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 825 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
861 __ Call(ic, RelocInfo::CODE_TARGET); 826 __ Call(ic, RelocInfo::CODE_TARGET);
862 Move(context, rax); 827 Apply(context, rax);
863 } 828 }
864 829
865 830
866 void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop, 831 void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop,
867 Expression::Context context) { 832 Expression::Context context) {
868 SetSourcePosition(prop->position()); 833 SetSourcePosition(prop->position());
869 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 834 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
870 __ Call(ic, RelocInfo::CODE_TARGET); 835 __ Call(ic, RelocInfo::CODE_TARGET);
871 Move(context, rax); 836 Apply(context, rax);
872 } 837 }
873 838
874 839
875 void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op, 840 void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op,
876 Expression::Context context) { 841 Expression::Context context) {
877 GenericBinaryOpStub stub(op, 842 GenericBinaryOpStub stub(op,
878 NO_OVERWRITE, 843 NO_OVERWRITE,
879 NO_GENERIC_BINARY_FLAGS); 844 NO_GENERIC_BINARY_FLAGS);
880 __ CallStub(&stub); 845 __ CallStub(&stub);
881 Move(context, rax); 846 Apply(context, rax);
882 } 847 }
883 848
884 849
885 void FastCodeGenerator::EmitVariableAssignment(Variable* var, 850 void FastCodeGenerator::EmitVariableAssignment(Variable* var,
886 Expression::Context context) { 851 Expression::Context context) {
887 ASSERT(var != NULL); 852 ASSERT(var != NULL);
888 ASSERT(var->is_global() || var->slot() != NULL); 853 ASSERT(var->is_global() || var->slot() != NULL);
889 if (var->is_global()) { 854 if (var->is_global()) {
890 // Assignment to a global variable. Use inline caching for the 855 // Assignment to a global variable. Use inline caching for the
891 // assignment. Right-hand-side value is passed in rax, variable name in 856 // assignment. Right-hand-side value is passed in rax, variable name in
892 // rcx, and the global object on the stack. 857 // rcx, and the global object on the stack.
893 __ pop(rax); 858 __ pop(rax);
894 __ Move(rcx, var->name()); 859 __ Move(rcx, var->name());
895 __ push(CodeGenerator::GlobalObject()); 860 __ push(CodeGenerator::GlobalObject());
896 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 861 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
897 __ Call(ic, RelocInfo::CODE_TARGET); 862 __ Call(ic, RelocInfo::CODE_TARGET);
898 // Overwrite the global object on the stack with the result if needed. 863 // Overwrite the global object on the stack with the result if needed.
899 DropAndMove(context, rax); 864 DropAndApply(1, context, rax);
900 865
901 } else if (var->slot() != NULL) { 866 } else if (var->slot() != NULL) {
902 Slot* slot = var->slot(); 867 Slot* slot = var->slot();
903 switch (slot->type()) { 868 switch (slot->type()) {
904 case Slot::LOCAL: 869 case Slot::LOCAL:
905 case Slot::PARAMETER: { 870 case Slot::PARAMETER: {
906 Operand target = Operand(rbp, SlotOffset(slot)); 871 Operand target = Operand(rbp, SlotOffset(slot));
907 switch (context) { 872 switch (context) {
908 case Expression::kUninitialized: 873 case Expression::kUninitialized:
909 UNREACHABLE(); 874 UNREACHABLE();
(...skipping 11 matching lines...) Expand all
921 __ pop(rax); 886 __ pop(rax);
922 __ movq(target, rax); 887 __ movq(target, rax);
923 TestAndBranch(rax, true_label_, false_label_); 888 TestAndBranch(rax, true_label_, false_label_);
924 break; 889 break;
925 case Expression::kValueTest: { 890 case Expression::kValueTest: {
926 Label discard; 891 Label discard;
927 __ movq(rax, Operand(rsp, 0)); 892 __ movq(rax, Operand(rsp, 0));
928 __ movq(target, rax); 893 __ movq(target, rax);
929 TestAndBranch(rax, true_label_, &discard); 894 TestAndBranch(rax, true_label_, &discard);
930 __ bind(&discard); 895 __ bind(&discard);
931 __ addq(rsp, Immediate(kPointerSize)); 896 __ Drop(1);
932 __ jmp(false_label_); 897 __ jmp(false_label_);
933 break; 898 break;
934 } 899 }
935 case Expression::kTestValue: { 900 case Expression::kTestValue: {
936 Label discard; 901 Label discard;
937 __ movq(rax, Operand(rsp, 0)); 902 __ movq(rax, Operand(rsp, 0));
938 __ movq(target, rax); 903 __ movq(target, rax);
939 TestAndBranch(rax, &discard, false_label_); 904 TestAndBranch(rax, &discard, false_label_);
940 __ bind(&discard); 905 __ bind(&discard);
941 __ addq(rsp, Immediate(kPointerSize)); 906 __ Drop(1);
942 __ jmp(true_label_); 907 __ jmp(true_label_);
943 break; 908 break;
944 } 909 }
945 } 910 }
946 break; 911 break;
947 } 912 }
948 913
949 case Slot::CONTEXT: { 914 case Slot::CONTEXT: {
950 MemOperand target = EmitSlotSearch(slot, rcx); 915 MemOperand target = EmitSlotSearch(slot, rcx);
951 __ pop(rax); 916 __ pop(rax);
952 __ movq(target, rax); 917 __ movq(target, rax);
953 918
954 // RecordWrite may destroy all its register arguments. 919 // RecordWrite may destroy all its register arguments.
955 if (context == Expression::kValue) { 920 if (context == Expression::kValue) {
956 __ push(rax); 921 __ push(rax);
957 } else if (context != Expression::kEffect) { 922 } else if (context != Expression::kEffect) {
958 __ movq(rdx, rax); 923 __ movq(rdx, rax);
959 } 924 }
960 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; 925 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;
961 __ RecordWrite(rcx, offset, rax, rbx); 926 __ RecordWrite(rcx, offset, rax, rbx);
962 if (context != Expression::kEffect && 927 if (context != Expression::kEffect && context != Expression::kValue) {
963 context != Expression::kValue) { 928 Apply(context, rdx);
964 Move(context, rdx);
965 } 929 }
966 break; 930 break;
967 } 931 }
968 932
969 case Slot::LOOKUP: 933 case Slot::LOOKUP:
970 UNREACHABLE(); 934 UNREACHABLE();
971 break; 935 break;
972 } 936 }
973 } else { 937 } else {
974 // Variables rewritten as properties are not treated as variables in 938 // Variables rewritten as properties are not treated as variables in
(...skipping 23 matching lines...) Expand all
998 __ Call(ic, RelocInfo::CODE_TARGET); 962 __ Call(ic, RelocInfo::CODE_TARGET);
999 963
1000 // If the assignment ends an initialization block, revert to fast case. 964 // If the assignment ends an initialization block, revert to fast case.
1001 if (expr->ends_initialization_block()) { 965 if (expr->ends_initialization_block()) {
1002 __ push(rax); // Result of assignment, saved even if not needed. 966 __ push(rax); // Result of assignment, saved even if not needed.
1003 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. 967 __ push(Operand(rsp, kPointerSize)); // Receiver is under value.
1004 __ CallRuntime(Runtime::kToFastProperties, 1); 968 __ CallRuntime(Runtime::kToFastProperties, 1);
1005 __ pop(rax); 969 __ pop(rax);
1006 } 970 }
1007 971
1008 DropAndMove(expr->context(), rax); 972 DropAndApply(1, expr->context(), rax);
1009 } 973 }
1010 974
1011 975
1012 void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 976 void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
1013 // Assignment to a property, using a keyed store IC. 977 // Assignment to a property, using a keyed store IC.
1014 978
1015 // If the assignment starts a block of assignments to the same object, 979 // If the assignment starts a block of assignments to the same object,
1016 // change to slow case to avoid the quadratic behavior of repeatedly 980 // change to slow case to avoid the quadratic behavior of repeatedly
1017 // adding fast properties. 981 // adding fast properties.
1018 if (expr->starts_initialization_block()) { 982 if (expr->starts_initialization_block()) {
(...skipping 12 matching lines...) Expand all
1031 // If the assignment ends an initialization block, revert to fast case. 995 // If the assignment ends an initialization block, revert to fast case.
1032 if (expr->ends_initialization_block()) { 996 if (expr->ends_initialization_block()) {
1033 __ push(rax); // Result of assignment, saved even if not needed. 997 __ push(rax); // Result of assignment, saved even if not needed.
1034 // Reciever is under the key and value. 998 // Reciever is under the key and value.
1035 __ push(Operand(rsp, 2 * kPointerSize)); 999 __ push(Operand(rsp, 2 * kPointerSize));
1036 __ CallRuntime(Runtime::kToFastProperties, 1); 1000 __ CallRuntime(Runtime::kToFastProperties, 1);
1037 __ pop(rax); 1001 __ pop(rax);
1038 } 1002 }
1039 1003
1040 // Receiver and key are still on stack. 1004 // Receiver and key are still on stack.
1041 __ addq(rsp, Immediate(2 * kPointerSize)); 1005 DropAndApply(2, expr->context(), rax);
1042 Move(expr->context(), rax);
1043 } 1006 }
1044 1007
1045 1008
1046 void FastCodeGenerator::VisitProperty(Property* expr) { 1009 void FastCodeGenerator::VisitProperty(Property* expr) {
1047 Comment cmnt(masm_, "[ Property"); 1010 Comment cmnt(masm_, "[ Property");
1048 Expression* key = expr->key(); 1011 Expression* key = expr->key();
1049 uint32_t dummy;
1050 1012
1051 // Record the source position for the property load. 1013 // Record the source position for the property load.
1052 SetSourcePosition(expr->position()); 1014 SetSourcePosition(expr->position());
1053 1015
1054 // Evaluate receiver. 1016 // Evaluate receiver.
1055 Visit(expr->obj()); 1017 Visit(expr->obj());
1056 1018
1057 1019 if (key->IsPropertyName()) {
1058 if (key->AsLiteral() != NULL && key->AsLiteral()->handle()->IsSymbol() && 1020 // Do a named property load. The IC expects the property name in rcx
1059 !String::cast(*(key->AsLiteral()->handle()))->AsArrayIndex(&dummy)) { 1021 // and the receiver on the stack.
1060 // Do a NAMED property load.
1061 // The IC expects the property name in rcx and the receiver on the stack.
1062 __ Move(rcx, key->AsLiteral()->handle()); 1022 __ Move(rcx, key->AsLiteral()->handle());
1063 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 1023 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
1064 __ call(ic, RelocInfo::CODE_TARGET); 1024 __ call(ic, RelocInfo::CODE_TARGET);
1065 // By emitting a nop we make sure that we do not have a "test rax,..." 1025 // By emitting a nop we make sure that we do not have a "test rax,..."
1066 // instruction after the call it is treated specially by the LoadIC code. 1026 // instruction after the call it is treated specially by the LoadIC code.
1067 __ nop(); 1027 __ nop();
1028 DropAndApply(1, expr->context(), rax);
1068 } else { 1029 } else {
1069 // Do a KEYED property load. 1030 // Do a keyed property load.
1070 Visit(expr->key()); 1031 Visit(expr->key());
1071 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 1032 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1072 __ call(ic, RelocInfo::CODE_TARGET); 1033 __ call(ic, RelocInfo::CODE_TARGET);
1073 // Notice: We must not have a "test rax, ..." instruction after 1034 // Notice: We must not have a "test rax, ..." instruction after the
1074 // the call. It is treated specially by the LoadIC code. 1035 // call. It is treated specially by the LoadIC code.
1075 1036 __ nop();
1076 // Drop key left on the stack by IC. 1037 // Drop key and receiver left on the stack by IC.
1077 __ addq(rsp, Immediate(kPointerSize)); 1038 DropAndApply(2, expr->context(), rax);
1078 } 1039 }
1079 DropAndMove(expr->context(), rax);
1080 } 1040 }
1081 1041
1082 1042
1083 void FastCodeGenerator::EmitCallWithIC(Call* expr, 1043 void FastCodeGenerator::EmitCallWithIC(Call* expr,
1084 Handle<Object> ignored, 1044 Handle<Object> ignored,
1085 RelocInfo::Mode mode) { 1045 RelocInfo::Mode mode) {
1086 // Code common for calls using the IC. 1046 // Code common for calls using the IC.
1087 ZoneList<Expression*>* args = expr->arguments(); 1047 ZoneList<Expression*>* args = expr->arguments();
1088 int arg_count = args->length(); 1048 int arg_count = args->length();
1089 for (int i = 0; i < arg_count; i++) { 1049 for (int i = 0; i < arg_count; i++) {
1090 Visit(args->at(i)); 1050 Visit(args->at(i));
1091 ASSERT_EQ(Expression::kValue, args->at(i)->context()); 1051 ASSERT_EQ(Expression::kValue, args->at(i)->context());
1092 } 1052 }
1093 // Record source position for debugger. 1053 // Record source position for debugger.
1094 SetSourcePosition(expr->position()); 1054 SetSourcePosition(expr->position());
1095 // Call the IC initialization code. 1055 // Call the IC initialization code.
1096 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, 1056 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
1097 NOT_IN_LOOP); 1057 NOT_IN_LOOP);
1098 __ call(ic, mode); 1058 __ call(ic, mode);
1099 // Restore context register. 1059 // Restore context register.
1100 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1060 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1101 // Discard the function left on TOS. 1061 // Discard the function left on TOS.
1102 DropAndMove(expr->context(), rax); 1062 DropAndApply(1, expr->context(), rax);
1103 } 1063 }
1104 1064
1105 1065
1106 void FastCodeGenerator::EmitCallWithStub(Call* expr) { 1066 void FastCodeGenerator::EmitCallWithStub(Call* expr) {
1107 // Code common for calls using the call stub. 1067 // Code common for calls using the call stub.
1108 ZoneList<Expression*>* args = expr->arguments(); 1068 ZoneList<Expression*>* args = expr->arguments();
1109 int arg_count = args->length(); 1069 int arg_count = args->length();
1110 for (int i = 0; i < arg_count; i++) { 1070 for (int i = 0; i < arg_count; i++) {
1111 Visit(args->at(i)); 1071 Visit(args->at(i));
1112 } 1072 }
1113 // Record source position for debugger. 1073 // Record source position for debugger.
1114 SetSourcePosition(expr->position()); 1074 SetSourcePosition(expr->position());
1115 CallFunctionStub stub(arg_count, NOT_IN_LOOP); 1075 CallFunctionStub stub(arg_count, NOT_IN_LOOP);
1116 __ CallStub(&stub); 1076 __ CallStub(&stub);
1117 // Restore context register. 1077 // Restore context register.
1118 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1078 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1119 // Discard the function left on TOS. 1079 // Discard the function left on TOS.
1120 DropAndMove(expr->context(), rax); 1080 DropAndApply(1, expr->context(), rax);
1121 } 1081 }
1122 1082
1123 1083
1124 void FastCodeGenerator::VisitCall(Call* expr) { 1084 void FastCodeGenerator::VisitCall(Call* expr) {
1125 Comment cmnt(masm_, "[ Call"); 1085 Comment cmnt(masm_, "[ Call");
1126 Expression* fun = expr->expression(); 1086 Expression* fun = expr->expression();
1127 Variable* var = fun->AsVariableProxy()->AsVariable(); 1087 Variable* var = fun->AsVariableProxy()->AsVariable();
1128 1088
1129 if (var != NULL && var->is_possibly_eval()) { 1089 if (var != NULL && var->is_possibly_eval()) {
1130 // Call to the identifier 'eval'. 1090 // Call to the identifier 'eval'.
(...skipping 23 matching lines...) Expand all
1154 Visit(prop->obj()); 1114 Visit(prop->obj());
1155 Visit(prop->key()); 1115 Visit(prop->key());
1156 // Record source code position for IC call. 1116 // Record source code position for IC call.
1157 SetSourcePosition(prop->position()); 1117 SetSourcePosition(prop->position());
1158 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 1118 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1159 __ call(ic, RelocInfo::CODE_TARGET); 1119 __ call(ic, RelocInfo::CODE_TARGET);
1160 // By emitting a nop we make sure that we do not have a "test rax,..." 1120 // By emitting a nop we make sure that we do not have a "test rax,..."
1161 // instruction after the call it is treated specially by the LoadIC code. 1121 // instruction after the call it is treated specially by the LoadIC code.
1162 __ nop(); 1122 __ nop();
1163 // Drop key left on the stack by IC. 1123 // Drop key left on the stack by IC.
1164 __ addq(rsp, Immediate(kPointerSize)); 1124 __ Drop(1);
1165 // Pop receiver. 1125 // Pop receiver.
1166 __ pop(rbx); 1126 __ pop(rbx);
1167 // Push result (function). 1127 // Push result (function).
1168 __ push(rax); 1128 __ push(rax);
1169 // Push receiver object on stack. 1129 // Push receiver object on stack.
1170 if (prop->is_synthetic()) { 1130 if (prop->is_synthetic()) {
1171 __ push(CodeGenerator::GlobalObject()); 1131 __ push(CodeGenerator::GlobalObject());
1172 } else { 1132 } else {
1173 __ push(rbx); 1133 __ push(rbx);
1174 } 1134 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1223 1183
1224 // Load function, arg_count into rdi and rax. 1184 // Load function, arg_count into rdi and rax.
1225 __ Set(rax, arg_count); 1185 __ Set(rax, arg_count);
1226 // Function is in rsp[arg_count + 1]. 1186 // Function is in rsp[arg_count + 1].
1227 __ movq(rdi, Operand(rsp, rax, times_pointer_size, kPointerSize)); 1187 __ movq(rdi, Operand(rsp, rax, times_pointer_size, kPointerSize));
1228 1188
1229 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); 1189 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall));
1230 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); 1190 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL);
1231 1191
1232 // Replace function on TOS with result in rax, or pop it. 1192 // Replace function on TOS with result in rax, or pop it.
1233 DropAndMove(expr->context(), rax); 1193 DropAndApply(1, expr->context(), rax);
1234 } 1194 }
1235 1195
1236 1196
1237 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 1197 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
1238 Comment cmnt(masm_, "[ CallRuntime"); 1198 Comment cmnt(masm_, "[ CallRuntime");
1239 ZoneList<Expression*>* args = expr->arguments(); 1199 ZoneList<Expression*>* args = expr->arguments();
1240 1200
1241 if (expr->is_jsruntime()) { 1201 if (expr->is_jsruntime()) {
1242 // Prepare for calling JS runtime function. 1202 // Prepare for calling JS runtime function.
1243 __ Push(expr->name()); 1203 __ Push(expr->name());
1244 __ movq(rax, CodeGenerator::GlobalObject()); 1204 __ movq(rax, CodeGenerator::GlobalObject());
1245 __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset)); 1205 __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset));
1246 } 1206 }
1247 1207
1248 // Push the arguments ("left-to-right"). 1208 // Push the arguments ("left-to-right").
1249 int arg_count = args->length(); 1209 int arg_count = args->length();
1250 for (int i = 0; i < arg_count; i++) { 1210 for (int i = 0; i < arg_count; i++) {
1251 Visit(args->at(i)); 1211 Visit(args->at(i));
1252 ASSERT_EQ(Expression::kValue, args->at(i)->context()); 1212 ASSERT_EQ(Expression::kValue, args->at(i)->context());
1253 } 1213 }
1254 1214
1255 if (expr->is_jsruntime()) { 1215 if (expr->is_jsruntime()) {
1256 // Call the JS runtime function. 1216 // Call the JS runtime function.
1257 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, 1217 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
1258 NOT_IN_LOOP); 1218 NOT_IN_LOOP);
1259 __ call(ic, RelocInfo::CODE_TARGET); 1219 __ call(ic, RelocInfo::CODE_TARGET);
1260 // Restore context register. 1220 // Restore context register.
1261 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1221 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1262 // Discard the function left on TOS. 1222 // Discard the function left on TOS.
1263 DropAndMove(expr->context(), rax); 1223 DropAndApply(1, expr->context(), rax);
1264 } else { 1224 } else {
1265 __ CallRuntime(expr->function(), arg_count); 1225 __ CallRuntime(expr->function(), arg_count);
1266 Move(expr->context(), rax); 1226 Apply(expr->context(), rax);
1267 } 1227 }
1268 } 1228 }
1269 1229
1270 1230
1271 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 1231 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
1272 switch (expr->op()) { 1232 switch (expr->op()) {
1273 case Token::VOID: { 1233 case Token::VOID: {
1274 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); 1234 Comment cmnt(masm_, "[ UnaryOperation (VOID)");
1275 Visit(expr->expression()); 1235 Visit(expr->expression());
1276 ASSERT_EQ(Expression::kEffect, expr->expression()->context()); 1236 ASSERT_EQ(Expression::kEffect, expr->expression()->context());
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
1379 __ push(rsi); 1339 __ push(rsi);
1380 __ Push(proxy->name()); 1340 __ Push(proxy->name());
1381 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 1341 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
1382 __ push(rax); 1342 __ push(rax);
1383 } else { 1343 } else {
1384 // This expression cannot throw a reference error at the top level. 1344 // This expression cannot throw a reference error at the top level.
1385 Visit(expr->expression()); 1345 Visit(expr->expression());
1386 } 1346 }
1387 1347
1388 __ CallRuntime(Runtime::kTypeof, 1); 1348 __ CallRuntime(Runtime::kTypeof, 1);
1389 Move(expr->context(), rax); 1349 Apply(expr->context(), rax);
1390 break; 1350 break;
1391 } 1351 }
1392 1352
1393 default: 1353 default:
1394 UNREACHABLE(); 1354 UNREACHABLE();
1395 } 1355 }
1396 } 1356 }
1397 1357
1398 1358
1399 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { 1359 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
1479 // Store the value returned in rax. 1439 // Store the value returned in rax.
1480 switch (assign_type) { 1440 switch (assign_type) {
1481 case VARIABLE: 1441 case VARIABLE:
1482 __ push(rax); 1442 __ push(rax);
1483 if (expr->is_postfix()) { 1443 if (expr->is_postfix()) {
1484 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 1444 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
1485 Expression::kEffect); 1445 Expression::kEffect);
1486 // For all contexts except kEffect: We have the result on 1446 // For all contexts except kEffect: We have the result on
1487 // top of the stack. 1447 // top of the stack.
1488 if (expr->context() != Expression::kEffect) { 1448 if (expr->context() != Expression::kEffect) {
1489 MoveTOS(expr->context()); 1449 ApplyTOS(expr->context());
1490 } 1450 }
1491 } else { 1451 } else {
1492 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 1452 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
1493 expr->context()); 1453 expr->context());
1494 } 1454 }
1495 break; 1455 break;
1496 case NAMED_PROPERTY: { 1456 case NAMED_PROPERTY: {
1497 __ Move(rcx, prop->key()->AsLiteral()->handle()); 1457 __ Move(rcx, prop->key()->AsLiteral()->handle());
1498 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1458 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1499 __ call(ic, RelocInfo::CODE_TARGET); 1459 __ call(ic, RelocInfo::CODE_TARGET);
1500 // This nop signals to the IC that there is no inlined code at the call 1460 // This nop signals to the IC that there is no inlined code at the call
1501 // site for it to patch. 1461 // site for it to patch.
1502 __ nop(); 1462 __ nop();
1503 if (expr->is_postfix()) { 1463 if (expr->is_postfix()) {
1504 __ Drop(1); // Result is on the stack under the receiver. 1464 __ Drop(1); // Result is on the stack under the receiver.
1505 if (expr->context() != Expression::kEffect) { 1465 if (expr->context() != Expression::kEffect) {
1506 MoveTOS(expr->context()); 1466 ApplyTOS(expr->context());
1507 } 1467 }
1508 } else { 1468 } else {
1509 DropAndMove(expr->context(), rax); 1469 DropAndApply(1, expr->context(), rax);
1510 } 1470 }
1511 break; 1471 break;
1512 } 1472 }
1513 case KEYED_PROPERTY: { 1473 case KEYED_PROPERTY: {
1514 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 1474 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
1515 __ call(ic, RelocInfo::CODE_TARGET); 1475 __ call(ic, RelocInfo::CODE_TARGET);
1516 // This nop signals to the IC that there is no inlined code at the call 1476 // This nop signals to the IC that there is no inlined code at the call
1517 // site for it to patch. 1477 // site for it to patch.
1518 __ nop(); 1478 __ nop();
1519 if (expr->is_postfix()) { 1479 if (expr->is_postfix()) {
1520 __ Drop(2); // Result is on the stack under the key and the receiver. 1480 __ Drop(2); // Result is on the stack under the key and the receiver.
1521 if (expr->context() != Expression::kEffect) { 1481 if (expr->context() != Expression::kEffect) {
1522 MoveTOS(expr->context()); 1482 ApplyTOS(expr->context());
1523 } 1483 }
1524 } else { 1484 } else {
1525 DropAndMove(expr->context(), rax, 2); 1485 DropAndApply(2, expr->context(), rax);
1526 } 1486 }
1527 break; 1487 break;
1528 } 1488 }
1529 } 1489 }
1530 } 1490 }
1531 1491
1532 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { 1492 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
1533 Comment cmnt(masm_, "[ BinaryOperation"); 1493 Comment cmnt(masm_, "[ BinaryOperation");
1534 switch (expr->op()) { 1494 switch (expr->op()) {
1535 case Token::COMMA: 1495 case Token::COMMA:
(...skipping 21 matching lines...) Expand all
1557 case Token::SAR: { 1517 case Token::SAR: {
1558 ASSERT_EQ(Expression::kValue, expr->left()->context()); 1518 ASSERT_EQ(Expression::kValue, expr->left()->context());
1559 ASSERT_EQ(Expression::kValue, expr->right()->context()); 1519 ASSERT_EQ(Expression::kValue, expr->right()->context());
1560 1520
1561 Visit(expr->left()); 1521 Visit(expr->left());
1562 Visit(expr->right()); 1522 Visit(expr->right());
1563 GenericBinaryOpStub stub(expr->op(), 1523 GenericBinaryOpStub stub(expr->op(),
1564 NO_OVERWRITE, 1524 NO_OVERWRITE,
1565 NO_GENERIC_BINARY_FLAGS); 1525 NO_GENERIC_BINARY_FLAGS);
1566 __ CallStub(&stub); 1526 __ CallStub(&stub);
1567 Move(expr->context(), rax); 1527 Apply(expr->context(), rax);
1568 1528
1569 break; 1529 break;
1570 } 1530 }
1571 default: 1531 default:
1572 UNREACHABLE(); 1532 UNREACHABLE();
1573 } 1533 }
1574 } 1534 }
1575 1535
1576 1536
1577 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 1537 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
1725 break; 1685 break;
1726 } 1686 }
1727 true_label_ = saved_true; 1687 true_label_ = saved_true;
1728 false_label_ = saved_false; 1688 false_label_ = saved_false;
1729 // Convert current context to test context: End post-test code. 1689 // Convert current context to test context: End post-test code.
1730 } 1690 }
1731 1691
1732 1692
1733 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { 1693 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) {
1734 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1694 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1735 Move(expr->context(), rax); 1695 Apply(expr->context(), rax);
1736 } 1696 }
1737 1697
1738 1698
1739 Register FastCodeGenerator::result_register() { return rax; } 1699 Register FastCodeGenerator::result_register() { return rax; }
1740 1700
1741 1701
1742 Register FastCodeGenerator::context_register() { return rsi; } 1702 Register FastCodeGenerator::context_register() { return rsi; }
1743 1703
1744 1704
1745 void FastCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 1705 void FastCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1784 __ movq(Operand(rsp, 0), rdx); 1744 __ movq(Operand(rsp, 0), rdx);
1785 // And return. 1745 // And return.
1786 __ ret(0); 1746 __ ret(0);
1787 } 1747 }
1788 1748
1789 1749
1790 #undef __ 1750 #undef __
1791 1751
1792 1752
1793 } } // namespace v8::internal 1753 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698