OLD | NEW |
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 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 __ RecordJSReturn(); | 113 __ RecordJSReturn(); |
114 __ mov(sp, fp); | 114 __ mov(sp, fp); |
115 __ ldm(ia_w, sp, fp.bit() | lr.bit()); | 115 __ ldm(ia_w, sp, fp.bit() | lr.bit()); |
116 int num_parameters = function_->scope()->num_parameters(); | 116 int num_parameters = function_->scope()->num_parameters(); |
117 __ add(sp, sp, Operand((num_parameters + 1) * kPointerSize)); | 117 __ add(sp, sp, Operand((num_parameters + 1) * kPointerSize)); |
118 __ Jump(lr); | 118 __ Jump(lr); |
119 } | 119 } |
120 } | 120 } |
121 | 121 |
122 | 122 |
| 123 void FastCodeGenerator::Move(Location destination, Slot* source) { |
| 124 switch (destination.type()) { |
| 125 case Location::NOWHERE: |
| 126 break; |
| 127 case Location::TEMP: |
| 128 __ ldr(ip, MemOperand(fp, SlotOffset(source))); |
| 129 __ push(ip); |
| 130 break; |
| 131 } |
| 132 } |
| 133 |
| 134 |
| 135 void FastCodeGenerator::Move(Location destination, Literal* expr) { |
| 136 switch (destination.type()) { |
| 137 case Location::NOWHERE: |
| 138 break; |
| 139 case Location::TEMP: |
| 140 __ mov(ip, Operand(expr->handle())); |
| 141 __ push(ip); |
| 142 break; |
| 143 } |
| 144 } |
| 145 |
| 146 |
| 147 void FastCodeGenerator::Move(Slot* destination, Location source) { |
| 148 switch (source.type()) { |
| 149 case Location::NOWHERE: |
| 150 UNREACHABLE(); |
| 151 case Location::TEMP: |
| 152 __ pop(ip); |
| 153 __ str(ip, MemOperand(fp, SlotOffset(destination))); |
| 154 break; |
| 155 } |
| 156 } |
| 157 |
| 158 |
123 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 159 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
124 // Call the runtime to declare the globals. | 160 // Call the runtime to declare the globals. |
125 // The context is the first argument. | 161 // The context is the first argument. |
126 __ mov(r1, Operand(pairs)); | 162 __ mov(r1, Operand(pairs)); |
127 __ mov(r0, Operand(Smi::FromInt(is_eval_ ? 1 : 0))); | 163 __ mov(r0, Operand(Smi::FromInt(is_eval_ ? 1 : 0))); |
128 __ stm(db_w, sp, cp.bit() | r1.bit() | r0.bit()); | 164 __ stm(db_w, sp, cp.bit() | r1.bit() | r0.bit()); |
129 __ CallRuntime(Runtime::kDeclareGlobals, 3); | 165 __ CallRuntime(Runtime::kDeclareGlobals, 3); |
130 // Return value is ignored. | 166 // Return value is ignored. |
131 } | 167 } |
132 | 168 |
133 | 169 |
134 void FastCodeGenerator::VisitBlock(Block* stmt) { | |
135 Comment cmnt(masm_, "[ Block"); | |
136 SetStatementPosition(stmt); | |
137 VisitStatements(stmt->statements()); | |
138 } | |
139 | |
140 | |
141 void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { | |
142 Comment cmnt(masm_, "[ ExpressionStatement"); | |
143 SetStatementPosition(stmt); | |
144 Visit(stmt->expression()); | |
145 } | |
146 | |
147 | |
148 void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { | 170 void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { |
149 Comment cmnt(masm_, "[ ReturnStatement"); | 171 Comment cmnt(masm_, "[ ReturnStatement"); |
150 SetStatementPosition(stmt); | 172 SetStatementPosition(stmt); |
151 Expression* expr = stmt->expression(); | 173 Expression* expr = stmt->expression(); |
152 // Complete the statement based on the type of the subexpression. | 174 // Complete the statement based on the type of the subexpression. |
153 if (expr->AsLiteral() != NULL) { | 175 if (expr->AsLiteral() != NULL) { |
154 __ mov(r0, Operand(expr->AsLiteral()->handle())); | 176 __ mov(r0, Operand(expr->AsLiteral()->handle())); |
155 } else { | 177 } else { |
156 Visit(expr); | 178 Visit(expr); |
157 ASSERT(expr->location().is_temporary()); | 179 ASSERT(expr->location().is_temporary()); |
(...skipping 20 matching lines...) Expand all Loading... |
178 // Build the function boilerplate and instantiate it. | 200 // Build the function boilerplate and instantiate it. |
179 Handle<JSFunction> boilerplate = BuildBoilerplate(expr); | 201 Handle<JSFunction> boilerplate = BuildBoilerplate(expr); |
180 if (HasStackOverflow()) return; | 202 if (HasStackOverflow()) return; |
181 | 203 |
182 ASSERT(boilerplate->IsBoilerplate()); | 204 ASSERT(boilerplate->IsBoilerplate()); |
183 | 205 |
184 // Create a new closure. | 206 // Create a new closure. |
185 __ mov(r0, Operand(boilerplate)); | 207 __ mov(r0, Operand(boilerplate)); |
186 __ stm(db_w, sp, cp.bit() | r0.bit()); | 208 __ stm(db_w, sp, cp.bit() | r0.bit()); |
187 __ CallRuntime(Runtime::kNewClosure, 2); | 209 __ CallRuntime(Runtime::kNewClosure, 2); |
188 | 210 Move(expr->location(), r0); |
189 if (expr->location().is_temporary()) { | |
190 __ push(r0); | |
191 } else { | |
192 ASSERT(expr->location().is_nowhere()); | |
193 } | |
194 } | 211 } |
195 | 212 |
196 | 213 |
197 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 214 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
198 Comment cmnt(masm_, "[ VariableProxy"); | 215 Comment cmnt(masm_, "[ VariableProxy"); |
199 Expression* rewrite = expr->var()->rewrite(); | 216 Expression* rewrite = expr->var()->rewrite(); |
200 if (rewrite == NULL) { | 217 if (rewrite == NULL) { |
201 Comment cmnt(masm_, "Global variable"); | 218 Comment cmnt(masm_, "Global variable"); |
202 // Use inline caching. Variable name is passed in r2 and the global | 219 // Use inline caching. Variable name is passed in r2 and the global |
203 // object on the stack. | 220 // object on the stack. |
204 __ ldr(ip, CodeGenerator::GlobalObject()); | 221 __ ldr(ip, CodeGenerator::GlobalObject()); |
205 __ push(ip); | 222 __ push(ip); |
206 __ mov(r2, Operand(expr->name())); | 223 __ mov(r2, Operand(expr->name())); |
207 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 224 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
208 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 225 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
209 if (expr->location().is_temporary()) { | 226 switch (expr->location().type()) { |
210 // Replace the global object with the result. | 227 case Location::NOWHERE: |
211 __ str(r0, MemOperand(sp)); | 228 __ pop(); |
212 } else { | 229 break; |
213 ASSERT(expr->location().is_nowhere()); | 230 case Location::TEMP: |
214 __ pop(); | 231 // Replace the global object with the result. |
| 232 __ str(r0, MemOperand(sp)); |
| 233 break; |
215 } | 234 } |
216 | 235 |
217 } else { | 236 } else { |
218 Comment cmnt(masm_, "Stack slot"); | 237 Comment cmnt(masm_, "Stack slot"); |
219 Slot* slot = rewrite->AsSlot(); | 238 Move(expr->location(), rewrite->AsSlot()); |
220 ASSERT(slot != NULL); | |
221 if (expr->location().is_temporary()) { | |
222 __ ldr(ip, MemOperand(fp, SlotOffset(slot))); | |
223 __ push(ip); | |
224 } else { | |
225 ASSERT(expr->location().is_nowhere()); | |
226 } | |
227 } | |
228 } | |
229 | |
230 | |
231 void FastCodeGenerator::VisitLiteral(Literal* expr) { | |
232 if (expr->location().is_temporary()) { | |
233 __ mov(ip, Operand(expr->AsLiteral()->handle())); | |
234 __ push(ip); | |
235 } else { | |
236 ASSERT(expr->location().is_nowhere()); | |
237 } | 239 } |
238 } | 240 } |
239 | 241 |
240 | 242 |
241 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 243 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
242 Comment cmnt(masm_, "[ ObjectLiteral"); | 244 Comment cmnt(masm_, "[ ObjectLiteral"); |
243 Label boilerplate_exists; | 245 Label boilerplate_exists; |
244 __ ldr(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 246 __ ldr(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
245 // r2 = literal array (0). | 247 // r2 = literal array (0). |
246 __ ldr(r2, FieldMemOperand(r2, JSFunction::kLiteralsOffset)); | 248 __ ldr(r2, FieldMemOperand(r2, JSFunction::kLiteralsOffset)); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 Smi::FromInt(0))); | 310 Smi::FromInt(0))); |
309 __ push(r1); | 311 __ push(r1); |
310 Visit(value); | 312 Visit(value); |
311 ASSERT(value->location().is_temporary()); | 313 ASSERT(value->location().is_temporary()); |
312 __ CallRuntime(Runtime::kDefineAccessor, 4); | 314 __ CallRuntime(Runtime::kDefineAccessor, 4); |
313 __ ldr(r0, MemOperand(sp)); // Restore result into r0 | 315 __ ldr(r0, MemOperand(sp)); // Restore result into r0 |
314 break; | 316 break; |
315 default: UNREACHABLE(); | 317 default: UNREACHABLE(); |
316 } | 318 } |
317 } | 319 } |
318 if (expr->location().is_nowhere() && result_saved) { | 320 switch (expr->location().type()) { |
319 __ pop(); | 321 case Location::NOWHERE: |
320 } else if (expr->location().is_temporary() && !result_saved) { | 322 if (result_saved) __ pop(); |
321 ASSERT(expr->location().is_temporary()); | 323 break; |
322 __ push(r0); | 324 case Location::TEMP: |
| 325 if (!result_saved) __ push(r0); |
| 326 break; |
323 } | 327 } |
324 } | 328 } |
325 | 329 |
326 | 330 |
327 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 331 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
328 Comment cmnt(masm_, "[ RegExp Literal"); | 332 Comment cmnt(masm_, "[ RegExp Literal"); |
329 Label done; | 333 Label done; |
330 // Registers will be used as follows: | 334 // Registers will be used as follows: |
331 // r4 = JS function, literals array | 335 // r4 = JS function, literals array |
332 // r3 = literal index | 336 // r3 = literal index |
333 // r2 = RegExp pattern | 337 // r2 = RegExp pattern |
334 // r1 = RegExp flags | 338 // r1 = RegExp flags |
335 // r0 = temp + return value (RegExp literal) | 339 // r0 = temp + return value (RegExp literal) |
336 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 340 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
337 __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); | 341 __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); |
338 int literal_offset = | 342 int literal_offset = |
339 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; | 343 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
340 __ ldr(r0, FieldMemOperand(r4, literal_offset)); | 344 __ ldr(r0, FieldMemOperand(r4, literal_offset)); |
341 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 345 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
342 __ cmp(r0, ip); | 346 __ cmp(r0, ip); |
343 __ b(ne, &done); | 347 __ b(ne, &done); |
344 __ mov(r3, Operand(Smi::FromInt(expr->literal_index()))); | 348 __ mov(r3, Operand(Smi::FromInt(expr->literal_index()))); |
345 __ mov(r2, Operand(expr->pattern())); | 349 __ mov(r2, Operand(expr->pattern())); |
346 __ mov(r1, Operand(expr->flags())); | 350 __ mov(r1, Operand(expr->flags())); |
347 __ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit()); | 351 __ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit()); |
348 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); | 352 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
349 __ bind(&done); | 353 __ bind(&done); |
350 if (expr->location().is_temporary()) { | 354 Move(expr->location(), r0); |
351 __ push(r0); | |
352 } else { | |
353 ASSERT(expr->location().is_nowhere()); | |
354 } | |
355 } | 355 } |
356 | 356 |
357 | 357 |
358 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 358 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
359 Comment cmnt(masm_, "[ ArrayLiteral"); | 359 Comment cmnt(masm_, "[ ArrayLiteral"); |
360 Label make_clone; | 360 Label make_clone; |
361 | 361 |
362 // Fetch the function's literals array. | 362 // Fetch the function's literals array. |
363 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 363 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
364 __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); | 364 __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
412 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); | 412 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); |
413 int offset = FixedArray::kHeaderSize + (i * kPointerSize); | 413 int offset = FixedArray::kHeaderSize + (i * kPointerSize); |
414 __ str(r0, FieldMemOperand(r1, offset)); | 414 __ str(r0, FieldMemOperand(r1, offset)); |
415 | 415 |
416 // Update the write barrier for the array store with r0 as the scratch | 416 // Update the write barrier for the array store with r0 as the scratch |
417 // register. | 417 // register. |
418 __ mov(r2, Operand(offset)); | 418 __ mov(r2, Operand(offset)); |
419 __ RecordWrite(r1, r2, r0); | 419 __ RecordWrite(r1, r2, r0); |
420 } | 420 } |
421 | 421 |
422 Location destination = expr->location(); | 422 switch (expr->location().type()) { |
423 if (destination.is_nowhere() && result_saved) { | 423 case Location::NOWHERE: |
424 __ pop(); | 424 if (result_saved) __ pop(); |
425 } else if (destination.is_temporary() && !result_saved) { | 425 break; |
426 __ push(r0); | 426 case Location::TEMP: |
| 427 if (!result_saved) __ push(r0); |
| 428 break; |
427 } | 429 } |
428 } | 430 } |
429 | 431 |
430 | 432 |
431 void FastCodeGenerator::VisitAssignment(Assignment* expr) { | 433 void FastCodeGenerator::VisitAssignment(Assignment* expr) { |
432 Comment cmnt(masm_, "[ Assignment"); | 434 Comment cmnt(masm_, "[ Assignment"); |
433 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); | 435 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); |
434 | 436 |
435 // Left-hand side can only be a global or a (parameter or local) slot. | 437 // Left-hand side can only be a global or a (parameter or local) slot. |
436 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); | 438 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); |
(...skipping 14 matching lines...) Expand all Loading... |
451 ASSERT(rhs->location().is_temporary()); | 453 ASSERT(rhs->location().is_temporary()); |
452 Visit(rhs); | 454 Visit(rhs); |
453 __ pop(r0); | 455 __ pop(r0); |
454 } | 456 } |
455 __ mov(r2, Operand(var->name())); | 457 __ mov(r2, Operand(var->name())); |
456 __ ldr(ip, CodeGenerator::GlobalObject()); | 458 __ ldr(ip, CodeGenerator::GlobalObject()); |
457 __ push(ip); | 459 __ push(ip); |
458 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 460 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
459 __ Call(ic, RelocInfo::CODE_TARGET); | 461 __ Call(ic, RelocInfo::CODE_TARGET); |
460 // Overwrite the global object on the stack with the result if needed. | 462 // Overwrite the global object on the stack with the result if needed. |
461 if (destination.is_temporary()) { | 463 switch (expr->location().type()) { |
462 __ str(r0, MemOperand(sp)); | 464 case Location::NOWHERE: |
463 } else { | 465 __ pop(); |
464 ASSERT(destination.is_nowhere()); | 466 break; |
465 __ pop(); | 467 case Location::TEMP: |
| 468 __ str(r0, MemOperand(sp)); |
| 469 break; |
466 } | 470 } |
467 | 471 |
468 } else { | 472 } else { |
469 // Local or parameter assignment. | 473 // Local or parameter assignment. |
470 | 474 |
471 // Code for the right-hand side expression depends on its type. | 475 // Code for the right-hand side expression depends on its type. |
472 if (rhs->AsLiteral() != NULL) { | 476 if (rhs->AsLiteral() != NULL) { |
473 // Two cases: 'temp <- (var = constant)', or 'var = constant' with a | 477 // Two cases: 'temp <- (var = constant)', or 'var = constant' with a |
474 // discarded result. Always perform the assignment. | 478 // discarded result. Always perform the assignment. |
475 __ mov(ip, Operand(rhs->AsLiteral()->handle())); | 479 __ mov(ip, Operand(rhs->AsLiteral()->handle())); |
476 __ str(ip, MemOperand(fp, SlotOffset(var->slot()))); | 480 __ str(ip, MemOperand(fp, SlotOffset(var->slot()))); |
477 if (destination.is_temporary()) { | 481 Move(expr->location(), ip); |
478 // Case 'temp <- (var = constant)'. Save result. | |
479 __ push(ip); | |
480 } | |
481 } else { | 482 } else { |
482 ASSERT(rhs->location().is_temporary()); | 483 ASSERT(rhs->location().is_temporary()); |
483 Visit(rhs); | 484 Visit(rhs); |
484 if (destination.is_temporary()) { | 485 // Load right-hand side into ip. |
485 // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side | 486 switch (expr->location().type()) { |
486 // temporary on the stack. | 487 case Location::NOWHERE: |
487 __ ldr(ip, MemOperand(sp)); | 488 // Case 'var = temp'. Discard right-hand-side temporary. |
488 } else { | 489 __ pop(ip); |
489 ASSERT(destination.is_nowhere()); | 490 break; |
490 // Case 'var = temp'. Discard right-hand-side temporary. | 491 case Location::TEMP: |
491 __ pop(ip); | 492 // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side |
| 493 // temporary on the stack. |
| 494 __ ldr(ip, MemOperand(sp)); |
| 495 break; |
492 } | 496 } |
| 497 // Do the slot assignment. |
493 __ str(ip, MemOperand(fp, SlotOffset(var->slot()))); | 498 __ str(ip, MemOperand(fp, SlotOffset(var->slot()))); |
494 } | 499 } |
495 } | 500 } |
496 } | 501 } |
497 | 502 |
498 | 503 |
499 void FastCodeGenerator::VisitCall(Call* expr) { | 504 void FastCodeGenerator::VisitCall(Call* expr) { |
500 Comment cmnt(masm_, "[ Call"); | 505 Comment cmnt(masm_, "[ Call"); |
501 Expression* fun = expr->expression(); | 506 Expression* fun = expr->expression(); |
502 ZoneList<Expression*>* args = expr->arguments(); | 507 ZoneList<Expression*>* args = expr->arguments(); |
(...skipping 11 matching lines...) Expand all Loading... |
514 ASSERT(args->at(i)->location().is_temporary()); | 519 ASSERT(args->at(i)->location().is_temporary()); |
515 } | 520 } |
516 // Record source position for debugger | 521 // Record source position for debugger |
517 SetSourcePosition(expr->position()); | 522 SetSourcePosition(expr->position()); |
518 // Call the IC initialization code. | 523 // Call the IC initialization code. |
519 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, | 524 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, |
520 NOT_IN_LOOP); | 525 NOT_IN_LOOP); |
521 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 526 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
522 // Restore context register. | 527 // Restore context register. |
523 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 528 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
524 if (expr->location().is_temporary()) { | 529 switch (expr->location().type()) { |
525 __ str(r0, MemOperand(sp)); | 530 case Location::NOWHERE: |
526 } else { | 531 __ pop(); |
527 ASSERT(expr->location().is_nowhere()); | 532 break; |
528 __ pop(); | 533 case Location::TEMP: |
| 534 __ str(r0, MemOperand(sp)); |
| 535 break; |
529 } | 536 } |
530 } | 537 } |
531 | 538 |
532 | 539 |
533 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 540 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
534 Comment cmnt(masm_, "[ CallRuntime"); | 541 Comment cmnt(masm_, "[ CallRuntime"); |
535 ZoneList<Expression*>* args = expr->arguments(); | 542 ZoneList<Expression*>* args = expr->arguments(); |
536 Runtime::Function* function = expr->function(); | 543 Runtime::Function* function = expr->function(); |
537 | 544 |
538 ASSERT(function != NULL); | 545 ASSERT(function != NULL); |
539 | 546 |
540 // Push the arguments ("left-to-right"). | 547 // Push the arguments ("left-to-right"). |
541 int arg_count = args->length(); | 548 int arg_count = args->length(); |
542 for (int i = 0; i < arg_count; i++) { | 549 for (int i = 0; i < arg_count; i++) { |
543 Visit(args->at(i)); | 550 Visit(args->at(i)); |
544 ASSERT(args->at(i)->location().is_temporary()); | 551 ASSERT(args->at(i)->location().is_temporary()); |
545 } | 552 } |
546 | 553 |
547 __ CallRuntime(function, arg_count); | 554 __ CallRuntime(function, arg_count); |
548 if (expr->location().is_temporary()) { | 555 Move(expr->location(), r0); |
549 __ push(r0); | |
550 } else { | |
551 ASSERT(expr->location().is_nowhere()); | |
552 } | |
553 } | 556 } |
554 | 557 |
555 | 558 |
556 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 559 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
557 // Compile a short-circuited boolean or operation in a non-test | 560 // Compile a short-circuited boolean or operation in a non-test |
558 // context. | 561 // context. |
559 ASSERT(expr->op() == Token::OR); | 562 ASSERT(expr->op() == Token::OR); |
560 // Compile (e0 || e1) as if it were | 563 // Compile (e0 || e1) as if it were |
561 // (let (temp = e0) temp ? temp : e1). | 564 // (let (temp = e0) temp ? temp : e1). |
562 | 565 |
(...skipping 21 matching lines...) Expand all Loading... |
584 // stack iff the destination location is temporary. | 587 // stack iff the destination location is temporary. |
585 __ CallRuntime(Runtime::kToBool, 1); | 588 __ CallRuntime(Runtime::kToBool, 1); |
586 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 589 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
587 __ cmp(r0, ip); | 590 __ cmp(r0, ip); |
588 __ b(eq, &done); | 591 __ b(eq, &done); |
589 | 592 |
590 // Discard the left-hand value if present on the stack. | 593 // Discard the left-hand value if present on the stack. |
591 if (destination.is_temporary()) __ pop(); | 594 if (destination.is_temporary()) __ pop(); |
592 // Save or discard the right-hand value as needed. | 595 // Save or discard the right-hand value as needed. |
593 if (right->AsLiteral() != NULL) { | 596 if (right->AsLiteral() != NULL) { |
594 if (destination.is_temporary()) { | 597 Move(destination, right->AsLiteral()); |
595 __ mov(ip, Operand(right->AsLiteral()->handle())); | |
596 __ push(ip); | |
597 } else { | |
598 ASSERT(destination.is_nowhere()); | |
599 } | |
600 } else { | 598 } else { |
601 Visit(right); | 599 Visit(right); |
602 ASSERT(right->location().is_temporary()); | 600 Move(destination, right->location()); |
603 if (destination.is_nowhere()) { | |
604 __ pop(); | |
605 } else { | |
606 ASSERT(destination.is_temporary()); | |
607 } | |
608 } | 601 } |
609 | 602 |
610 __ bind(&done); | 603 __ bind(&done); |
611 } | 604 } |
612 | 605 |
613 } } // namespace v8::internal | 606 } } // namespace v8::internal |
OLD | NEW |