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 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 // patch with the code required by the debugger. | 103 // patch with the code required by the debugger. |
104 __ mov(esp, ebp); | 104 __ mov(esp, ebp); |
105 __ pop(ebp); | 105 __ pop(ebp); |
106 __ ret((fun->scope()->num_parameters() + 1) * kPointerSize); | 106 __ ret((fun->scope()->num_parameters() + 1) * kPointerSize); |
107 } | 107 } |
108 } | 108 } |
109 | 109 |
110 | 110 |
111 void FastCodeGenerator::Move(Location destination, Slot* source) { | 111 void FastCodeGenerator::Move(Location destination, Slot* source) { |
112 switch (destination.type()) { | 112 switch (destination.type()) { |
113 case Location::NOWHERE: | 113 case Location::UNINITIALIZED: |
| 114 UNREACHABLE(); |
| 115 case Location::EFFECT: |
114 break; | 116 break; |
115 case Location::TEMP: | 117 case Location::VALUE: |
116 __ push(Operand(ebp, SlotOffset(source))); | 118 __ push(Operand(ebp, SlotOffset(source))); |
117 break; | 119 break; |
118 } | 120 } |
119 } | 121 } |
120 | 122 |
121 | 123 |
122 void FastCodeGenerator::Move(Location destination, Literal* expr) { | 124 void FastCodeGenerator::Move(Location destination, Literal* expr) { |
123 switch (destination.type()) { | 125 switch (destination.type()) { |
124 case Location::NOWHERE: | 126 case Location::UNINITIALIZED: |
| 127 UNREACHABLE(); |
| 128 case Location::EFFECT: |
125 break; | 129 break; |
126 case Location::TEMP: | 130 case Location::VALUE: |
127 __ push(Immediate(expr->handle())); | 131 __ push(Immediate(expr->handle())); |
128 break; | 132 break; |
129 } | 133 } |
130 } | 134 } |
131 | 135 |
132 | 136 |
133 void FastCodeGenerator::Move(Slot* destination, Location source) { | 137 void FastCodeGenerator::Move(Slot* destination, Location source) { |
134 switch (source.type()) { | 138 switch (source.type()) { |
135 case Location::NOWHERE: | 139 case Location::UNINITIALIZED: // Fall through. |
| 140 case Location::EFFECT: |
136 UNREACHABLE(); | 141 UNREACHABLE(); |
137 case Location::TEMP: | 142 case Location::VALUE: |
138 __ pop(Operand(ebp, SlotOffset(destination))); | 143 __ pop(Operand(ebp, SlotOffset(destination))); |
139 break; | 144 break; |
140 } | 145 } |
141 } | 146 } |
142 | 147 |
143 | 148 |
144 void FastCodeGenerator::DropAndMove(Location destination, Register source) { | 149 void FastCodeGenerator::DropAndMove(Location destination, Register source) { |
145 switch (destination.type()) { | 150 switch (destination.type()) { |
146 case Location::NOWHERE: | 151 case Location::UNINITIALIZED: |
| 152 UNREACHABLE(); |
| 153 case Location::EFFECT: |
147 __ add(Operand(esp), Immediate(kPointerSize)); | 154 __ add(Operand(esp), Immediate(kPointerSize)); |
148 break; | 155 break; |
149 case Location::TEMP: | 156 case Location::VALUE: |
150 __ mov(Operand(esp, 0), source); | 157 __ mov(Operand(esp, 0), source); |
151 break; | 158 break; |
152 } | 159 } |
153 } | 160 } |
154 | 161 |
155 | 162 |
156 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 163 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
157 // Call the runtime to declare the globals. | 164 // Call the runtime to declare the globals. |
158 __ push(esi); // The context is the first argument. | 165 __ push(esi); // The context is the first argument. |
159 __ push(Immediate(pairs)); | 166 __ push(Immediate(pairs)); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 __ nop(); | 231 __ nop(); |
225 | 232 |
226 DropAndMove(expr->location(), eax); | 233 DropAndMove(expr->location(), eax); |
227 } else { | 234 } else { |
228 Comment cmnt(masm_, "Stack slot"); | 235 Comment cmnt(masm_, "Stack slot"); |
229 Move(expr->location(), rewrite->AsSlot()); | 236 Move(expr->location(), rewrite->AsSlot()); |
230 } | 237 } |
231 } | 238 } |
232 | 239 |
233 | 240 |
| 241 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 242 Comment cmnt(masm_, "[ RegExp Literal"); |
| 243 Label done; |
| 244 // Registers will be used as follows: |
| 245 // edi = JS function. |
| 246 // ebx = literals array. |
| 247 // eax = regexp literal. |
| 248 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 249 __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset)); |
| 250 int literal_offset = |
| 251 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
| 252 __ mov(eax, FieldOperand(ebx, literal_offset)); |
| 253 __ cmp(eax, Factory::undefined_value()); |
| 254 __ j(not_equal, &done); |
| 255 // Create regexp literal using runtime function |
| 256 // Result will be in eax. |
| 257 __ push(ebx); |
| 258 __ push(Immediate(Smi::FromInt(expr->literal_index()))); |
| 259 __ push(Immediate(expr->pattern())); |
| 260 __ push(Immediate(expr->flags())); |
| 261 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
| 262 // Label done: |
| 263 __ bind(&done); |
| 264 Move(expr->location(), eax); |
| 265 } |
| 266 |
| 267 |
234 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 268 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
235 Comment cmnt(masm_, "[ ObjectLiteral"); | 269 Comment cmnt(masm_, "[ ObjectLiteral"); |
236 Label exists; | 270 Label exists; |
237 // Registers will be used as follows: | 271 // Registers will be used as follows: |
238 // edi = JS function. | 272 // edi = JS function. |
239 // ebx = literals array. | 273 // ebx = literals array. |
240 // eax = boilerplate | 274 // eax = boilerplate |
241 | 275 |
242 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 276 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
243 __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset)); | 277 __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset)); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 __ mov(ecx, Immediate(key->handle())); | 322 __ mov(ecx, Immediate(key->handle())); |
289 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 323 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
290 __ call(ic, RelocInfo::CODE_TARGET); | 324 __ call(ic, RelocInfo::CODE_TARGET); |
291 // StoreIC leaves the receiver on the stack. | 325 // StoreIC leaves the receiver on the stack. |
292 break; | 326 break; |
293 } | 327 } |
294 // fall through | 328 // fall through |
295 case ObjectLiteral::Property::PROTOTYPE: | 329 case ObjectLiteral::Property::PROTOTYPE: |
296 __ push(eax); | 330 __ push(eax); |
297 Visit(key); | 331 Visit(key); |
298 ASSERT(key->location().is_temporary()); | 332 ASSERT(key->location().is_value()); |
299 Visit(value); | 333 Visit(value); |
300 ASSERT(value->location().is_temporary()); | 334 ASSERT(value->location().is_value()); |
301 __ CallRuntime(Runtime::kSetProperty, 3); | 335 __ CallRuntime(Runtime::kSetProperty, 3); |
302 __ mov(eax, Operand(esp, 0)); // Restore result into eax. | 336 __ mov(eax, Operand(esp, 0)); // Restore result into eax. |
303 break; | 337 break; |
304 case ObjectLiteral::Property::SETTER: // fall through | 338 case ObjectLiteral::Property::SETTER: // fall through |
305 case ObjectLiteral::Property::GETTER: | 339 case ObjectLiteral::Property::GETTER: |
306 __ push(eax); | 340 __ push(eax); |
307 Visit(key); | 341 Visit(key); |
308 ASSERT(key->location().is_temporary()); | 342 ASSERT(key->location().is_value()); |
309 __ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ? | 343 __ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ? |
310 Smi::FromInt(1) : | 344 Smi::FromInt(1) : |
311 Smi::FromInt(0))); | 345 Smi::FromInt(0))); |
312 Visit(value); | 346 Visit(value); |
313 ASSERT(value->location().is_temporary()); | 347 ASSERT(value->location().is_value()); |
314 __ CallRuntime(Runtime::kDefineAccessor, 4); | 348 __ CallRuntime(Runtime::kDefineAccessor, 4); |
315 __ mov(eax, Operand(esp, 0)); // Restore result into eax. | 349 __ mov(eax, Operand(esp, 0)); // Restore result into eax. |
316 break; | 350 break; |
317 default: UNREACHABLE(); | 351 default: UNREACHABLE(); |
318 } | 352 } |
319 } | 353 } |
320 switch (expr->location().type()) { | 354 switch (expr->location().type()) { |
321 case Location::NOWHERE: | 355 case Location::UNINITIALIZED: |
| 356 UNREACHABLE(); |
| 357 case Location::EFFECT: |
322 if (result_saved) __ add(Operand(esp), Immediate(kPointerSize)); | 358 if (result_saved) __ add(Operand(esp), Immediate(kPointerSize)); |
323 break; | 359 break; |
324 case Location::TEMP: | 360 case Location::VALUE: |
325 if (!result_saved) __ push(eax); | 361 if (!result_saved) __ push(eax); |
326 break; | 362 break; |
327 } | 363 } |
328 } | 364 } |
329 | 365 |
330 | 366 |
331 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | |
332 Comment cmnt(masm_, "[ RegExp Literal"); | |
333 Label done; | |
334 // Registers will be used as follows: | |
335 // edi = JS function. | |
336 // ebx = literals array. | |
337 // eax = regexp literal. | |
338 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | |
339 __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset)); | |
340 int literal_offset = | |
341 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; | |
342 __ mov(eax, FieldOperand(ebx, literal_offset)); | |
343 __ cmp(eax, Factory::undefined_value()); | |
344 __ j(not_equal, &done); | |
345 // Create regexp literal using runtime function | |
346 // Result will be in eax. | |
347 __ push(ebx); | |
348 __ push(Immediate(Smi::FromInt(expr->literal_index()))); | |
349 __ push(Immediate(expr->pattern())); | |
350 __ push(Immediate(expr->flags())); | |
351 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); | |
352 // Label done: | |
353 __ bind(&done); | |
354 Move(expr->location(), eax); | |
355 } | |
356 | |
357 | |
358 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 367 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
359 Comment cmnt(masm_, "[ ArrayLiteral"); | 368 Comment cmnt(masm_, "[ ArrayLiteral"); |
360 Label make_clone; | 369 Label make_clone; |
361 | 370 |
362 // Fetch the function's literals array. | 371 // Fetch the function's literals array. |
363 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 372 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
364 __ mov(ebx, FieldOperand(ebx, JSFunction::kLiteralsOffset)); | 373 __ mov(ebx, FieldOperand(ebx, JSFunction::kLiteralsOffset)); |
365 // Check if the literal's boilerplate has been instantiated. | 374 // Check if the literal's boilerplate has been instantiated. |
366 int offset = | 375 int offset = |
367 FixedArray::kHeaderSize + (expr->literal_index() * kPointerSize); | 376 FixedArray::kHeaderSize + (expr->literal_index() * kPointerSize); |
(...skipping 28 matching lines...) Expand all Loading... |
396 if (subexpr->AsLiteral() != NULL || | 405 if (subexpr->AsLiteral() != NULL || |
397 CompileTimeValue::IsCompileTimeValue(subexpr)) { | 406 CompileTimeValue::IsCompileTimeValue(subexpr)) { |
398 continue; | 407 continue; |
399 } | 408 } |
400 | 409 |
401 if (!result_saved) { | 410 if (!result_saved) { |
402 __ push(eax); | 411 __ push(eax); |
403 result_saved = true; | 412 result_saved = true; |
404 } | 413 } |
405 Visit(subexpr); | 414 Visit(subexpr); |
406 ASSERT(subexpr->location().is_temporary()); | 415 ASSERT(subexpr->location().is_value()); |
407 | 416 |
408 // Store the subexpression value in the array's elements. | 417 // Store the subexpression value in the array's elements. |
409 __ pop(eax); // Subexpression value. | 418 __ pop(eax); // Subexpression value. |
410 __ mov(ebx, Operand(esp, 0)); // Copy of array literal. | 419 __ mov(ebx, Operand(esp, 0)); // Copy of array literal. |
411 __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset)); | 420 __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset)); |
412 int offset = FixedArray::kHeaderSize + (i * kPointerSize); | 421 int offset = FixedArray::kHeaderSize + (i * kPointerSize); |
413 __ mov(FieldOperand(ebx, offset), eax); | 422 __ mov(FieldOperand(ebx, offset), eax); |
414 | 423 |
415 // Update the write barrier for the array store. | 424 // Update the write barrier for the array store. |
416 __ RecordWrite(ebx, offset, eax, ecx); | 425 __ RecordWrite(ebx, offset, eax, ecx); |
417 } | 426 } |
418 | 427 |
419 switch (expr->location().type()) { | 428 switch (expr->location().type()) { |
420 case Location::NOWHERE: | 429 case Location::UNINITIALIZED: |
| 430 UNREACHABLE(); |
| 431 case Location::EFFECT: |
421 if (result_saved) __ add(Operand(esp), Immediate(kPointerSize)); | 432 if (result_saved) __ add(Operand(esp), Immediate(kPointerSize)); |
422 break; | 433 break; |
423 case Location::TEMP: | 434 case Location::VALUE: |
424 if (!result_saved) __ push(eax); | 435 if (!result_saved) __ push(eax); |
425 break; | 436 break; |
426 } | 437 } |
427 } | 438 } |
428 | 439 |
429 | 440 |
430 void FastCodeGenerator::VisitAssignment(Assignment* expr) { | 441 void FastCodeGenerator::VisitAssignment(Assignment* expr) { |
431 Comment cmnt(masm_, "[ Assignment"); | 442 Comment cmnt(masm_, "[ Assignment"); |
432 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); | 443 ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); |
433 | 444 |
434 // Left-hand side can only be a global or a (parameter or local) slot. | 445 // Left-hand side can only be a global or a (parameter or local) slot. |
435 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); | 446 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); |
436 ASSERT(var != NULL); | 447 ASSERT(var != NULL); |
437 ASSERT(var->is_global() || var->slot() != NULL); | 448 ASSERT(var->is_global() || var->slot() != NULL); |
438 | 449 |
439 Expression* rhs = expr->value(); | 450 Expression* rhs = expr->value(); |
440 if (var->is_global()) { | 451 if (var->is_global()) { |
441 // Assignment to a global variable, use inline caching. Right-hand-side | 452 // Assignment to a global variable, use inline caching. Right-hand-side |
442 // value is passed in eax, variable name in ecx, and the global object | 453 // value is passed in eax, variable name in ecx, and the global object |
443 // on the stack. | 454 // on the stack. |
444 | 455 |
445 // Code for the right-hand-side expression depends on its type. | 456 // Code for the right-hand-side expression depends on its type. |
446 if (rhs->AsLiteral() != NULL) { | 457 if (rhs->AsLiteral() != NULL) { |
447 __ mov(eax, rhs->AsLiteral()->handle()); | 458 __ mov(eax, rhs->AsLiteral()->handle()); |
448 } else { | 459 } else { |
449 ASSERT(rhs->location().is_temporary()); | 460 ASSERT(rhs->location().is_value()); |
450 Visit(rhs); | 461 Visit(rhs); |
451 __ pop(eax); | 462 __ pop(eax); |
452 } | 463 } |
453 __ mov(ecx, var->name()); | 464 __ mov(ecx, var->name()); |
454 __ push(CodeGenerator::GlobalObject()); | 465 __ push(CodeGenerator::GlobalObject()); |
455 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 466 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
456 __ call(ic, RelocInfo::CODE_TARGET); | 467 __ call(ic, RelocInfo::CODE_TARGET); |
457 // Overwrite the global object on the stack with the result if needed. | 468 // Overwrite the global object on the stack with the result if needed. |
458 DropAndMove(expr->location(), eax); | 469 DropAndMove(expr->location(), eax); |
459 } else { | 470 } else { |
460 // Local or parameter assignment. | 471 // Local or parameter assignment. |
461 | 472 |
462 // Code for the right-hand side expression depends on its type. | 473 // Code for the right-hand side expression depends on its type. |
463 if (rhs->AsLiteral() != NULL) { | 474 if (rhs->AsLiteral() != NULL) { |
464 // Two cases: 'temp <- (var = constant)', or 'var = constant' with a | 475 // Two cases: 'temp <- (var = constant)', or 'var = constant' with a |
465 // discarded result. Always perform the assignment. | 476 // discarded result. Always perform the assignment. |
466 __ mov(eax, rhs->AsLiteral()->handle()); | 477 __ mov(eax, rhs->AsLiteral()->handle()); |
467 __ mov(Operand(ebp, SlotOffset(var->slot())), eax); | 478 __ mov(Operand(ebp, SlotOffset(var->slot())), eax); |
468 Move(expr->location(), eax); | 479 Move(expr->location(), eax); |
469 } else { | 480 } else { |
470 ASSERT(rhs->location().is_temporary()); | 481 ASSERT(rhs->location().is_value()); |
471 Visit(rhs); | 482 Visit(rhs); |
472 switch (expr->location().type()) { | 483 switch (expr->location().type()) { |
473 case Location::NOWHERE: | 484 case Location::UNINITIALIZED: |
| 485 UNREACHABLE(); |
| 486 case Location::EFFECT: |
474 // Case 'var = temp'. Discard right-hand-side temporary. | 487 // Case 'var = temp'. Discard right-hand-side temporary. |
475 Move(var->slot(), rhs->location()); | 488 Move(var->slot(), rhs->location()); |
476 break; | 489 break; |
477 case Location::TEMP: | 490 case Location::VALUE: |
478 // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side | 491 // Case 'temp1 <- (var = temp0)'. Preserve right-hand-side |
479 // temporary on the stack. | 492 // temporary on the stack. |
480 __ mov(eax, Operand(esp, 0)); | 493 __ mov(eax, Operand(esp, 0)); |
481 __ mov(Operand(ebp, SlotOffset(var->slot())), eax); | 494 __ mov(Operand(ebp, SlotOffset(var->slot())), eax); |
482 break; | 495 break; |
483 } | 496 } |
484 } | 497 } |
485 } | 498 } |
486 } | 499 } |
487 | 500 |
(...skipping 24 matching lines...) Expand all Loading... |
512 Visit(expr->key()); | 525 Visit(expr->key()); |
513 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 526 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
514 __ call(ic, RelocInfo::CODE_TARGET); | 527 __ call(ic, RelocInfo::CODE_TARGET); |
515 // By emitting a nop we make sure that we do not have a "test eax,..." | 528 // By emitting a nop we make sure that we do not have a "test eax,..." |
516 // instruction after the call it is treated specially by the LoadIC code. | 529 // instruction after the call it is treated specially by the LoadIC code. |
517 __ nop(); | 530 __ nop(); |
518 // Drop key left on the stack by IC. | 531 // Drop key left on the stack by IC. |
519 __ add(Operand(esp), Immediate(kPointerSize)); | 532 __ add(Operand(esp), Immediate(kPointerSize)); |
520 } | 533 } |
521 switch (expr->location().type()) { | 534 switch (expr->location().type()) { |
522 case Location::TEMP: | 535 case Location::UNINITIALIZED: |
| 536 UNREACHABLE(); |
| 537 case Location::VALUE: |
523 __ mov(Operand(esp, 0), eax); | 538 __ mov(Operand(esp, 0), eax); |
524 break; | 539 break; |
525 case Location::NOWHERE: | 540 case Location::EFFECT: |
526 __ add(Operand(esp), Immediate(kPointerSize)); | 541 __ add(Operand(esp), Immediate(kPointerSize)); |
527 break; | 542 break; |
528 } | 543 } |
529 } | 544 } |
530 | 545 |
531 | 546 |
532 void FastCodeGenerator::VisitCall(Call* expr) { | 547 void FastCodeGenerator::VisitCall(Call* expr) { |
533 Expression* fun = expr->expression(); | 548 Expression* fun = expr->expression(); |
534 ZoneList<Expression*>* args = expr->arguments(); | 549 ZoneList<Expression*>* args = expr->arguments(); |
535 Variable* var = fun->AsVariableProxy()->AsVariable(); | 550 Variable* var = fun->AsVariableProxy()->AsVariable(); |
536 ASSERT(var != NULL && !var->is_this() && var->is_global()); | 551 ASSERT(var != NULL && !var->is_this() && var->is_global()); |
537 ASSERT(!var->is_possibly_eval()); | 552 ASSERT(!var->is_possibly_eval()); |
538 | 553 |
539 __ push(Immediate(var->name())); | 554 __ push(Immediate(var->name())); |
540 // Push global object (receiver). | 555 // Push global object (receiver). |
541 __ push(CodeGenerator::GlobalObject()); | 556 __ push(CodeGenerator::GlobalObject()); |
542 int arg_count = args->length(); | 557 int arg_count = args->length(); |
543 for (int i = 0; i < arg_count; i++) { | 558 for (int i = 0; i < arg_count; i++) { |
544 Visit(args->at(i)); | 559 Visit(args->at(i)); |
545 ASSERT(args->at(i)->location().is_temporary()); | 560 ASSERT(args->at(i)->location().is_value()); |
546 } | 561 } |
547 // Record source position for debugger | 562 // Record source position for debugger |
548 SetSourcePosition(expr->position()); | 563 SetSourcePosition(expr->position()); |
549 // Call the IC initialization code. | 564 // Call the IC initialization code. |
550 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, | 565 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, |
551 NOT_IN_LOOP); | 566 NOT_IN_LOOP); |
552 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 567 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
553 // Restore context register. | 568 // Restore context register. |
554 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 569 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
555 // Discard the function left on TOS. | 570 // Discard the function left on TOS. |
556 DropAndMove(expr->location(), eax); | 571 DropAndMove(expr->location(), eax); |
557 } | 572 } |
558 | 573 |
559 | 574 |
560 void FastCodeGenerator::VisitCallNew(CallNew* node) { | 575 void FastCodeGenerator::VisitCallNew(CallNew* node) { |
561 Comment cmnt(masm_, "[ CallNew"); | 576 Comment cmnt(masm_, "[ CallNew"); |
562 // According to ECMA-262, section 11.2.2, page 44, the function | 577 // According to ECMA-262, section 11.2.2, page 44, the function |
563 // expression in new calls must be evaluated before the | 578 // expression in new calls must be evaluated before the |
564 // arguments. | 579 // arguments. |
565 // Push function on the stack. | 580 // Push function on the stack. |
566 Visit(node->expression()); | 581 Visit(node->expression()); |
567 ASSERT(node->expression()->location().is_temporary()); | 582 ASSERT(node->expression()->location().is_value()); |
568 | 583 |
569 // Push global object (receiver). | 584 // Push global object (receiver). |
570 __ push(CodeGenerator::GlobalObject()); | 585 __ push(CodeGenerator::GlobalObject()); |
571 | 586 |
572 // Push the arguments ("left-to-right") on the stack. | 587 // Push the arguments ("left-to-right") on the stack. |
573 ZoneList<Expression*>* args = node->arguments(); | 588 ZoneList<Expression*>* args = node->arguments(); |
574 int arg_count = args->length(); | 589 int arg_count = args->length(); |
575 for (int i = 0; i < arg_count; i++) { | 590 for (int i = 0; i < arg_count; i++) { |
576 Visit(args->at(i)); | 591 Visit(args->at(i)); |
577 ASSERT(args->at(i)->location().is_temporary()); | 592 ASSERT(args->at(i)->location().is_value()); |
578 // If location is temporary, it is already on the stack, | 593 // If location is temporary, it is already on the stack, |
579 // so nothing to do here. | 594 // so nothing to do here. |
580 } | 595 } |
581 | 596 |
582 // Call the construct call builtin that handles allocation and | 597 // Call the construct call builtin that handles allocation and |
583 // constructor invocation. | 598 // constructor invocation. |
584 SetSourcePosition(node->position()); | 599 SetSourcePosition(node->position()); |
585 | 600 |
586 // Load function, arg_count into edi and eax. | 601 // Load function, arg_count into edi and eax. |
587 __ Set(eax, Immediate(arg_count)); | 602 __ Set(eax, Immediate(arg_count)); |
(...skipping 12 matching lines...) Expand all Loading... |
600 Comment cmnt(masm_, "[ CallRuntime"); | 615 Comment cmnt(masm_, "[ CallRuntime"); |
601 ZoneList<Expression*>* args = expr->arguments(); | 616 ZoneList<Expression*>* args = expr->arguments(); |
602 Runtime::Function* function = expr->function(); | 617 Runtime::Function* function = expr->function(); |
603 | 618 |
604 ASSERT(function != NULL); | 619 ASSERT(function != NULL); |
605 | 620 |
606 // Push the arguments ("left-to-right"). | 621 // Push the arguments ("left-to-right"). |
607 int arg_count = args->length(); | 622 int arg_count = args->length(); |
608 for (int i = 0; i < arg_count; i++) { | 623 for (int i = 0; i < arg_count; i++) { |
609 Visit(args->at(i)); | 624 Visit(args->at(i)); |
610 ASSERT(args->at(i)->location().is_temporary()); | 625 ASSERT(args->at(i)->location().is_value()); |
611 } | 626 } |
612 | 627 |
613 __ CallRuntime(function, arg_count); | 628 __ CallRuntime(function, arg_count); |
614 Move(expr->location(), eax); | 629 Move(expr->location(), eax); |
615 } | 630 } |
616 | 631 |
617 | 632 |
618 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 633 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
619 // Compile a short-circuited boolean or operation in a non-test | 634 // Compile a short-circuited boolean or operation in a non-test |
620 // context. | 635 // context. |
621 ASSERT(expr->op() == Token::OR); | 636 ASSERT(expr->op() == Token::OR); |
622 // Compile (e0 || e1) as if it were | 637 // Compile (e0 || e1) as if it were |
623 // (let (temp = e0) temp ? temp : e1). | 638 // (let (temp = e0) temp ? temp : e1). |
624 | 639 |
625 Label eval_right, done; | 640 Label eval_right, done; |
626 Location destination = expr->location(); | 641 Location destination = expr->location(); |
627 Expression* left = expr->left(); | 642 Expression* left = expr->left(); |
628 Expression* right = expr->right(); | 643 Expression* right = expr->right(); |
629 | 644 |
630 // Use the shared ToBoolean stub to find the boolean value of the | 645 // Use the shared ToBoolean stub to find the boolean value of the |
631 // left-hand subexpression. Load the value into eax to perform some | 646 // left-hand subexpression. Load the value into eax to perform some |
632 // inlined checks assumed by the stub. | 647 // inlined checks assumed by the stub. |
633 | 648 |
634 // Compile the left-hand value into eax. Put it on the stack if we may | 649 // Compile the left-hand value into eax. Put it on the stack if we may |
635 // need it as the value of the whole expression. | 650 // need it as the value of the whole expression. |
636 if (left->AsLiteral() != NULL) { | 651 if (left->AsLiteral() != NULL) { |
637 __ mov(eax, left->AsLiteral()->handle()); | 652 __ mov(eax, left->AsLiteral()->handle()); |
638 if (destination.is_temporary()) __ push(eax); | 653 if (destination.is_value()) __ push(eax); |
639 } else { | 654 } else { |
640 Visit(left); | 655 Visit(left); |
641 ASSERT(left->location().is_temporary()); | 656 ASSERT(left->location().is_value()); |
642 switch (destination.type()) { | 657 switch (destination.type()) { |
643 case Location::NOWHERE: | 658 case Location::UNINITIALIZED: |
| 659 UNREACHABLE(); |
| 660 case Location::EFFECT: |
644 // Pop the left-hand value into eax because we will not need it as the | 661 // Pop the left-hand value into eax because we will not need it as the |
645 // final result. | 662 // final result. |
646 __ pop(eax); | 663 __ pop(eax); |
647 break; | 664 break; |
648 case Location::TEMP: | 665 case Location::VALUE: |
649 // Copy the left-hand value into eax because we may need it as the | 666 // Copy the left-hand value into eax because we may need it as the |
650 // final result. | 667 // final result. |
651 __ mov(eax, Operand(esp, 0)); | 668 __ mov(eax, Operand(esp, 0)); |
652 break; | 669 break; |
653 } | 670 } |
654 } | 671 } |
655 // The left-hand value is in eax. It is also on the stack iff the | 672 // The left-hand value is in eax. It is also on the stack iff the |
656 // destination location is temporary. | 673 // destination location is temporary. |
657 | 674 |
658 // Perform fast checks assumed by the stub. | 675 // Perform fast checks assumed by the stub. |
(...skipping 11 matching lines...) Expand all Loading... |
670 | 687 |
671 // Call the stub for all other cases. | 688 // Call the stub for all other cases. |
672 __ push(eax); | 689 __ push(eax); |
673 ToBooleanStub stub; | 690 ToBooleanStub stub; |
674 __ CallStub(&stub); | 691 __ CallStub(&stub); |
675 __ test(eax, Operand(eax)); // The stub returns nonzero for true. | 692 __ test(eax, Operand(eax)); // The stub returns nonzero for true. |
676 __ j(not_zero, &done); | 693 __ j(not_zero, &done); |
677 | 694 |
678 __ bind(&eval_right); | 695 __ bind(&eval_right); |
679 // Discard the left-hand value if present on the stack. | 696 // Discard the left-hand value if present on the stack. |
680 if (destination.is_temporary()) { | 697 if (destination.is_value()) { |
681 __ add(Operand(esp), Immediate(kPointerSize)); | 698 __ add(Operand(esp), Immediate(kPointerSize)); |
682 } | 699 } |
683 // Save or discard the right-hand value as needed. | 700 // Save or discard the right-hand value as needed. |
684 if (right->AsLiteral() != NULL) { | 701 if (right->AsLiteral() != NULL) { |
685 Move(destination, right->AsLiteral()); | 702 Move(destination, right->AsLiteral()); |
686 } else { | 703 } else { |
687 Visit(right); | 704 Visit(right); |
688 Move(destination, right->location()); | 705 Move(destination, right->location()); |
689 } | 706 } |
690 | 707 |
691 __ bind(&done); | 708 __ bind(&done); |
692 } | 709 } |
693 | 710 |
694 | 711 |
695 } } // namespace v8::internal | 712 } } // namespace v8::internal |
OLD | NEW |