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 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
187 #ifdef ENABLE_DEBUGGER_SUPPORT | 187 #ifdef ENABLE_DEBUGGER_SUPPORT |
188 // Check that the size of the code used for returning matches what is | 188 // Check that the size of the code used for returning matches what is |
189 // expected by the debugger. | 189 // expected by the debugger. |
190 ASSERT_EQ(Assembler::kJSReturnSequenceLength, | 190 ASSERT_EQ(Assembler::kJSReturnSequenceLength, |
191 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); | 191 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); |
192 #endif | 192 #endif |
193 } | 193 } |
194 } | 194 } |
195 | 195 |
196 | 196 |
197 void FastCodeGenerator::Move(Expression::Context context, Register source) { | 197 void FastCodeGenerator::Apply(Expression::Context context, |
198 Slot* slot, | |
199 Register scratch) { | |
Lasse Reichstein
2010/01/12 08:30:05
This function looks generic enough that it could b
| |
200 switch (context) { | |
201 case Expression::kUninitialized: | |
202 UNREACHABLE(); | |
203 case Expression::kEffect: | |
204 break; | |
205 case Expression::kValue: { | |
206 MemOperand location = EmitSlotSearch(slot, scratch); | |
207 __ push(location); | |
208 break; | |
209 } | |
210 case Expression::kTest: | |
211 case Expression::kValueTest: | |
212 case Expression::kTestValue: | |
213 Move(scratch, slot); | |
214 Apply(context, scratch); | |
215 break; | |
216 } | |
217 } | |
218 | |
219 | |
220 void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) { | |
Lasse Reichstein
2010/01/12 08:30:05
If we had MacroAssembler::Push(Handle<Object> sour
| |
198 switch (context) { | 221 switch (context) { |
199 case Expression::kUninitialized: | 222 case Expression::kUninitialized: |
200 UNREACHABLE(); | 223 UNREACHABLE(); |
201 case Expression::kEffect: | 224 case Expression::kEffect: |
202 break; | 225 break; |
203 case Expression::kValue: | 226 case Expression::kValue: |
204 __ push(source); | 227 __ push(Immediate(lit->handle())); |
205 break; | 228 break; |
206 case Expression::kTest: | 229 case Expression::kTest: |
207 TestAndBranch(source, true_label_, false_label_); | 230 case Expression::kValueTest: |
231 case Expression::kTestValue: | |
232 __ mov(eax, lit->handle()); | |
233 Apply(context, eax); | |
208 break; | 234 break; |
209 case Expression::kValueTest: { | |
210 Label discard; | |
211 __ push(source); | |
212 TestAndBranch(source, true_label_, &discard); | |
213 __ bind(&discard); | |
214 __ add(Operand(esp), Immediate(kPointerSize)); | |
215 __ jmp(false_label_); | |
216 break; | |
217 } | |
218 case Expression::kTestValue: { | |
219 Label discard; | |
220 __ push(source); | |
221 TestAndBranch(source, &discard, false_label_); | |
222 __ bind(&discard); | |
223 __ add(Operand(esp), Immediate(kPointerSize)); | |
224 __ jmp(true_label_); | |
225 } | |
226 } | 235 } |
227 } | 236 } |
228 | 237 |
229 | 238 |
230 void FastCodeGenerator::MoveTOS(Expression::Context context) { | 239 void FastCodeGenerator::ApplyTOS(Expression::Context context) { |
231 switch (context) { | 240 switch (context) { |
232 case Expression::kUninitialized: | 241 case Expression::kUninitialized: |
233 UNREACHABLE(); | 242 UNREACHABLE(); |
234 case Expression::kEffect: | 243 case Expression::kEffect: |
235 __ Drop(1); | 244 __ Drop(1); |
236 break; | 245 break; |
237 case Expression::kValue: | 246 case Expression::kValue: |
238 break; | 247 break; |
239 case Expression::kTest: | 248 case Expression::kTest: |
240 __ pop(eax); | 249 __ pop(eax); |
241 TestAndBranch(eax, true_label_, false_label_); | 250 TestAndBranch(eax, true_label_, false_label_); |
242 break; | 251 break; |
243 case Expression::kValueTest: { | 252 case Expression::kValueTest: { |
244 Label discard; | 253 Label discard; |
245 __ mov(eax, Operand(esp, 0)); | 254 __ mov(eax, Operand(esp, 0)); |
Lasse Reichstein
2010/01/12 08:30:05
With a function like MacroAssembler::MoveToStack(i
| |
246 TestAndBranch(eax, true_label_, &discard); | 255 TestAndBranch(eax, true_label_, &discard); |
247 __ bind(&discard); | 256 __ bind(&discard); |
248 __ Drop(1); | 257 __ Drop(1); |
249 __ jmp(false_label_); | 258 __ jmp(false_label_); |
259 break; | |
260 } | |
261 case Expression::kTestValue: { | |
262 Label discard; | |
263 __ mov(eax, Operand(esp, 0)); | |
264 TestAndBranch(eax, &discard, false_label_); | |
265 __ bind(&discard); | |
266 __ Drop(1); | |
267 __ jmp(true_label_); | |
268 } | |
269 } | |
270 } | |
271 | |
272 | |
273 void FastCodeGenerator::DropAndApply(int count, | |
274 Expression::Context context, | |
275 Register reg) { | |
Lasse Reichstein
2010/01/12 08:30:05
And this one too!
(A good abstraction of the stack
| |
276 ASSERT(count > 0); | |
277 ASSERT(!reg.is(esp)); | |
278 switch (context) { | |
279 case Expression::kUninitialized: | |
280 UNREACHABLE(); | |
281 case Expression::kEffect: | |
282 __ Drop(count); | |
283 break; | |
284 case Expression::kValue: | |
285 if (count > 1) __ Drop(count - 1); | |
286 __ mov(Operand(esp, 0), reg); | |
287 break; | |
288 case Expression::kTest: | |
289 __ Drop(count); | |
290 TestAndBranch(reg, true_label_, false_label_); | |
291 break; | |
292 case Expression::kValueTest: { | |
293 Label discard; | |
294 if (count > 1) __ Drop(count - 1); | |
295 __ mov(Operand(esp, 0), reg); | |
296 TestAndBranch(reg, true_label_, &discard); | |
297 __ bind(&discard); | |
298 __ Drop(1); | |
299 __ jmp(false_label_); | |
250 break; | 300 break; |
251 } | 301 } |
252 case Expression::kTestValue: { | 302 case Expression::kTestValue: { |
253 Label discard; | 303 Label discard; |
254 __ mov(eax, Operand(esp, 0)); | 304 if (count > 1) __ Drop(count - 1); |
255 TestAndBranch(eax, &discard, false_label_); | 305 __ mov(Operand(esp, 0), reg); |
306 TestAndBranch(reg, &discard, false_label_); | |
256 __ bind(&discard); | 307 __ bind(&discard); |
257 __ Drop(1); | 308 __ Drop(1); |
258 __ jmp(true_label_); | 309 __ jmp(true_label_); |
310 break; | |
259 } | 311 } |
260 } | 312 } |
261 } | 313 } |
262 | 314 |
263 | 315 |
264 MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { | 316 MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { |
265 switch (slot->type()) { | 317 switch (slot->type()) { |
266 case Slot::PARAMETER: | 318 case Slot::PARAMETER: |
267 case Slot::LOCAL: | 319 case Slot::LOCAL: |
268 return Operand(ebp, SlotOffset(slot)); | 320 return Operand(ebp, SlotOffset(slot)); |
(...skipping 10 matching lines...) Expand all Loading... | |
279 return Operand(eax, 0); | 331 return Operand(eax, 0); |
280 } | 332 } |
281 | 333 |
282 | 334 |
283 void FastCodeGenerator::Move(Register destination, Slot* source) { | 335 void FastCodeGenerator::Move(Register destination, Slot* source) { |
284 MemOperand location = EmitSlotSearch(source, destination); | 336 MemOperand location = EmitSlotSearch(source, destination); |
285 __ mov(destination, location); | 337 __ mov(destination, location); |
286 } | 338 } |
287 | 339 |
288 | 340 |
289 void FastCodeGenerator::Move(Expression::Context context, | |
290 Slot* source, | |
291 Register scratch) { | |
292 switch (context) { | |
293 case Expression::kUninitialized: | |
294 UNREACHABLE(); | |
295 case Expression::kEffect: | |
296 break; | |
297 case Expression::kValue: { | |
298 MemOperand location = EmitSlotSearch(source, scratch); | |
299 __ push(location); | |
300 break; | |
301 } | |
302 case Expression::kTest: | |
303 case Expression::kValueTest: | |
304 case Expression::kTestValue: | |
305 Move(scratch, source); | |
306 Move(context, scratch); | |
307 break; | |
308 } | |
309 } | |
310 | |
311 | |
312 void FastCodeGenerator::Move(Expression::Context context, Literal* expr) { | |
313 switch (context) { | |
314 case Expression::kUninitialized: | |
315 UNREACHABLE(); | |
316 case Expression::kEffect: | |
317 break; | |
318 case Expression::kValue: | |
319 __ push(Immediate(expr->handle())); | |
320 break; | |
321 case Expression::kTest: | |
322 case Expression::kValueTest: | |
323 case Expression::kTestValue: | |
324 __ mov(eax, expr->handle()); | |
325 Move(context, eax); | |
326 break; | |
327 } | |
328 } | |
329 | |
330 | |
331 void FastCodeGenerator::Move(Slot* dst, | 341 void FastCodeGenerator::Move(Slot* dst, |
332 Register src, | 342 Register src, |
333 Register scratch1, | 343 Register scratch1, |
334 Register scratch2) { | 344 Register scratch2) { |
335 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. | 345 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. |
336 ASSERT(!scratch1.is(src) && !scratch2.is(src)); | 346 ASSERT(!scratch1.is(src) && !scratch2.is(src)); |
337 MemOperand location = EmitSlotSearch(dst, scratch1); | 347 MemOperand location = EmitSlotSearch(dst, scratch1); |
338 __ mov(location, src); | 348 __ mov(location, src); |
339 // Emit the write barrier code if the location is in the heap. | 349 // Emit the write barrier code if the location is in the heap. |
340 if (dst->type() == Slot::CONTEXT) { | 350 if (dst->type() == Slot::CONTEXT) { |
341 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; | 351 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; |
342 __ RecordWrite(scratch1, offset, src, scratch2); | 352 __ RecordWrite(scratch1, offset, src, scratch2); |
343 } | 353 } |
344 } | 354 } |
345 | 355 |
346 | 356 |
347 void FastCodeGenerator::DropAndMove(Expression::Context context, | |
348 Register source, | |
349 int count) { | |
350 ASSERT(count > 0); | |
351 switch (context) { | |
352 case Expression::kUninitialized: | |
353 UNREACHABLE(); | |
354 case Expression::kEffect: | |
355 __ add(Operand(esp), Immediate(count * kPointerSize)); | |
356 break; | |
357 case Expression::kValue: | |
358 if (count > 1) { | |
359 __ add(Operand(esp), Immediate((count - 1) * kPointerSize)); | |
360 } | |
361 __ mov(Operand(esp, 0), source); | |
362 break; | |
363 case Expression::kTest: | |
364 ASSERT(!source.is(esp)); | |
365 __ add(Operand(esp), Immediate(count * kPointerSize)); | |
366 TestAndBranch(source, true_label_, false_label_); | |
367 break; | |
368 case Expression::kValueTest: { | |
369 Label discard; | |
370 if (count > 1) { | |
371 __ add(Operand(esp), Immediate((count - 1) * kPointerSize)); | |
372 } | |
373 __ mov(Operand(esp, 0), source); | |
374 TestAndBranch(source, true_label_, &discard); | |
375 __ bind(&discard); | |
376 __ add(Operand(esp), Immediate(kPointerSize)); | |
377 __ jmp(false_label_); | |
378 break; | |
379 } | |
380 case Expression::kTestValue: { | |
381 Label discard; | |
382 if (count > 1) { | |
383 __ add(Operand(esp), Immediate((count - 1) * kPointerSize)); | |
384 } | |
385 __ mov(Operand(esp, 0), source); | |
386 TestAndBranch(source, &discard, false_label_); | |
387 __ bind(&discard); | |
388 __ add(Operand(esp), Immediate(kPointerSize)); | |
389 __ jmp(true_label_); | |
390 break; | |
391 } | |
392 } | |
393 } | |
394 | |
395 | |
396 void FastCodeGenerator::TestAndBranch(Register source, | 357 void FastCodeGenerator::TestAndBranch(Register source, |
397 Label* true_label, | 358 Label* true_label, |
398 Label* false_label) { | 359 Label* false_label) { |
399 ASSERT_NE(NULL, true_label); | 360 ASSERT_NE(NULL, true_label); |
400 ASSERT_NE(NULL, false_label); | 361 ASSERT_NE(NULL, false_label); |
401 // Use the shared ToBoolean stub to compile the value in the register into | 362 // Use the shared ToBoolean stub to compile the value in the register into |
402 // control flow to the code generator's true and false labels. Perform | 363 // control flow to the code generator's true and false labels. Perform |
403 // the fast checks assumed by the stub. | 364 // the fast checks assumed by the stub. |
404 __ cmp(source, Factory::undefined_value()); // The undefined value is false. | 365 __ cmp(source, Factory::undefined_value()); // The undefined value is false. |
405 __ j(equal, false_label); | 366 __ j(equal, false_label); |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
511 __ Set(eax, Immediate(Factory::the_hole_value())); | 472 __ Set(eax, Immediate(Factory::the_hole_value())); |
512 } | 473 } |
513 | 474 |
514 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 475 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
515 __ call(ic, RelocInfo::CODE_TARGET); | 476 __ call(ic, RelocInfo::CODE_TARGET); |
516 // Absence of a test eax instruction following the call | 477 // Absence of a test eax instruction following the call |
517 // indicates that none of the load was inlined. | 478 // indicates that none of the load was inlined. |
518 | 479 |
519 // Value in eax is ignored (declarations are statements). Receiver | 480 // Value in eax is ignored (declarations are statements). Receiver |
520 // and key on stack are discarded. | 481 // and key on stack are discarded. |
521 __ add(Operand(esp), Immediate(2 * kPointerSize)); | 482 __ Drop(2); |
522 } | 483 } |
523 } | 484 } |
524 } | 485 } |
525 | 486 |
526 | 487 |
527 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 488 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
528 // Call the runtime to declare the globals. | 489 // Call the runtime to declare the globals. |
529 __ push(esi); // The context is the first argument. | 490 __ push(esi); // The context is the first argument. |
530 __ push(Immediate(pairs)); | 491 __ push(Immediate(pairs)); |
531 __ push(Immediate(Smi::FromInt(is_eval_ ? 1 : 0))); | 492 __ push(Immediate(Smi::FromInt(is_eval_ ? 1 : 0))); |
532 __ CallRuntime(Runtime::kDeclareGlobals, 3); | 493 __ CallRuntime(Runtime::kDeclareGlobals, 3); |
533 // Return value is ignored. | 494 // Return value is ignored. |
534 } | 495 } |
535 | 496 |
536 | 497 |
537 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { | 498 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { |
538 Comment cmnt(masm_, "[ FunctionLiteral"); | 499 Comment cmnt(masm_, "[ FunctionLiteral"); |
539 | 500 |
540 // Build the function boilerplate and instantiate it. | 501 // Build the function boilerplate and instantiate it. |
541 Handle<JSFunction> boilerplate = | 502 Handle<JSFunction> boilerplate = |
542 Compiler::BuildBoilerplate(expr, script_, this); | 503 Compiler::BuildBoilerplate(expr, script_, this); |
543 if (HasStackOverflow()) return; | 504 if (HasStackOverflow()) return; |
544 | 505 |
545 ASSERT(boilerplate->IsBoilerplate()); | 506 ASSERT(boilerplate->IsBoilerplate()); |
546 | 507 |
547 // Create a new closure. | 508 // Create a new closure. |
548 __ push(esi); | 509 __ push(esi); |
549 __ push(Immediate(boilerplate)); | 510 __ push(Immediate(boilerplate)); |
550 __ CallRuntime(Runtime::kNewClosure, 2); | 511 __ CallRuntime(Runtime::kNewClosure, 2); |
551 Move(expr->context(), eax); | 512 Apply(expr->context(), eax); |
552 } | 513 } |
553 | 514 |
554 | 515 |
555 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 516 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
556 Comment cmnt(masm_, "[ VariableProxy"); | 517 Comment cmnt(masm_, "[ VariableProxy"); |
557 EmitVariableLoad(expr->var(), expr->context()); | 518 EmitVariableLoad(expr->var(), expr->context()); |
558 } | 519 } |
559 | 520 |
560 | 521 |
561 void FastCodeGenerator::EmitVariableLoad(Variable* var, | 522 void FastCodeGenerator::EmitVariableLoad(Variable* var, |
562 Expression::Context context) { | 523 Expression::Context context) { |
563 Expression* rewrite = var->rewrite(); | 524 Expression* rewrite = var->rewrite(); |
564 if (rewrite == NULL) { | 525 if (rewrite == NULL) { |
565 ASSERT(var->is_global()); | 526 ASSERT(var->is_global()); |
566 Comment cmnt(masm_, "Global variable"); | 527 Comment cmnt(masm_, "Global variable"); |
567 // Use inline caching. Variable name is passed in ecx and the global | 528 // Use inline caching. Variable name is passed in ecx and the global |
568 // object on the stack. | 529 // object on the stack. |
569 __ push(CodeGenerator::GlobalObject()); | 530 __ push(CodeGenerator::GlobalObject()); |
570 __ mov(ecx, var->name()); | 531 __ mov(ecx, var->name()); |
571 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 532 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
572 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 533 __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
573 // By emitting a nop we make sure that we do not have a test eax | 534 // By emitting a nop we make sure that we do not have a test eax |
574 // instruction after the call it is treated specially by the LoadIC code | 535 // instruction after the call it is treated specially by the LoadIC code |
575 // Remember that the assembler may choose to do peephole optimization | 536 // Remember that the assembler may choose to do peephole optimization |
576 // (eg, push/pop elimination). | 537 // (eg, push/pop elimination). |
577 __ nop(); | 538 __ nop(); |
578 DropAndMove(context, eax); | 539 DropAndApply(1, context, eax); |
579 } else if (rewrite->AsSlot() != NULL) { | 540 } else if (rewrite->AsSlot() != NULL) { |
580 Slot* slot = rewrite->AsSlot(); | 541 Slot* slot = rewrite->AsSlot(); |
581 if (FLAG_debug_code) { | 542 if (FLAG_debug_code) { |
582 switch (slot->type()) { | 543 switch (slot->type()) { |
583 case Slot::PARAMETER: | 544 case Slot::PARAMETER: |
584 case Slot::LOCAL: { | 545 case Slot::LOCAL: { |
585 Comment cmnt(masm_, "Stack slot"); | 546 Comment cmnt(masm_, "Stack slot"); |
586 break; | 547 break; |
587 } | 548 } |
588 case Slot::CONTEXT: { | 549 case Slot::CONTEXT: { |
589 Comment cmnt(masm_, "Context slot"); | 550 Comment cmnt(masm_, "Context slot"); |
590 break; | 551 break; |
591 } | 552 } |
592 case Slot::LOOKUP: | 553 case Slot::LOOKUP: |
593 UNIMPLEMENTED(); | 554 UNIMPLEMENTED(); |
594 break; | 555 break; |
595 } | 556 } |
596 } | 557 } |
597 Move(context, slot, eax); | 558 Apply(context, slot, eax); |
598 } else { | 559 } else { |
599 Comment cmnt(masm_, "Variable rewritten to Property"); | 560 Comment cmnt(masm_, "Variable rewritten to property"); |
600 // A variable has been rewritten into an explicit access to | 561 // A variable has been rewritten into an explicit access to an object |
601 // an object property. | 562 // property. |
602 Property* property = rewrite->AsProperty(); | 563 Property* property = rewrite->AsProperty(); |
603 ASSERT_NOT_NULL(property); | 564 ASSERT_NOT_NULL(property); |
604 | 565 |
605 // Currently the only parameter expressions that can occur are | 566 // The only property expressions that can occur are of the form |
606 // on the form "slot[literal]". | 567 // "slot[literal]". |
607 | 568 |
608 // Check that the object is in a slot. | 569 // Assert that the object is in a slot. |
609 Variable* object_var = property->obj()->AsVariableProxy()->AsVariable(); | 570 Variable* object_var = property->obj()->AsVariableProxy()->AsVariable(); |
610 ASSERT_NOT_NULL(object_var); | 571 ASSERT_NOT_NULL(object_var); |
611 Slot* object_slot = object_var->slot(); | 572 Slot* object_slot = object_var->slot(); |
612 ASSERT_NOT_NULL(object_slot); | 573 ASSERT_NOT_NULL(object_slot); |
613 | 574 |
614 // Load the object. | 575 // Load the object. |
615 Move(Expression::kValue, object_slot, eax); | 576 MemOperand object_loc = EmitSlotSearch(object_slot, eax); |
577 __ push(object_loc); | |
616 | 578 |
617 // Check that the key is a smi. | 579 // Assert that the key is a smi. |
618 Literal* key_literal = property->key()->AsLiteral(); | 580 Literal* key_literal = property->key()->AsLiteral(); |
619 ASSERT_NOT_NULL(key_literal); | 581 ASSERT_NOT_NULL(key_literal); |
620 ASSERT(key_literal->handle()->IsSmi()); | 582 ASSERT(key_literal->handle()->IsSmi()); |
621 | 583 |
622 // Load the key. | 584 // Load the key. |
623 Move(Expression::kValue, key_literal); | 585 __ push(Immediate(key_literal->handle())); |
624 | 586 |
625 // Do a KEYED property load. | 587 // Do a keyed property load. |
626 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 588 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
627 __ call(ic, RelocInfo::CODE_TARGET); | 589 __ call(ic, RelocInfo::CODE_TARGET); |
628 // Notice: We must not have a "test eax, ..." instruction after | 590 // Notice: We must not have a "test eax, ..." instruction after the |
629 // the call. It is treated specially by the LoadIC code. | 591 // call. It is treated specially by the LoadIC code. |
630 __ nop(); | 592 __ nop(); |
Lasse Reichstein
2010/01/12 08:30:05
Can we assume that DropAndMove does not start with
| |
631 // Drop key and object left on the stack by IC. | 593 // Drop key and object left on the stack by IC. |
632 DropAndMove(context, eax, 2); | 594 DropAndApply(2, context, eax); |
633 } | 595 } |
634 } | 596 } |
635 | 597 |
636 | 598 |
637 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 599 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
638 Comment cmnt(masm_, "[ RegExpLiteral"); | 600 Comment cmnt(masm_, "[ RegExpLiteral"); |
639 Label done; | 601 Label done; |
640 // Registers will be used as follows: | 602 // Registers will be used as follows: |
641 // edi = JS function. | 603 // edi = JS function. |
642 // ebx = literals array. | 604 // ebx = literals array. |
643 // eax = regexp literal. | 605 // eax = regexp literal. |
644 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 606 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
645 __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset)); | 607 __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset)); |
646 int literal_offset = | 608 int literal_offset = |
647 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; | 609 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
648 __ mov(eax, FieldOperand(ebx, literal_offset)); | 610 __ mov(eax, FieldOperand(ebx, literal_offset)); |
649 __ cmp(eax, Factory::undefined_value()); | 611 __ cmp(eax, Factory::undefined_value()); |
650 __ j(not_equal, &done); | 612 __ j(not_equal, &done); |
651 // Create regexp literal using runtime function | 613 // Create regexp literal using runtime function |
652 // Result will be in eax. | 614 // Result will be in eax. |
653 __ push(ebx); | 615 __ push(ebx); |
654 __ push(Immediate(Smi::FromInt(expr->literal_index()))); | 616 __ push(Immediate(Smi::FromInt(expr->literal_index()))); |
655 __ push(Immediate(expr->pattern())); | 617 __ push(Immediate(expr->pattern())); |
656 __ push(Immediate(expr->flags())); | 618 __ push(Immediate(expr->flags())); |
657 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); | 619 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
658 // Label done: | 620 // Label done: |
659 __ bind(&done); | 621 __ bind(&done); |
660 Move(expr->context(), eax); | 622 Apply(expr->context(), eax); |
661 } | 623 } |
662 | 624 |
663 | 625 |
664 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 626 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
665 Comment cmnt(masm_, "[ ObjectLiteral"); | 627 Comment cmnt(masm_, "[ ObjectLiteral"); |
666 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 628 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
667 __ push(FieldOperand(edi, JSFunction::kLiteralsOffset)); | 629 __ push(FieldOperand(edi, JSFunction::kLiteralsOffset)); |
668 __ push(Immediate(Smi::FromInt(expr->literal_index()))); | 630 __ push(Immediate(Smi::FromInt(expr->literal_index()))); |
669 __ push(Immediate(expr->constant_properties())); | 631 __ push(Immediate(expr->constant_properties())); |
670 if (expr->depth() > 1) { | 632 if (expr->depth() > 1) { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
726 __ CallRuntime(Runtime::kDefineAccessor, 4); | 688 __ CallRuntime(Runtime::kDefineAccessor, 4); |
727 __ mov(eax, Operand(esp, 0)); // Restore result into eax. | 689 __ mov(eax, Operand(esp, 0)); // Restore result into eax. |
728 break; | 690 break; |
729 default: UNREACHABLE(); | 691 default: UNREACHABLE(); |
730 } | 692 } |
731 } | 693 } |
732 switch (expr->context()) { | 694 switch (expr->context()) { |
733 case Expression::kUninitialized: | 695 case Expression::kUninitialized: |
734 UNREACHABLE(); | 696 UNREACHABLE(); |
735 case Expression::kEffect: | 697 case Expression::kEffect: |
736 if (result_saved) __ add(Operand(esp), Immediate(kPointerSize)); | 698 if (result_saved) __ Drop(1); |
737 break; | 699 break; |
738 case Expression::kValue: | 700 case Expression::kValue: |
739 if (!result_saved) __ push(eax); | 701 if (!result_saved) __ push(eax); |
740 break; | 702 break; |
741 case Expression::kTest: | 703 case Expression::kTest: |
742 if (result_saved) __ pop(eax); | 704 if (result_saved) __ pop(eax); |
743 TestAndBranch(eax, true_label_, false_label_); | 705 TestAndBranch(eax, true_label_, false_label_); |
744 break; | 706 break; |
745 case Expression::kValueTest: { | 707 case Expression::kValueTest: { |
746 Label discard; | 708 Label discard; |
747 if (!result_saved) __ push(eax); | 709 if (!result_saved) __ push(eax); |
748 TestAndBranch(eax, true_label_, &discard); | 710 TestAndBranch(eax, true_label_, &discard); |
749 __ bind(&discard); | 711 __ bind(&discard); |
750 __ add(Operand(esp), Immediate(kPointerSize)); | 712 __ Drop(1); |
751 __ jmp(false_label_); | 713 __ jmp(false_label_); |
752 break; | 714 break; |
753 } | 715 } |
754 case Expression::kTestValue: { | 716 case Expression::kTestValue: { |
755 Label discard; | 717 Label discard; |
756 if (!result_saved) __ push(eax); | 718 if (!result_saved) __ push(eax); |
757 TestAndBranch(eax, &discard, false_label_); | 719 TestAndBranch(eax, &discard, false_label_); |
758 __ bind(&discard); | 720 __ bind(&discard); |
759 __ add(Operand(esp), Immediate(kPointerSize)); | 721 __ Drop (1); |
760 __ jmp(true_label_); | 722 __ jmp(true_label_); |
761 break; | 723 break; |
762 } | 724 } |
763 } | 725 } |
764 } | 726 } |
765 | 727 |
766 | 728 |
767 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 729 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
768 Comment cmnt(masm_, "[ ArrayLiteral"); | 730 Comment cmnt(masm_, "[ ArrayLiteral"); |
769 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 731 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
805 __ mov(FieldOperand(ebx, offset), eax); | 767 __ mov(FieldOperand(ebx, offset), eax); |
806 | 768 |
807 // Update the write barrier for the array store. | 769 // Update the write barrier for the array store. |
808 __ RecordWrite(ebx, offset, eax, ecx); | 770 __ RecordWrite(ebx, offset, eax, ecx); |
809 } | 771 } |
810 | 772 |
811 switch (expr->context()) { | 773 switch (expr->context()) { |
812 case Expression::kUninitialized: | 774 case Expression::kUninitialized: |
813 UNREACHABLE(); | 775 UNREACHABLE(); |
814 case Expression::kEffect: | 776 case Expression::kEffect: |
815 if (result_saved) __ add(Operand(esp), Immediate(kPointerSize)); | 777 if (result_saved) __ Drop(1); |
816 break; | 778 break; |
817 case Expression::kValue: | 779 case Expression::kValue: |
818 if (!result_saved) __ push(eax); | 780 if (!result_saved) __ push(eax); |
819 break; | 781 break; |
820 case Expression::kTest: | 782 case Expression::kTest: |
821 if (result_saved) __ pop(eax); | 783 if (result_saved) __ pop(eax); |
822 TestAndBranch(eax, true_label_, false_label_); | 784 TestAndBranch(eax, true_label_, false_label_); |
823 break; | 785 break; |
824 case Expression::kValueTest: { | 786 case Expression::kValueTest: { |
825 Label discard; | 787 Label discard; |
826 if (!result_saved) __ push(eax); | 788 if (!result_saved) __ push(eax); |
827 TestAndBranch(eax, true_label_, &discard); | 789 TestAndBranch(eax, true_label_, &discard); |
828 __ bind(&discard); | 790 __ bind(&discard); |
829 __ add(Operand(esp), Immediate(kPointerSize)); | 791 __ Drop(1); |
830 __ jmp(false_label_); | 792 __ jmp(false_label_); |
831 break; | 793 break; |
832 } | 794 } |
833 case Expression::kTestValue: { | 795 case Expression::kTestValue: { |
834 Label discard; | 796 Label discard; |
835 if (!result_saved) __ push(eax); | 797 if (!result_saved) __ push(eax); |
836 TestAndBranch(eax, &discard, false_label_); | 798 TestAndBranch(eax, &discard, false_label_); |
837 __ bind(&discard); | 799 __ bind(&discard); |
838 __ add(Operand(esp), Immediate(kPointerSize)); | 800 __ Drop(1); |
839 __ jmp(true_label_); | 801 __ jmp(true_label_); |
840 break; | 802 break; |
841 } | 803 } |
842 } | 804 } |
843 } | 805 } |
844 | 806 |
845 | 807 |
846 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop, | 808 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop, |
847 Expression::Context context) { | 809 Expression::Context context) { |
848 SetSourcePosition(prop->position()); | 810 SetSourcePosition(prop->position()); |
849 Literal* key = prop->key()->AsLiteral(); | 811 Literal* key = prop->key()->AsLiteral(); |
850 __ mov(ecx, Immediate(key->handle())); | 812 __ mov(ecx, Immediate(key->handle())); |
851 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 813 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
852 __ call(ic, RelocInfo::CODE_TARGET); | 814 __ call(ic, RelocInfo::CODE_TARGET); |
853 Move(context, eax); | 815 Apply(context, eax); |
854 } | 816 } |
855 | 817 |
856 | 818 |
857 void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop, | 819 void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop, |
858 Expression::Context context) { | 820 Expression::Context context) { |
859 SetSourcePosition(prop->position()); | 821 SetSourcePosition(prop->position()); |
860 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 822 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
861 __ call(ic, RelocInfo::CODE_TARGET); | 823 __ call(ic, RelocInfo::CODE_TARGET); |
862 Move(context, eax); | 824 Apply(context, eax); |
863 } | 825 } |
864 | 826 |
865 | 827 |
866 void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op, | 828 void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op, |
867 Expression::Context context) { | 829 Expression::Context context) { |
868 GenericBinaryOpStub stub(op, | 830 GenericBinaryOpStub stub(op, |
869 NO_OVERWRITE, | 831 NO_OVERWRITE, |
870 NO_GENERIC_BINARY_FLAGS); | 832 NO_GENERIC_BINARY_FLAGS); |
871 __ CallStub(&stub); | 833 __ CallStub(&stub); |
872 Move(context, eax); | 834 Apply(context, eax); |
873 } | 835 } |
874 | 836 |
875 | 837 |
876 void FastCodeGenerator::EmitVariableAssignment(Variable* var, | 838 void FastCodeGenerator::EmitVariableAssignment(Variable* var, |
877 Expression::Context context) { | 839 Expression::Context context) { |
878 ASSERT(var != NULL); | 840 ASSERT(var != NULL); |
879 ASSERT(var->is_global() || var->slot() != NULL); | 841 ASSERT(var->is_global() || var->slot() != NULL); |
880 if (var->is_global()) { | 842 if (var->is_global()) { |
881 // Assignment to a global variable. Use inline caching for the | 843 // Assignment to a global variable. Use inline caching for the |
882 // assignment. Right-hand-side value is passed in eax, variable name in | 844 // assignment. Right-hand-side value is passed in eax, variable name in |
883 // ecx, and the global object on the stack. | 845 // ecx, and the global object on the stack. |
884 __ pop(eax); | 846 __ pop(eax); |
885 __ mov(ecx, var->name()); | 847 __ mov(ecx, var->name()); |
886 __ push(CodeGenerator::GlobalObject()); | 848 __ push(CodeGenerator::GlobalObject()); |
887 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 849 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
888 __ call(ic, RelocInfo::CODE_TARGET); | 850 __ call(ic, RelocInfo::CODE_TARGET); |
889 // Overwrite the receiver on the stack with the result if needed. | 851 // Overwrite the receiver on the stack with the result if needed. |
890 DropAndMove(context, eax); | 852 DropAndApply(1, context, eax); |
891 | 853 |
892 } else if (var->slot() != NULL) { | 854 } else if (var->slot() != NULL) { |
893 Slot* slot = var->slot(); | 855 Slot* slot = var->slot(); |
894 switch (slot->type()) { | 856 switch (slot->type()) { |
895 case Slot::LOCAL: | 857 case Slot::LOCAL: |
896 case Slot::PARAMETER: { | 858 case Slot::PARAMETER: { |
897 Operand target = Operand(ebp, SlotOffset(slot)); | 859 Operand target = Operand(ebp, SlotOffset(slot)); |
898 switch (context) { | 860 switch (context) { |
899 case Expression::kUninitialized: | 861 case Expression::kUninitialized: |
900 UNREACHABLE(); | 862 UNREACHABLE(); |
(...skipping 11 matching lines...) Expand all Loading... | |
912 __ pop(eax); | 874 __ pop(eax); |
913 __ mov(target, eax); | 875 __ mov(target, eax); |
914 TestAndBranch(eax, true_label_, false_label_); | 876 TestAndBranch(eax, true_label_, false_label_); |
915 break; | 877 break; |
916 case Expression::kValueTest: { | 878 case Expression::kValueTest: { |
917 Label discard; | 879 Label discard; |
918 __ mov(eax, Operand(esp, 0)); | 880 __ mov(eax, Operand(esp, 0)); |
919 __ mov(target, eax); | 881 __ mov(target, eax); |
920 TestAndBranch(eax, true_label_, &discard); | 882 TestAndBranch(eax, true_label_, &discard); |
921 __ bind(&discard); | 883 __ bind(&discard); |
922 __ add(Operand(esp), Immediate(kPointerSize)); | 884 __ Drop(1); |
923 __ jmp(false_label_); | 885 __ jmp(false_label_); |
924 break; | 886 break; |
925 } | 887 } |
926 case Expression::kTestValue: { | 888 case Expression::kTestValue: { |
927 Label discard; | 889 Label discard; |
928 __ mov(eax, Operand(esp, 0)); | 890 __ mov(eax, Operand(esp, 0)); |
929 __ mov(target, eax); | 891 __ mov(target, eax); |
930 TestAndBranch(eax, &discard, false_label_); | 892 TestAndBranch(eax, &discard, false_label_); |
931 __ bind(&discard); | 893 __ bind(&discard); |
932 __ add(Operand(esp), Immediate(kPointerSize)); | 894 __ Drop(1); |
933 __ jmp(true_label_); | 895 __ jmp(true_label_); |
934 break; | 896 break; |
935 } | 897 } |
936 } | 898 } |
937 break; | 899 break; |
938 } | 900 } |
939 | 901 |
940 case Slot::CONTEXT: { | 902 case Slot::CONTEXT: { |
941 MemOperand target = EmitSlotSearch(slot, ecx); | 903 MemOperand target = EmitSlotSearch(slot, ecx); |
942 __ pop(eax); | 904 __ pop(eax); |
943 __ mov(target, eax); | 905 __ mov(target, eax); |
944 | 906 |
945 // RecordWrite may destroy all its register arguments. | 907 // RecordWrite may destroy all its register arguments. |
946 if (context == Expression::kValue) { | 908 if (context == Expression::kValue) { |
947 __ push(eax); | 909 __ push(eax); |
948 } else if (context != Expression::kEffect) { | 910 } else if (context != Expression::kEffect) { |
949 __ mov(edx, eax); | 911 __ mov(edx, eax); |
950 } | 912 } |
951 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; | 913 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; |
952 __ RecordWrite(ecx, offset, eax, ebx); | 914 __ RecordWrite(ecx, offset, eax, ebx); |
953 if (context != Expression::kEffect && | 915 if (context != Expression::kEffect && context != Expression::kValue) { |
954 context != Expression::kValue) { | 916 Apply(context, edx); |
955 Move(context, edx); | |
956 } | 917 } |
957 break; | 918 break; |
958 } | 919 } |
959 | 920 |
960 case Slot::LOOKUP: | 921 case Slot::LOOKUP: |
961 UNREACHABLE(); | 922 UNREACHABLE(); |
962 break; | 923 break; |
963 } | 924 } |
964 } else { | 925 } else { |
965 // Variables rewritten as properties are not treated as variables in | 926 // Variables rewritten as properties are not treated as variables in |
(...skipping 23 matching lines...) Expand all Loading... | |
989 __ call(ic, RelocInfo::CODE_TARGET); | 950 __ call(ic, RelocInfo::CODE_TARGET); |
990 | 951 |
991 // If the assignment ends an initialization block, revert to fast case. | 952 // If the assignment ends an initialization block, revert to fast case. |
992 if (expr->ends_initialization_block()) { | 953 if (expr->ends_initialization_block()) { |
993 __ push(eax); // Result of assignment, saved even if not needed. | 954 __ push(eax); // Result of assignment, saved even if not needed. |
994 __ push(Operand(esp, kPointerSize)); // Receiver is under value. | 955 __ push(Operand(esp, kPointerSize)); // Receiver is under value. |
995 __ CallRuntime(Runtime::kToFastProperties, 1); | 956 __ CallRuntime(Runtime::kToFastProperties, 1); |
996 __ pop(eax); | 957 __ pop(eax); |
997 } | 958 } |
998 | 959 |
999 DropAndMove(expr->context(), eax); | 960 DropAndApply(1, expr->context(), eax); |
1000 } | 961 } |
1001 | 962 |
1002 | 963 |
1003 void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 964 void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
1004 // Assignment to a property, using a keyed store IC. | 965 // Assignment to a property, using a keyed store IC. |
1005 | 966 |
1006 // If the assignment starts a block of assignments to the same object, | 967 // If the assignment starts a block of assignments to the same object, |
1007 // change to slow case to avoid the quadratic behavior of repeatedly | 968 // change to slow case to avoid the quadratic behavior of repeatedly |
1008 // adding fast properties. | 969 // adding fast properties. |
1009 if (expr->starts_initialization_block()) { | 970 if (expr->starts_initialization_block()) { |
(...skipping 12 matching lines...) Expand all Loading... | |
1022 // If the assignment ends an initialization block, revert to fast case. | 983 // If the assignment ends an initialization block, revert to fast case. |
1023 if (expr->ends_initialization_block()) { | 984 if (expr->ends_initialization_block()) { |
1024 __ push(eax); // Result of assignment, saved even if not needed. | 985 __ push(eax); // Result of assignment, saved even if not needed. |
1025 // Reciever is under the key and value. | 986 // Reciever is under the key and value. |
1026 __ push(Operand(esp, 2 * kPointerSize)); | 987 __ push(Operand(esp, 2 * kPointerSize)); |
1027 __ CallRuntime(Runtime::kToFastProperties, 1); | 988 __ CallRuntime(Runtime::kToFastProperties, 1); |
1028 __ pop(eax); | 989 __ pop(eax); |
1029 } | 990 } |
1030 | 991 |
1031 // Receiver and key are still on stack. | 992 // Receiver and key are still on stack. |
1032 __ add(Operand(esp), Immediate(2 * kPointerSize)); | 993 DropAndApply(2, expr->context(), eax); |
1033 Move(expr->context(), eax); | |
1034 } | 994 } |
1035 | 995 |
1036 | 996 |
1037 void FastCodeGenerator::VisitProperty(Property* expr) { | 997 void FastCodeGenerator::VisitProperty(Property* expr) { |
1038 Comment cmnt(masm_, "[ Property"); | 998 Comment cmnt(masm_, "[ Property"); |
1039 Expression* key = expr->key(); | 999 Expression* key = expr->key(); |
1040 uint32_t dummy; | |
1041 | 1000 |
1042 // Record the source position for the property load. | 1001 // Record the source position for the property load. |
1043 SetSourcePosition(expr->position()); | 1002 SetSourcePosition(expr->position()); |
1044 | 1003 |
1045 // Evaluate receiver. | 1004 // Evaluate the receiver. |
1046 Visit(expr->obj()); | 1005 Visit(expr->obj()); |
1047 | 1006 |
1048 if (key->AsLiteral() != NULL && key->AsLiteral()->handle()->IsSymbol() && | 1007 if (key->IsPropertyName()) { |
1049 !String::cast(*(key->AsLiteral()->handle()))->AsArrayIndex(&dummy)) { | 1008 // Do a named property load. The IC expects the property name in ecx |
1050 // Do a NAMED property load. | 1009 // and the receiver on the stack. |
1051 // The IC expects the property name in ecx and the receiver on the stack. | |
1052 __ mov(ecx, Immediate(key->AsLiteral()->handle())); | 1010 __ mov(ecx, Immediate(key->AsLiteral()->handle())); |
1053 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1011 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
1054 __ call(ic, RelocInfo::CODE_TARGET); | 1012 __ call(ic, RelocInfo::CODE_TARGET); |
1055 // By emitting a nop we make sure that we do not have a test eax | 1013 // By emitting a nop we make sure that we do not have a test eax |
1056 // instruction after the call it is treated specially by the LoadIC code. | 1014 // instruction after the call it is treated specially by the LoadIC code. |
1057 __ nop(); | 1015 __ nop(); |
1016 DropAndApply(1, expr->context(), eax); | |
1058 } else { | 1017 } else { |
1059 // Do a KEYED property load. | 1018 // Do a keyed property load. |
1060 Visit(expr->key()); | 1019 Visit(expr->key()); |
1061 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1020 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
1062 __ call(ic, RelocInfo::CODE_TARGET); | 1021 __ call(ic, RelocInfo::CODE_TARGET); |
1063 // By emitting a nop we make sure that we do not have a "test eax,..." | 1022 // By emitting a nop we make sure that we do not have a "test eax,..." |
1064 // instruction after the call it is treated specially by the LoadIC code. | 1023 // instruction after the call it is treated specially by the LoadIC code. |
1065 __ nop(); | 1024 __ nop(); |
1066 // Drop key left on the stack by IC. | 1025 // Drop key left on the stack by IC. |
1067 __ add(Operand(esp), Immediate(kPointerSize)); | 1026 DropAndApply(2, expr->context(), eax); |
1068 } | 1027 } |
1069 DropAndMove(expr->context(), eax); | |
1070 } | 1028 } |
1071 | 1029 |
1072 | 1030 |
1073 void FastCodeGenerator::EmitCallWithIC(Call* expr, | 1031 void FastCodeGenerator::EmitCallWithIC(Call* expr, |
1074 Handle<Object> name, | 1032 Handle<Object> name, |
1075 RelocInfo::Mode mode) { | 1033 RelocInfo::Mode mode) { |
1076 // Code common for calls using the IC. | 1034 // Code common for calls using the IC. |
1077 ZoneList<Expression*>* args = expr->arguments(); | 1035 ZoneList<Expression*>* args = expr->arguments(); |
1078 int arg_count = args->length(); | 1036 int arg_count = args->length(); |
1079 for (int i = 0; i < arg_count; i++) { | 1037 for (int i = 0; i < arg_count; i++) { |
1080 Visit(args->at(i)); | 1038 Visit(args->at(i)); |
1081 ASSERT_EQ(Expression::kValue, args->at(i)->context()); | 1039 ASSERT_EQ(Expression::kValue, args->at(i)->context()); |
1082 } | 1040 } |
1083 __ Set(ecx, Immediate(name)); | 1041 __ Set(ecx, Immediate(name)); |
1084 // Record source position of the IC call. | 1042 // Record source position of the IC call. |
1085 SetSourcePosition(expr->position()); | 1043 SetSourcePosition(expr->position()); |
1086 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 1044 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
1087 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); | 1045 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); |
1088 __ call(ic, mode); | 1046 __ call(ic, mode); |
1089 // Restore context register. | 1047 // Restore context register. |
1090 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 1048 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
1091 Move(expr->context(), eax); | 1049 Apply(expr->context(), eax); |
1092 } | 1050 } |
1093 | 1051 |
1094 | 1052 |
1095 void FastCodeGenerator::EmitCallWithStub(Call* expr) { | 1053 void FastCodeGenerator::EmitCallWithStub(Call* expr) { |
1096 // Code common for calls using the call stub. | 1054 // Code common for calls using the call stub. |
1097 ZoneList<Expression*>* args = expr->arguments(); | 1055 ZoneList<Expression*>* args = expr->arguments(); |
1098 int arg_count = args->length(); | 1056 int arg_count = args->length(); |
1099 for (int i = 0; i < arg_count; i++) { | 1057 for (int i = 0; i < arg_count; i++) { |
1100 Visit(args->at(i)); | 1058 Visit(args->at(i)); |
1101 } | 1059 } |
1102 // Record source position for debugger. | 1060 // Record source position for debugger. |
1103 SetSourcePosition(expr->position()); | 1061 SetSourcePosition(expr->position()); |
1104 CallFunctionStub stub(arg_count, NOT_IN_LOOP); | 1062 CallFunctionStub stub(arg_count, NOT_IN_LOOP); |
1105 __ CallStub(&stub); | 1063 __ CallStub(&stub); |
1106 // Restore context register. | 1064 // Restore context register. |
1107 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 1065 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
1108 DropAndMove(expr->context(), eax); | 1066 DropAndApply(1, expr->context(), eax); |
1109 } | 1067 } |
1110 | 1068 |
1111 | 1069 |
1112 void FastCodeGenerator::VisitCall(Call* expr) { | 1070 void FastCodeGenerator::VisitCall(Call* expr) { |
1113 Comment cmnt(masm_, "[ Call"); | 1071 Comment cmnt(masm_, "[ Call"); |
1114 Expression* fun = expr->expression(); | 1072 Expression* fun = expr->expression(); |
1115 Variable* var = fun->AsVariableProxy()->AsVariable(); | 1073 Variable* var = fun->AsVariableProxy()->AsVariable(); |
1116 | 1074 |
1117 if (var != NULL && var->is_possibly_eval()) { | 1075 if (var != NULL && var->is_possibly_eval()) { |
1118 // Call to the identifier 'eval'. | 1076 // Call to the identifier 'eval'. |
(...skipping 20 matching lines...) Expand all Loading... | |
1139 Visit(prop->obj()); | 1097 Visit(prop->obj()); |
1140 Visit(prop->key()); | 1098 Visit(prop->key()); |
1141 // Record source code position for IC call. | 1099 // Record source code position for IC call. |
1142 SetSourcePosition(prop->position()); | 1100 SetSourcePosition(prop->position()); |
1143 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1101 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
1144 __ call(ic, RelocInfo::CODE_TARGET); | 1102 __ call(ic, RelocInfo::CODE_TARGET); |
1145 // By emitting a nop we make sure that we do not have a "test eax,..." | 1103 // By emitting a nop we make sure that we do not have a "test eax,..." |
1146 // instruction after the call it is treated specially by the LoadIC code. | 1104 // instruction after the call it is treated specially by the LoadIC code. |
1147 __ nop(); | 1105 __ nop(); |
1148 // Drop key left on the stack by IC. | 1106 // Drop key left on the stack by IC. |
1149 __ add(Operand(esp), Immediate(kPointerSize)); | 1107 __ Drop(1); |
1150 // Pop receiver. | 1108 // Pop receiver. |
1151 __ pop(ebx); | 1109 __ pop(ebx); |
1152 // Push result (function). | 1110 // Push result (function). |
1153 __ push(eax); | 1111 __ push(eax); |
1154 // Push receiver object on stack. | 1112 // Push receiver object on stack. |
1155 if (prop->is_synthetic()) { | 1113 if (prop->is_synthetic()) { |
1156 __ push(CodeGenerator::GlobalObject()); | 1114 __ push(CodeGenerator::GlobalObject()); |
1157 } else { | 1115 } else { |
1158 __ push(ebx); | 1116 __ push(ebx); |
1159 } | 1117 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1207 | 1165 |
1208 // Load function, arg_count into edi and eax. | 1166 // Load function, arg_count into edi and eax. |
1209 __ Set(eax, Immediate(arg_count)); | 1167 __ Set(eax, Immediate(arg_count)); |
1210 // Function is in esp[arg_count + 1]. | 1168 // Function is in esp[arg_count + 1]. |
1211 __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize)); | 1169 __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize)); |
1212 | 1170 |
1213 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); | 1171 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); |
1214 __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL); | 1172 __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL); |
1215 | 1173 |
1216 // Replace function on TOS with result in eax, or pop it. | 1174 // Replace function on TOS with result in eax, or pop it. |
1217 DropAndMove(expr->context(), eax); | 1175 DropAndApply(1, expr->context(), eax); |
1218 } | 1176 } |
1219 | 1177 |
1220 | 1178 |
1221 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 1179 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
1222 Comment cmnt(masm_, "[ CallRuntime"); | 1180 Comment cmnt(masm_, "[ CallRuntime"); |
1223 ZoneList<Expression*>* args = expr->arguments(); | 1181 ZoneList<Expression*>* args = expr->arguments(); |
1224 | 1182 |
1225 if (expr->is_jsruntime()) { | 1183 if (expr->is_jsruntime()) { |
1226 // Prepare for calling JS runtime function. | 1184 // Prepare for calling JS runtime function. |
1227 __ mov(eax, CodeGenerator::GlobalObject()); | 1185 __ mov(eax, CodeGenerator::GlobalObject()); |
(...skipping 12 matching lines...) Expand all Loading... | |
1240 __ Set(ecx, Immediate(expr->name())); | 1198 __ Set(ecx, Immediate(expr->name())); |
1241 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 1199 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
1242 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); | 1200 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); |
1243 __ call(ic, RelocInfo::CODE_TARGET); | 1201 __ call(ic, RelocInfo::CODE_TARGET); |
1244 // Restore context register. | 1202 // Restore context register. |
1245 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 1203 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
1246 } else { | 1204 } else { |
1247 // Call the C runtime function. | 1205 // Call the C runtime function. |
1248 __ CallRuntime(expr->function(), arg_count); | 1206 __ CallRuntime(expr->function(), arg_count); |
1249 } | 1207 } |
1250 Move(expr->context(), eax); | 1208 Apply(expr->context(), eax); |
1251 } | 1209 } |
1252 | 1210 |
1253 | 1211 |
1254 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 1212 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
1255 switch (expr->op()) { | 1213 switch (expr->op()) { |
1256 case Token::VOID: { | 1214 case Token::VOID: { |
1257 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); | 1215 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); |
1258 Visit(expr->expression()); | 1216 Visit(expr->expression()); |
1259 ASSERT_EQ(Expression::kEffect, expr->expression()->context()); | 1217 ASSERT_EQ(Expression::kEffect, expr->expression()->context()); |
1260 switch (expr->context()) { | 1218 switch (expr->context()) { |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1362 __ push(esi); | 1320 __ push(esi); |
1363 __ push(Immediate(proxy->name())); | 1321 __ push(Immediate(proxy->name())); |
1364 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); | 1322 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); |
1365 __ push(eax); | 1323 __ push(eax); |
1366 } else { | 1324 } else { |
1367 // This expression cannot throw a reference error at the top level. | 1325 // This expression cannot throw a reference error at the top level. |
1368 Visit(expr->expression()); | 1326 Visit(expr->expression()); |
1369 } | 1327 } |
1370 | 1328 |
1371 __ CallRuntime(Runtime::kTypeof, 1); | 1329 __ CallRuntime(Runtime::kTypeof, 1); |
1372 Move(expr->context(), eax); | 1330 Apply(expr->context(), eax); |
1373 break; | 1331 break; |
1374 } | 1332 } |
1375 | 1333 |
1376 default: | 1334 default: |
1377 UNREACHABLE(); | 1335 UNREACHABLE(); |
1378 } | 1336 } |
1379 } | 1337 } |
1380 | 1338 |
1381 | 1339 |
1382 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { | 1340 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1462 // Store the value returned in eax. | 1420 // Store the value returned in eax. |
1463 switch (assign_type) { | 1421 switch (assign_type) { |
1464 case VARIABLE: | 1422 case VARIABLE: |
1465 __ push(eax); | 1423 __ push(eax); |
1466 if (expr->is_postfix()) { | 1424 if (expr->is_postfix()) { |
1467 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 1425 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
1468 Expression::kEffect); | 1426 Expression::kEffect); |
1469 // For all contexts except kEffect: We have the result on | 1427 // For all contexts except kEffect: We have the result on |
1470 // top of the stack. | 1428 // top of the stack. |
1471 if (expr->context() != Expression::kEffect) { | 1429 if (expr->context() != Expression::kEffect) { |
1472 MoveTOS(expr->context()); | 1430 ApplyTOS(expr->context()); |
1473 } | 1431 } |
1474 } else { | 1432 } else { |
1475 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 1433 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
1476 expr->context()); | 1434 expr->context()); |
1477 } | 1435 } |
1478 break; | 1436 break; |
1479 case NAMED_PROPERTY: { | 1437 case NAMED_PROPERTY: { |
1480 __ mov(ecx, prop->key()->AsLiteral()->handle()); | 1438 __ mov(ecx, prop->key()->AsLiteral()->handle()); |
1481 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1439 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
1482 __ call(ic, RelocInfo::CODE_TARGET); | 1440 __ call(ic, RelocInfo::CODE_TARGET); |
1483 // This nop signals to the IC that there is no inlined code at the call | 1441 // This nop signals to the IC that there is no inlined code at the call |
1484 // site for it to patch. | 1442 // site for it to patch. |
1485 __ nop(); | 1443 __ nop(); |
1486 if (expr->is_postfix()) { | 1444 if (expr->is_postfix()) { |
1487 __ Drop(1); // Result is on the stack under the receiver. | 1445 __ Drop(1); // Result is on the stack under the receiver. |
1488 if (expr->context() != Expression::kEffect) { | 1446 if (expr->context() != Expression::kEffect) { |
1489 MoveTOS(expr->context()); | 1447 ApplyTOS(expr->context()); |
1490 } | 1448 } |
1491 } else { | 1449 } else { |
1492 DropAndMove(expr->context(), eax); | 1450 DropAndApply(1, expr->context(), eax); |
1493 } | 1451 } |
1494 break; | 1452 break; |
1495 } | 1453 } |
1496 case KEYED_PROPERTY: { | 1454 case KEYED_PROPERTY: { |
1497 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 1455 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
1498 __ call(ic, RelocInfo::CODE_TARGET); | 1456 __ call(ic, RelocInfo::CODE_TARGET); |
1499 // This nop signals to the IC that there is no inlined code at the call | 1457 // This nop signals to the IC that there is no inlined code at the call |
1500 // site for it to patch. | 1458 // site for it to patch. |
1501 __ nop(); | 1459 __ nop(); |
1502 if (expr->is_postfix()) { | 1460 if (expr->is_postfix()) { |
1503 __ Drop(2); // Result is on the stack under the key and the receiver. | 1461 __ Drop(2); // Result is on the stack under the key and the receiver. |
1504 if (expr->context() != Expression::kEffect) { | 1462 if (expr->context() != Expression::kEffect) { |
1505 MoveTOS(expr->context()); | 1463 ApplyTOS(expr->context()); |
1506 } | 1464 } |
1507 } else { | 1465 } else { |
1508 DropAndMove(expr->context(), eax, 2); | 1466 DropAndApply(2, expr->context(), eax); |
1509 } | 1467 } |
1510 break; | 1468 break; |
1511 } | 1469 } |
1512 } | 1470 } |
1513 } | 1471 } |
1514 | 1472 |
1515 | 1473 |
1516 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 1474 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
1517 Comment cmnt(masm_, "[ BinaryOperation"); | 1475 Comment cmnt(masm_, "[ BinaryOperation"); |
1518 switch (expr->op()) { | 1476 switch (expr->op()) { |
(...skipping 22 matching lines...) Expand all Loading... | |
1541 case Token::SAR: { | 1499 case Token::SAR: { |
1542 ASSERT_EQ(Expression::kValue, expr->left()->context()); | 1500 ASSERT_EQ(Expression::kValue, expr->left()->context()); |
1543 ASSERT_EQ(Expression::kValue, expr->right()->context()); | 1501 ASSERT_EQ(Expression::kValue, expr->right()->context()); |
1544 | 1502 |
1545 Visit(expr->left()); | 1503 Visit(expr->left()); |
1546 Visit(expr->right()); | 1504 Visit(expr->right()); |
1547 GenericBinaryOpStub stub(expr->op(), | 1505 GenericBinaryOpStub stub(expr->op(), |
1548 NO_OVERWRITE, | 1506 NO_OVERWRITE, |
1549 NO_GENERIC_BINARY_FLAGS); | 1507 NO_GENERIC_BINARY_FLAGS); |
1550 __ CallStub(&stub); | 1508 __ CallStub(&stub); |
1551 Move(expr->context(), eax); | 1509 Apply(expr->context(), eax); |
1552 | 1510 |
1553 break; | 1511 break; |
1554 } | 1512 } |
1555 default: | 1513 default: |
1556 UNREACHABLE(); | 1514 UNREACHABLE(); |
1557 } | 1515 } |
1558 } | 1516 } |
1559 | 1517 |
1560 | 1518 |
1561 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 1519 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1712 break; | 1670 break; |
1713 } | 1671 } |
1714 true_label_ = saved_true; | 1672 true_label_ = saved_true; |
1715 false_label_ = saved_false; | 1673 false_label_ = saved_false; |
1716 // Convert current context to test context: End post-test code. | 1674 // Convert current context to test context: End post-test code. |
1717 } | 1675 } |
1718 | 1676 |
1719 | 1677 |
1720 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 1678 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
1721 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 1679 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
1722 Move(expr->context(), eax); | 1680 Apply(expr->context(), eax); |
1723 } | 1681 } |
1724 | 1682 |
1725 | 1683 |
1726 Register FastCodeGenerator::result_register() { return eax; } | 1684 Register FastCodeGenerator::result_register() { return eax; } |
1727 | 1685 |
1728 | 1686 |
1729 Register FastCodeGenerator::context_register() { return esi; } | 1687 Register FastCodeGenerator::context_register() { return esi; } |
1730 | 1688 |
1731 | 1689 |
1732 void FastCodeGenerator::StoreToFrameField(int frame_offset, Register value) { | 1690 void FastCodeGenerator::StoreToFrameField(int frame_offset, Register value) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1767 __ add(Operand(edx), Immediate(masm_->CodeObject())); | 1725 __ add(Operand(edx), Immediate(masm_->CodeObject())); |
1768 __ mov(Operand(esp, 0), edx); | 1726 __ mov(Operand(esp, 0), edx); |
1769 // And return. | 1727 // And return. |
1770 __ ret(0); | 1728 __ ret(0); |
1771 } | 1729 } |
1772 | 1730 |
1773 | 1731 |
1774 #undef __ | 1732 #undef __ |
1775 | 1733 |
1776 } } // namespace v8::internal | 1734 } } // namespace v8::internal |
OLD | NEW |