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

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

Issue 338043: Make it more pleasant to work with expression locations in the... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/location.h ('k') | no next file » | 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 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 // (3 + 1 + 3). 109 // (3 + 1 + 3).
110 const int kPadding = Debug::kX64JSReturnSequenceLength - 7; 110 const int kPadding = Debug::kX64JSReturnSequenceLength - 7;
111 for (int i = 0; i < kPadding; ++i) { 111 for (int i = 0; i < kPadding; ++i) {
112 masm_->int3(); 112 masm_->int3();
113 } 113 }
114 #endif 114 #endif
115 } 115 }
116 } 116 }
117 117
118 118
119 void FastCodeGenerator::Move(Location destination, Slot* source) {
120 switch (destination.type()) {
121 case Location::NOWHERE:
122 break;
123 case Location::TEMP:
124 __ push(Operand(rbp, SlotOffset(source)));
125 break;
126 }
127 }
128
129
130 void FastCodeGenerator::Move(Location destination, Literal* expr) {
131 switch (destination.type()) {
132 case Location::NOWHERE:
133 break;
134 case Location::TEMP:
135 __ Push(expr->handle());
136 break;
137 }
138 }
139
140
141 void FastCodeGenerator::Move(Slot* destination, Location source) {
142 switch (source.type()) {
143 case Location::NOWHERE:
144 UNREACHABLE();
145 case Location::TEMP:
146 __ pop(Operand(rbp, SlotOffset(destination)));
147 break;
148 }
149 }
150
151
119 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 152 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
120 // Call the runtime to declare the globals. 153 // Call the runtime to declare the globals.
121 __ push(rsi); // The context is the first argument. 154 __ push(rsi); // The context is the first argument.
122 __ Push(pairs); 155 __ Push(pairs);
123 __ Push(Smi::FromInt(is_eval_ ? 1 : 0)); 156 __ Push(Smi::FromInt(is_eval_ ? 1 : 0));
124 __ CallRuntime(Runtime::kDeclareGlobals, 3); 157 __ CallRuntime(Runtime::kDeclareGlobals, 3);
125 // Return value is ignored. 158 // Return value is ignored.
126 } 159 }
127 160
128 161
129 void FastCodeGenerator::VisitBlock(Block* stmt) {
130 Comment cmnt(masm_, "[ Block");
131 SetStatementPosition(stmt);
132 VisitStatements(stmt->statements());
133 }
134
135
136 void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
137 Comment cmnt(masm_, "[ ExpressionStatement");
138 SetStatementPosition(stmt);
139 Visit(stmt->expression());
140 }
141
142
143 void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { 162 void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
144 Comment cmnt(masm_, "[ ReturnStatement"); 163 Comment cmnt(masm_, "[ ReturnStatement");
145 SetStatementPosition(stmt); 164 SetStatementPosition(stmt);
146 Expression* expr = stmt->expression(); 165 Expression* expr = stmt->expression();
147 // Complete the statement based on the type of the subexpression. 166 // Complete the statement based on the type of the subexpression.
148 if (expr->AsLiteral() != NULL) { 167 if (expr->AsLiteral() != NULL) {
149 __ Move(rax, expr->AsLiteral()->handle()); 168 __ Move(rax, expr->AsLiteral()->handle());
150 } else { 169 } else {
151 Visit(expr); 170 Visit(expr);
152 ASSERT(expr->location().is_temporary()); 171 ASSERT(expr->location().is_temporary());
(...skipping 29 matching lines...) Expand all
182 // Build the function boilerplate and instantiate it. 201 // Build the function boilerplate and instantiate it.
183 Handle<JSFunction> boilerplate = BuildBoilerplate(expr); 202 Handle<JSFunction> boilerplate = BuildBoilerplate(expr);
184 if (HasStackOverflow()) return; 203 if (HasStackOverflow()) return;
185 204
186 ASSERT(boilerplate->IsBoilerplate()); 205 ASSERT(boilerplate->IsBoilerplate());
187 206
188 // Create a new closure. 207 // Create a new closure.
189 __ push(rsi); 208 __ push(rsi);
190 __ Push(boilerplate); 209 __ Push(boilerplate);
191 __ CallRuntime(Runtime::kNewClosure, 2); 210 __ CallRuntime(Runtime::kNewClosure, 2);
192 211 Move(expr->location(), rax);
193 if (expr->location().is_temporary()) {
194 __ push(rax);
195 } else {
196 ASSERT(expr->location().is_nowhere());
197 }
198 } 212 }
199 213
200 214
201 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 215 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
202 Comment cmnt(masm_, "[ VariableProxy"); 216 Comment cmnt(masm_, "[ VariableProxy");
203 Expression* rewrite = expr->var()->rewrite(); 217 Expression* rewrite = expr->var()->rewrite();
204 if (rewrite == NULL) { 218 if (rewrite == NULL) {
205 Comment cmnt(masm_, "Global variable"); 219 Comment cmnt(masm_, "Global variable");
206 // Use inline caching. Variable name is passed in rcx and the global 220 // Use inline caching. Variable name is passed in rcx and the global
207 // object on the stack. 221 // object on the stack.
208 __ push(CodeGenerator::GlobalObject()); 222 __ push(CodeGenerator::GlobalObject());
209 __ Move(rcx, expr->name()); 223 __ Move(rcx, expr->name());
210 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 224 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
211 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); 225 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
212 226
213 // A test rax instruction following the call is used by the IC to 227 // A test rax instruction following the call is used by the IC to
214 // indicate that the inobject property case was inlined. Ensure there 228 // indicate that the inobject property case was inlined. Ensure there
215 // is no test rax instruction here. 229 // is no test rax instruction here.
216 if (expr->location().is_temporary()) { 230 switch (expr->location().type()) {
217 // Replace the global object with the result. 231 case Location::NOWHERE:
218 __ movq(Operand(rsp, 0), rax); 232 __ addq(rsp, Immediate(kPointerSize));
219 } else { 233 break;
220 ASSERT(expr->location().is_nowhere()); 234 case Location::TEMP:
221 __ addq(rsp, Immediate(kPointerSize)); 235 // Replace the global object with the result.
236 __ movq(Operand(rsp, 0), rax);
237 break;
222 } 238 }
223 239
224 } else { 240 } else {
225 Comment cmnt(masm_, "Stack slot"); 241 Comment cmnt(masm_, "Stack slot");
226 Slot* slot = rewrite->AsSlot(); 242 Move(expr->location(), rewrite->AsSlot());
227 ASSERT(slot != NULL);
228 if (expr->location().is_temporary()) {
229 __ push(Operand(rbp, SlotOffset(slot)));
230 } else {
231 ASSERT(expr->location().is_nowhere());
232 }
233 }
234 }
235
236
237 void FastCodeGenerator::VisitLiteral(Literal* expr) {
238 if (expr->location().is_temporary()) {
239 __ Push(expr->handle());
240 } else {
241 ASSERT(expr->location().is_nowhere());
242 } 243 }
243 } 244 }
244 245
245 246
246 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 247 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
247 Comment cmnt(masm_, "[ ObjectLiteral"); 248 Comment cmnt(masm_, "[ ObjectLiteral");
248 Label boilerplate_exists; 249 Label boilerplate_exists;
249 250
250 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 251 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
251 __ movq(rbx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); 252 __ movq(rbx, FieldOperand(rdi, JSFunction::kLiteralsOffset));
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 Smi::FromInt(1) : 323 Smi::FromInt(1) :
323 Smi::FromInt(0)); 324 Smi::FromInt(0));
324 Visit(value); 325 Visit(value);
325 ASSERT(value->location().is_temporary()); 326 ASSERT(value->location().is_temporary());
326 __ CallRuntime(Runtime::kDefineAccessor, 4); 327 __ CallRuntime(Runtime::kDefineAccessor, 4);
327 __ movq(rax, Operand(rsp, 0)); // Restore result into rax. 328 __ movq(rax, Operand(rsp, 0)); // Restore result into rax.
328 break; 329 break;
329 default: UNREACHABLE(); 330 default: UNREACHABLE();
330 } 331 }
331 } 332 }
332 if (expr->location().is_nowhere() && result_saved) { 333 switch (expr->location().type()) {
333 __ addq(rsp, Immediate(kPointerSize)); 334 case Location::NOWHERE:
334 } else if (expr->location().is_temporary() && !result_saved) { 335 if (result_saved) __ addq(rsp, Immediate(kPointerSize));
335 __ push(rax); 336 break;
337 case Location::TEMP:
338 if (!result_saved) __ push(rax);
339 break;
336 } 340 }
337 } 341 }
338 342
339 343
340 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 344 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
341 Comment cmnt(masm_, "[ RegExp Literal"); 345 Comment cmnt(masm_, "[ RegExp Literal");
342 Label done; 346 Label done;
343 // Registers will be used as follows: 347 // Registers will be used as follows:
344 // rdi = JS function. 348 // rdi = JS function.
345 // rbx = literals array. 349 // rbx = literals array.
346 // rax = regexp literal. 350 // rax = regexp literal.
347 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 351 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
348 __ movq(rbx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); 352 __ movq(rbx, FieldOperand(rdi, JSFunction::kLiteralsOffset));
349 int literal_offset = 353 int literal_offset =
350 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; 354 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
351 __ movq(rax, FieldOperand(rbx, literal_offset)); 355 __ movq(rax, FieldOperand(rbx, literal_offset));
352 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 356 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
353 __ j(not_equal, &done); 357 __ j(not_equal, &done);
354 // Create regexp literal using runtime function 358 // Create regexp literal using runtime function
355 // Result will be in rax. 359 // Result will be in rax.
356 __ push(rbx); 360 __ push(rbx);
357 __ Push(Smi::FromInt(expr->literal_index())); 361 __ Push(Smi::FromInt(expr->literal_index()));
358 __ Push(expr->pattern()); 362 __ Push(expr->pattern());
359 __ Push(expr->flags()); 363 __ Push(expr->flags());
360 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 364 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
361 // Label done: 365 // Label done:
362 __ bind(&done); 366 __ bind(&done);
363 if (expr->location().is_temporary()) { 367 Move(expr->location(), rax);
364 __ push(rax);
365 } else {
366 ASSERT(expr->location().is_nowhere());
367 }
368 } 368 }
369 369
370 370
371 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 371 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
372 Comment cmnt(masm_, "[ ArrayLiteral"); 372 Comment cmnt(masm_, "[ ArrayLiteral");
373 Label make_clone; 373 Label make_clone;
374 374
375 // Fetch the function's literals array. 375 // Fetch the function's literals array.
376 __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 376 __ movq(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
377 __ movq(rbx, FieldOperand(rbx, JSFunction::kLiteralsOffset)); 377 __ movq(rbx, FieldOperand(rbx, JSFunction::kLiteralsOffset));
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 __ pop(rax); // Subexpression value. 422 __ pop(rax); // Subexpression value.
423 __ movq(rbx, Operand(rsp, 0)); // Copy of array literal. 423 __ movq(rbx, Operand(rsp, 0)); // Copy of array literal.
424 __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset)); 424 __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
425 int offset = FixedArray::kHeaderSize + (i * kPointerSize); 425 int offset = FixedArray::kHeaderSize + (i * kPointerSize);
426 __ movq(FieldOperand(rbx, offset), rax); 426 __ movq(FieldOperand(rbx, offset), rax);
427 427
428 // Update the write barrier for the array store. 428 // Update the write barrier for the array store.
429 __ RecordWrite(rbx, offset, rax, rcx); 429 __ RecordWrite(rbx, offset, rax, rcx);
430 } 430 }
431 431
432 Location destination = expr->location(); 432 switch (expr->location().type()) {
433 if (destination.is_nowhere() && result_saved) { 433 case Location::NOWHERE:
434 __ addq(rsp, Immediate(kPointerSize)); 434 if (result_saved) __ addq(rsp, Immediate(kPointerSize));
435 } else if (destination.is_temporary() && !result_saved) { 435 break;
436 __ push(rax); 436 case Location::TEMP:
437 if (!result_saved) __ push(rax);
438 break;
437 } 439 }
438 } 440 }
439 441
440 442
441 void FastCodeGenerator::VisitAssignment(Assignment* expr) { 443 void FastCodeGenerator::VisitAssignment(Assignment* expr) {
442 Comment cmnt(masm_, "[ Assignment"); 444 Comment cmnt(masm_, "[ Assignment");
443 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); 445 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR);
444 446
445 // Left-hand side can only be a global or a (parameter or local) slot. 447 // Left-hand side can only be a global or a (parameter or local) slot.
446 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); 448 Variable* var = expr->target()->AsVariableProxy()->AsVariable();
(...skipping 13 matching lines...) Expand all
460 } else { 462 } else {
461 ASSERT(rhs->location().is_temporary()); 463 ASSERT(rhs->location().is_temporary());
462 Visit(rhs); 464 Visit(rhs);
463 __ pop(rax); 465 __ pop(rax);
464 } 466 }
465 __ Move(rcx, var->name()); 467 __ Move(rcx, var->name());
466 __ push(CodeGenerator::GlobalObject()); 468 __ push(CodeGenerator::GlobalObject());
467 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 469 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
468 __ Call(ic, RelocInfo::CODE_TARGET); 470 __ Call(ic, RelocInfo::CODE_TARGET);
469 // Overwrite the global object on the stack with the result if needed. 471 // Overwrite the global object on the stack with the result if needed.
470 if (destination.is_temporary()) { 472 switch (expr->location().type()) {
471 __ movq(Operand(rsp, 0), rax); 473 case Location::NOWHERE:
472 } else { 474 __ addq(rsp, Immediate(kPointerSize));
473 __ addq(rsp, Immediate(kPointerSize)); 475 break;
476 case Location::TEMP:
477 __ movq(Operand(rsp, 0), rax);
478 break;
474 } 479 }
475 } else { 480 } else {
476 // Local or parameter assignment. 481 // Local or parameter assignment.
477 482
478 // Code for the right-hand-side expression depends on its type. 483 // Code for the right-hand-side expression depends on its type.
479 if (rhs->AsLiteral() != NULL) { 484 if (rhs->AsLiteral() != NULL) {
480 // Two cases: 'temp <- (var = constant)', or 'var = constant' with a 485 // Two cases: 'temp <- (var = constant)', or 'var = constant' with a
481 // discarded result. Always perform the assignment. 486 // discarded result. Always perform the assignment.
482 __ Move(kScratchRegister, rhs->AsLiteral()->handle()); 487 __ Move(kScratchRegister, rhs->AsLiteral()->handle());
483 __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister); 488 __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister);
484 if (destination.is_temporary()) { 489 Move(expr->location(), kScratchRegister);
485 // Case 'temp <- (var = constant)'. Save result.
486 __ push(kScratchRegister);
487 }
488 } else { 490 } else {
489 ASSERT(rhs->location().is_temporary()); 491 ASSERT(rhs->location().is_temporary());
490 Visit(rhs); 492 Visit(rhs);
491 if (destination.is_temporary()) { 493 switch (expr->location().type()) {
492 // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side temporary 494 case Location::NOWHERE:
493 // on the stack. 495 // Case 'var = temp'. Discard right-hand-side temporary.
494 __ movq(kScratchRegister, Operand(rsp, 0)); 496 Move(var->slot(), rhs->location());
495 __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister); 497 break;
496 } else { 498 case Location::TEMP:
497 ASSERT(destination.is_nowhere()); 499 // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side
498 // Case 'var = temp'. Discard right-hand-side temporary. 500 // temporary on the stack.
499 __ pop(Operand(rbp, SlotOffset(var->slot()))); 501 __ movq(kScratchRegister, Operand(rsp, 0));
502 __ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister);
503 break;
500 } 504 }
501 } 505 }
502 } 506 }
503 } 507 }
504 508
505 509
506 void FastCodeGenerator::VisitCall(Call* expr) { 510 void FastCodeGenerator::VisitCall(Call* expr) {
507 Expression* fun = expr->expression(); 511 Expression* fun = expr->expression();
508 ZoneList<Expression*>* args = expr->arguments(); 512 ZoneList<Expression*>* args = expr->arguments();
509 Variable* var = fun->AsVariableProxy()->AsVariable(); 513 Variable* var = fun->AsVariableProxy()->AsVariable();
(...skipping 10 matching lines...) Expand all
520 } 524 }
521 // Record source position for debugger 525 // Record source position for debugger
522 SetSourcePosition(expr->position()); 526 SetSourcePosition(expr->position());
523 // Call the IC initialization code. 527 // Call the IC initialization code.
524 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, 528 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count,
525 NOT_IN_LOOP); 529 NOT_IN_LOOP);
526 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); 530 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
527 // Restore context register. 531 // Restore context register.
528 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 532 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
529 // Discard the function left on TOS. 533 // Discard the function left on TOS.
530 if (expr->location().is_temporary()) { 534 switch (expr->location().type()) {
531 __ movq(Operand(rsp, 0), rax); 535 case Location::NOWHERE:
532 } else { 536 __ addq(rsp, Immediate(kPointerSize));
533 ASSERT(expr->location().is_nowhere()); 537 break;
534 __ addq(rsp, Immediate(kPointerSize)); 538 case Location::TEMP:
539 __ movq(Operand(rsp, 0), rax);
540 break;
535 } 541 }
536 } 542 }
537 543
538 544
539 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 545 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
540 Comment cmnt(masm_, "[ CallRuntime"); 546 Comment cmnt(masm_, "[ CallRuntime");
541 ZoneList<Expression*>* args = expr->arguments(); 547 ZoneList<Expression*>* args = expr->arguments();
542 Runtime::Function* function = expr->function(); 548 Runtime::Function* function = expr->function();
543 549
544 ASSERT(function != NULL); 550 ASSERT(function != NULL);
545 551
546 // Push the arguments ("left-to-right"). 552 // Push the arguments ("left-to-right").
547 int arg_count = args->length(); 553 int arg_count = args->length();
548 for (int i = 0; i < arg_count; i++) { 554 for (int i = 0; i < arg_count; i++) {
549 Visit(args->at(i)); 555 Visit(args->at(i));
550 ASSERT(args->at(i)->location().is_temporary()); 556 ASSERT(args->at(i)->location().is_temporary());
551 } 557 }
552 558
553 __ CallRuntime(function, arg_count); 559 __ CallRuntime(function, arg_count);
554 if (expr->location().is_temporary()) { 560 Move(expr->location(), rax);
555 __ push(rax);
556 } else {
557 ASSERT(expr->location().is_nowhere());
558 }
559 } 561 }
560 562
561 563
562 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { 564 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
563 // Compile a short-circuited boolean or operation in a non-test 565 // Compile a short-circuited boolean or operation in a non-test
564 // context. 566 // context.
565 ASSERT(expr->op() == Token::OR); 567 ASSERT(expr->op() == Token::OR);
566 // Compile (e0 || e1) as if it were 568 // Compile (e0 || e1) as if it were
567 // (let (temp = e0) temp ? temp : e1). 569 // (let (temp = e0) temp ? temp : e1).
568 570
569 Label eval_right, done; 571 Label eval_right, done;
570 Location destination = expr->location(); 572 Location destination = expr->location();
571 Expression* left = expr->left(); 573 Expression* left = expr->left();
572 Expression* right = expr->right(); 574 Expression* right = expr->right();
573 575
574 // Use the shared ToBoolean stub to find the boolean value of the 576 // Use the shared ToBoolean stub to find the boolean value of the
575 // left-hand subexpression. Load the value into rax to perform some 577 // left-hand subexpression. Load the value into rax to perform some
576 // inlined checks assumed by the stub. 578 // inlined checks assumed by the stub.
577 579
578 // Compile the left-hand value into rax. Put it on the stack if we may 580 // Compile the left-hand value into rax. Put it on the stack if we may
579 // need it as the value of the whole expression. 581 // need it as the value of the whole expression.
580 if (left->AsLiteral() != NULL) { 582 if (left->AsLiteral() != NULL) {
581 __ Move(rax, left->AsLiteral()->handle()); 583 __ Move(rax, left->AsLiteral()->handle());
582 if (destination.is_temporary()) __ push(rax); 584 if (destination.is_temporary()) __ push(rax);
583 } else { 585 } else {
584 Visit(left); 586 Visit(left);
585 ASSERT(left->location().is_temporary()); 587 ASSERT(left->location().is_temporary());
586 if (destination.is_temporary()) { 588 switch (destination.type()) {
587 // Copy the left-hand value into rax because we may need it as the 589 case Location::NOWHERE:
588 // final result. 590 // Pop the left-hand value into rax because we will not need it as the
589 __ movq(rax, Operand(rsp, 0)); 591 // final result.
590 } else { 592 __ pop(rax);
591 // Pop the left-hand value into rax because we will not need it as the 593 break;
592 // final result. 594 case Location::TEMP:
593 __ pop(rax); 595 // Copy the left-hand value into rax because we may need it as the
596 // final result.
597 __ movq(rax, Operand(rsp, 0));
598 break;
594 } 599 }
595 } 600 }
596 // The left-hand value is in rax. It is also on the stack iff the 601 // The left-hand value is in rax. It is also on the stack iff the
597 // destination location is temporary. 602 // destination location is temporary.
598 603
599 // Perform fast checks assumed by the stub. 604 // Perform fast checks assumed by the stub.
600 // The undefined value is false. 605 // The undefined value is false.
601 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 606 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
602 __ j(equal, &eval_right); 607 __ j(equal, &eval_right);
603 __ CompareRoot(rax, Heap::kTrueValueRootIndex); // True is true. 608 __ CompareRoot(rax, Heap::kTrueValueRootIndex); // True is true.
(...skipping 13 matching lines...) Expand all
617 __ testq(rax, rax); // The stub returns nonzero for true. 622 __ testq(rax, rax); // The stub returns nonzero for true.
618 __ j(not_zero, &done); 623 __ j(not_zero, &done);
619 624
620 __ bind(&eval_right); 625 __ bind(&eval_right);
621 // Discard the left-hand value if present on the stack. 626 // Discard the left-hand value if present on the stack.
622 if (destination.is_temporary()) { 627 if (destination.is_temporary()) {
623 __ addq(rsp, Immediate(kPointerSize)); 628 __ addq(rsp, Immediate(kPointerSize));
624 } 629 }
625 // Save or discard the right-hand value as needed. 630 // Save or discard the right-hand value as needed.
626 if (right->AsLiteral() != NULL) { 631 if (right->AsLiteral() != NULL) {
627 if (destination.is_temporary()) { 632 Move(destination, right->AsLiteral());
628 __ Push(right->AsLiteral()->handle());
629 } else {
630 ASSERT(destination.is_nowhere());
631 }
632 } else { 633 } else {
633 Visit(right); 634 Visit(right);
634 ASSERT(right->location().is_temporary()); 635 Move(destination, right->location());
635 if (destination.is_nowhere()) {
636 __ addq(rsp, Immediate(kPointerSize));
637 } else {
638 ASSERT(destination.is_temporary());
639 }
640 } 636 }
641 637
642 __ bind(&done); 638 __ bind(&done);
643 } 639 }
644 640
645 641
646 } } // namespace v8::internal 642 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/location.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698