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 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
207 // mode 1 instruction where there are restrictions on which immediate values | 207 // mode 1 instruction where there are restrictions on which immediate values |
208 // can be encoded in the instruction and which immediate values requires | 208 // can be encoded in the instruction and which immediate values requires |
209 // use of an additional instruction for moving the immediate to a temporary | 209 // use of an additional instruction for moving the immediate to a temporary |
210 // register. | 210 // register. |
211 ASSERT_EQ(return_sequence_length, | 211 ASSERT_EQ(return_sequence_length, |
212 masm_->InstructionsGeneratedSince(&check_exit_codesize)); | 212 masm_->InstructionsGeneratedSince(&check_exit_codesize)); |
213 } | 213 } |
214 } | 214 } |
215 | 215 |
216 | 216 |
217 void FastCodeGenerator::Move(Expression::Context context, Register source) { | 217 void FastCodeGenerator::Apply(Expression::Context context, |
218 Slot* slot, | |
219 Register scratch) { | |
218 switch (context) { | 220 switch (context) { |
219 case Expression::kUninitialized: | 221 case Expression::kUninitialized: |
220 UNREACHABLE(); | 222 UNREACHABLE(); |
221 case Expression::kEffect: | 223 case Expression::kEffect: |
222 break; | 224 break; |
223 case Expression::kValue: | 225 case Expression::kValue: |
224 __ push(source); | 226 case Expression::kTest: |
227 case Expression::kValueTest: | |
228 case Expression::kTestValue: | |
229 Move(scratch, slot); | |
230 Apply(context, scratch); | |
225 break; | 231 break; |
226 case Expression::kTest: | |
227 TestAndBranch(source, true_label_, false_label_); | |
228 break; | |
229 case Expression::kValueTest: { | |
230 Label discard; | |
231 __ push(source); | |
232 TestAndBranch(source, true_label_, &discard); | |
233 __ bind(&discard); | |
234 __ pop(); | |
235 __ jmp(false_label_); | |
236 break; | |
237 } | |
238 case Expression::kTestValue: { | |
239 Label discard; | |
240 __ push(source); | |
241 TestAndBranch(source, &discard, false_label_); | |
242 __ bind(&discard); | |
243 __ pop(); | |
244 __ jmp(true_label_); | |
245 } | |
246 } | 232 } |
247 } | 233 } |
248 | 234 |
249 | 235 |
250 void FastCodeGenerator::MoveTOS(Expression::Context context) { | 236 void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) { |
237 switch (context) { | |
238 case Expression::kUninitialized: | |
239 UNREACHABLE(); | |
240 case Expression::kEffect: | |
241 break; | |
242 case Expression::kValue: | |
243 case Expression::kTest: | |
244 case Expression::kValueTest: | |
245 case Expression::kTestValue: | |
246 __ mov(ip, Operand(lit->handle())); | |
247 Apply(context, ip); | |
248 break; | |
249 } | |
250 } | |
251 | |
252 | |
253 void FastCodeGenerator::ApplyTOS(Expression::Context context) { | |
251 switch (context) { | 254 switch (context) { |
252 case Expression::kUninitialized: | 255 case Expression::kUninitialized: |
253 UNREACHABLE(); | 256 UNREACHABLE(); |
254 case Expression::kEffect: | 257 case Expression::kEffect: |
255 __ Drop(1); | 258 __ Drop(1); |
256 break; | 259 break; |
257 case Expression::kValue: | 260 case Expression::kValue: |
258 break; | 261 break; |
259 case Expression::kTest: | 262 case Expression::kTest: |
260 __ pop(r0); | 263 __ pop(r0); |
261 TestAndBranch(r0, true_label_, false_label_); | 264 TestAndBranch(r0, true_label_, false_label_); |
262 break; | 265 break; |
263 case Expression::kValueTest: { | 266 case Expression::kValueTest: { |
264 Label discard; | 267 Label discard; |
265 __ ldr(r0, MemOperand(sp, 0)); | 268 __ ldr(r0, MemOperand(sp, 0)); |
266 TestAndBranch(r0, true_label_, &discard); | 269 TestAndBranch(r0, true_label_, &discard); |
267 __ bind(&discard); | 270 __ bind(&discard); |
268 __ Drop(1); | 271 __ Drop(1); |
269 __ jmp(false_label_); | 272 __ jmp(false_label_); |
273 break; | |
274 } | |
275 case Expression::kTestValue: { | |
276 Label discard; | |
277 __ ldr(r0, MemOperand(sp, 0)); | |
278 TestAndBranch(r0, &discard, false_label_); | |
279 __ bind(&discard); | |
280 __ Drop(1); | |
281 __ jmp(true_label_); | |
282 } | |
283 } | |
284 } | |
285 | |
286 | |
287 void FastCodeGenerator::DropAndApply(int count, | |
288 Expression::Context context, | |
289 Register reg) { | |
290 ASSERT(count > 0); | |
291 ASSERT(!reg.is(sp)); | |
292 switch (context) { | |
293 case Expression::kUninitialized: | |
294 UNREACHABLE(); | |
295 case Expression::kEffect: | |
296 __ Drop(count); | |
297 break; | |
298 case Expression::kValue: | |
299 if (count > 1) __ Drop(count - 1); | |
300 __ str(reg, MemOperand(sp)); | |
301 break; | |
302 case Expression::kTest: | |
303 __ Drop(count); | |
304 TestAndBranch(reg, true_label_, false_label_); | |
305 break; | |
306 case Expression::kValueTest: { | |
307 Label discard; | |
308 if (count > 1) __ Drop(count - 1); | |
309 __ str(reg, MemOperand(sp)); | |
310 TestAndBranch(reg, true_label_, &discard); | |
311 __ bind(&discard); | |
312 __ Drop(1); | |
313 __ jmp(false_label_); | |
270 break; | 314 break; |
271 } | 315 } |
272 case Expression::kTestValue: { | 316 case Expression::kTestValue: { |
273 Label discard; | 317 Label discard; |
274 __ ldr(r0, MemOperand(sp, 0)); | 318 if (count > 1) __ Drop(count - 1); |
275 TestAndBranch(r0, &discard, false_label_); | 319 __ str(reg, MemOperand(sp)); |
320 TestAndBranch(reg, &discard, false_label_); | |
276 __ bind(&discard); | 321 __ bind(&discard); |
277 __ Drop(1); | 322 __ Drop(1); |
278 __ jmp(true_label_); | 323 __ jmp(true_label_); |
324 break; | |
279 } | 325 } |
280 } | 326 } |
281 } | 327 } |
282 | 328 |
283 | 329 |
284 MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { | 330 MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { |
285 switch (slot->type()) { | 331 switch (slot->type()) { |
286 case Slot::PARAMETER: | 332 case Slot::PARAMETER: |
287 case Slot::LOCAL: | 333 case Slot::LOCAL: |
288 return MemOperand(fp, SlotOffset(slot)); | 334 return MemOperand(fp, SlotOffset(slot)); |
(...skipping 12 matching lines...) Expand all Loading... | |
301 | 347 |
302 | 348 |
303 void FastCodeGenerator::Move(Register destination, Slot* source) { | 349 void FastCodeGenerator::Move(Register destination, Slot* source) { |
304 // Use destination as scratch. | 350 // Use destination as scratch. |
305 MemOperand location = EmitSlotSearch(source, destination); | 351 MemOperand location = EmitSlotSearch(source, destination); |
306 __ ldr(destination, location); | 352 __ ldr(destination, location); |
307 } | 353 } |
308 | 354 |
309 | 355 |
310 | 356 |
311 void FastCodeGenerator::Move(Expression::Context context, | |
312 Slot* source, | |
313 Register scratch) { | |
314 switch (context) { | |
315 case Expression::kUninitialized: | |
316 UNREACHABLE(); | |
317 case Expression::kEffect: | |
318 break; | |
319 case Expression::kValue: | |
320 case Expression::kTest: | |
321 case Expression::kValueTest: | |
322 case Expression::kTestValue: | |
323 Move(scratch, source); | |
324 Move(context, scratch); | |
325 break; | |
326 } | |
327 } | |
328 | |
329 | |
330 void FastCodeGenerator::Move(Expression::Context context, Literal* expr) { | |
331 switch (context) { | |
332 case Expression::kUninitialized: | |
333 UNREACHABLE(); | |
334 case Expression::kEffect: | |
335 break; | |
336 case Expression::kValue: | |
337 case Expression::kTest: | |
338 case Expression::kValueTest: | |
339 case Expression::kTestValue: | |
340 __ mov(ip, Operand(expr->handle())); | |
341 Move(context, ip); | |
342 break; | |
343 } | |
344 } | |
345 | |
346 | |
347 void FastCodeGenerator::Move(Slot* dst, | 357 void FastCodeGenerator::Move(Slot* dst, |
348 Register src, | 358 Register src, |
349 Register scratch1, | 359 Register scratch1, |
350 Register scratch2) { | 360 Register scratch2) { |
351 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. | 361 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. |
352 ASSERT(!scratch1.is(src) && !scratch2.is(src)); | 362 ASSERT(!scratch1.is(src) && !scratch2.is(src)); |
353 MemOperand location = EmitSlotSearch(dst, scratch1); | 363 MemOperand location = EmitSlotSearch(dst, scratch1); |
354 __ str(src, location); | 364 __ str(src, location); |
355 // Emit the write barrier code if the location is in the heap. | 365 // Emit the write barrier code if the location is in the heap. |
356 if (dst->type() == Slot::CONTEXT) { | 366 if (dst->type() == Slot::CONTEXT) { |
357 __ mov(scratch2, Operand(Context::SlotOffset(dst->index()))); | 367 __ mov(scratch2, Operand(Context::SlotOffset(dst->index()))); |
358 __ RecordWrite(scratch1, scratch2, src); | 368 __ RecordWrite(scratch1, scratch2, src); |
359 } | 369 } |
360 } | 370 } |
361 | 371 |
362 | 372 |
363 | 373 |
364 void FastCodeGenerator::DropAndMove(Expression::Context context, | |
365 Register source, | |
366 int drop_count) { | |
367 ASSERT(drop_count > 0); | |
368 switch (context) { | |
369 case Expression::kUninitialized: | |
370 UNREACHABLE(); | |
371 case Expression::kEffect: | |
372 __ add(sp, sp, Operand(drop_count * kPointerSize)); | |
373 break; | |
374 case Expression::kValue: | |
375 if (drop_count > 1) { | |
376 __ add(sp, sp, Operand((drop_count - 1) * kPointerSize)); | |
377 } | |
378 __ str(source, MemOperand(sp)); | |
379 break; | |
380 case Expression::kTest: | |
381 ASSERT(!source.is(sp)); | |
382 __ add(sp, sp, Operand(drop_count * kPointerSize)); | |
383 TestAndBranch(source, true_label_, false_label_); | |
384 break; | |
385 case Expression::kValueTest: { | |
386 Label discard; | |
387 if (drop_count > 1) { | |
388 __ add(sp, sp, Operand((drop_count - 1) * kPointerSize)); | |
389 } | |
390 __ str(source, MemOperand(sp)); | |
391 TestAndBranch(source, true_label_, &discard); | |
392 __ bind(&discard); | |
393 __ pop(); | |
394 __ jmp(false_label_); | |
395 break; | |
396 } | |
397 case Expression::kTestValue: { | |
398 Label discard; | |
399 if (drop_count > 1) { | |
400 __ add(sp, sp, Operand((drop_count - 1) * kPointerSize)); | |
401 } | |
402 __ str(source, MemOperand(sp)); | |
403 TestAndBranch(source, &discard, false_label_); | |
404 __ bind(&discard); | |
405 __ pop(); | |
406 __ jmp(true_label_); | |
407 break; | |
408 } | |
409 } | |
410 } | |
411 | |
412 | |
413 void FastCodeGenerator::TestAndBranch(Register source, | 374 void FastCodeGenerator::TestAndBranch(Register source, |
414 Label* true_label, | 375 Label* true_label, |
415 Label* false_label) { | 376 Label* false_label) { |
416 ASSERT_NE(NULL, true_label); | 377 ASSERT_NE(NULL, true_label); |
417 ASSERT_NE(NULL, false_label); | 378 ASSERT_NE(NULL, false_label); |
418 // Call the runtime to find the boolean value of the source and then | 379 // Call the runtime to find the boolean value of the source and then |
419 // translate it into control flow to the pair of labels. | 380 // translate it into control flow to the pair of labels. |
420 __ push(source); | 381 __ push(source); |
421 __ CallRuntime(Runtime::kToBool, 1); | 382 __ CallRuntime(Runtime::kToBool, 1); |
422 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 383 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
517 __ pop(r0); | 478 __ pop(r0); |
518 } else { | 479 } else { |
519 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); | 480 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); |
520 } | 481 } |
521 | 482 |
522 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 483 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
523 __ Call(ic, RelocInfo::CODE_TARGET); | 484 __ Call(ic, RelocInfo::CODE_TARGET); |
524 | 485 |
525 // Value in r0 is ignored (declarations are statements). Receiver | 486 // Value in r0 is ignored (declarations are statements). Receiver |
526 // and key on stack are discarded. | 487 // and key on stack are discarded. |
527 __ add(sp, sp, Operand(2 * kPointerSize)); | 488 __ Drop(2); |
528 } | 489 } |
529 } | 490 } |
530 } | 491 } |
531 | 492 |
532 | 493 |
533 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 494 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
534 // Call the runtime to declare the globals. | 495 // Call the runtime to declare the globals. |
535 // The context is the first argument. | 496 // The context is the first argument. |
536 __ mov(r1, Operand(pairs)); | 497 __ mov(r1, Operand(pairs)); |
537 __ mov(r0, Operand(Smi::FromInt(is_eval_ ? 1 : 0))); | 498 __ mov(r0, Operand(Smi::FromInt(is_eval_ ? 1 : 0))); |
(...skipping 10 matching lines...) Expand all Loading... | |
548 Handle<JSFunction> boilerplate = | 509 Handle<JSFunction> boilerplate = |
549 Compiler::BuildBoilerplate(expr, script_, this); | 510 Compiler::BuildBoilerplate(expr, script_, this); |
550 if (HasStackOverflow()) return; | 511 if (HasStackOverflow()) return; |
551 | 512 |
552 ASSERT(boilerplate->IsBoilerplate()); | 513 ASSERT(boilerplate->IsBoilerplate()); |
553 | 514 |
554 // Create a new closure. | 515 // Create a new closure. |
555 __ mov(r0, Operand(boilerplate)); | 516 __ mov(r0, Operand(boilerplate)); |
556 __ stm(db_w, sp, cp.bit() | r0.bit()); | 517 __ stm(db_w, sp, cp.bit() | r0.bit()); |
557 __ CallRuntime(Runtime::kNewClosure, 2); | 518 __ CallRuntime(Runtime::kNewClosure, 2); |
558 Move(expr->context(), r0); | 519 Apply(expr->context(), r0); |
559 } | 520 } |
560 | 521 |
561 | 522 |
562 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 523 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
563 Comment cmnt(masm_, "[ VariableProxy"); | 524 Comment cmnt(masm_, "[ VariableProxy"); |
564 EmitVariableLoad(expr->var(), expr->context()); | 525 EmitVariableLoad(expr->var(), expr->context()); |
565 } | 526 } |
566 | 527 |
567 | 528 |
568 void FastCodeGenerator::EmitVariableLoad(Variable* var, | 529 void FastCodeGenerator::EmitVariableLoad(Variable* var, |
569 Expression::Context context) { | 530 Expression::Context context) { |
570 Expression* rewrite = var->rewrite(); | 531 Expression* rewrite = var->rewrite(); |
571 if (rewrite == NULL) { | 532 if (rewrite == NULL) { |
572 ASSERT(var->is_global()); | 533 ASSERT(var->is_global()); |
573 Comment cmnt(masm_, "Global variable"); | 534 Comment cmnt(masm_, "Global variable"); |
574 // Use inline caching. Variable name is passed in r2 and the global | 535 // Use inline caching. Variable name is passed in r2 and the global |
575 // object on the stack. | 536 // object on the stack. |
576 __ ldr(ip, CodeGenerator::GlobalObject()); | 537 __ ldr(ip, CodeGenerator::GlobalObject()); |
577 __ push(ip); | 538 __ push(ip); |
578 __ mov(r2, Operand(var->name())); | 539 __ mov(r2, Operand(var->name())); |
579 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 540 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
580 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); | 541 __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); |
581 DropAndMove(context, r0); | 542 DropAndApply(1, context, r0); |
582 } else if (rewrite->AsSlot() != NULL) { | 543 } else if (rewrite->AsSlot() != NULL) { |
583 Slot* slot = rewrite->AsSlot(); | 544 Slot* slot = rewrite->AsSlot(); |
584 if (FLAG_debug_code) { | 545 if (FLAG_debug_code) { |
585 switch (slot->type()) { | 546 switch (slot->type()) { |
586 case Slot::PARAMETER: | 547 case Slot::PARAMETER: |
587 case Slot::LOCAL: { | 548 case Slot::LOCAL: { |
588 Comment cmnt(masm_, "Stack slot"); | 549 Comment cmnt(masm_, "Stack slot"); |
589 break; | 550 break; |
590 } | 551 } |
591 case Slot::CONTEXT: { | 552 case Slot::CONTEXT: { |
592 Comment cmnt(masm_, "Context slot"); | 553 Comment cmnt(masm_, "Context slot"); |
593 break; | 554 break; |
594 } | 555 } |
595 case Slot::LOOKUP: | 556 case Slot::LOOKUP: |
596 UNIMPLEMENTED(); | 557 UNIMPLEMENTED(); |
597 break; | 558 break; |
598 } | 559 } |
599 } | 560 } |
600 Move(context, slot, r0); | 561 Apply(context, slot, r0); |
601 } else { | 562 } else { |
602 // A variable has been rewritten into an explicit access to | 563 Comment cmnt(masm_, "Variable rewritten to property"); |
603 // an object property. | 564 // A variable has been rewritten into an explicit access to an object |
565 // property. | |
604 Property* property = rewrite->AsProperty(); | 566 Property* property = rewrite->AsProperty(); |
605 ASSERT_NOT_NULL(property); | 567 ASSERT_NOT_NULL(property); |
606 | 568 |
607 // Currently the only parameter expressions that can occur are | 569 // The only property expressions that can occur are of the form |
608 // on the form "slot[literal]". | 570 // "slot[literal]". |
609 | 571 |
610 // Check that the object is in a slot. | 572 // Assert that the object is in a slot. |
611 Variable* object_var = property->obj()->AsVariableProxy()->AsVariable(); | 573 Variable* object_var = property->obj()->AsVariableProxy()->AsVariable(); |
612 ASSERT_NOT_NULL(object_var); | 574 ASSERT_NOT_NULL(object_var); |
613 Slot* object_slot = object_var->slot(); | 575 Slot* object_slot = object_var->slot(); |
614 ASSERT_NOT_NULL(object_slot); | 576 ASSERT_NOT_NULL(object_slot); |
615 | 577 |
616 // Load the object. | 578 // Load the object. |
617 Move(r2, object_slot); | 579 Move(r2, object_slot); |
618 | 580 |
619 // Check that the key is a smi. | 581 // Assert that the key is a smi. |
620 Literal* key_literal = property->key()->AsLiteral(); | 582 Literal* key_literal = property->key()->AsLiteral(); |
621 ASSERT_NOT_NULL(key_literal); | 583 ASSERT_NOT_NULL(key_literal); |
622 ASSERT(key_literal->handle()->IsSmi()); | 584 ASSERT(key_literal->handle()->IsSmi()); |
623 | 585 |
624 // Load the key. | 586 // Load the key. |
625 __ mov(r1, Operand(key_literal->handle())); | 587 __ mov(r1, Operand(key_literal->handle())); |
626 | 588 |
627 // Push both as arguments to ic. | 589 // Push both as arguments to ic. |
628 __ stm(db_w, sp, r2.bit() | r1.bit()); | 590 __ stm(db_w, sp, r2.bit() | r1.bit()); |
629 | 591 |
630 // Do a KEYED property load. | 592 // Do a keyed property load. |
631 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 593 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
632 __ Call(ic, RelocInfo::CODE_TARGET); | 594 __ Call(ic, RelocInfo::CODE_TARGET); |
633 | 595 |
634 // Drop key and object left on the stack by IC, and push the result. | 596 // Drop key and object left on the stack by IC, and push the result. |
635 DropAndMove(context, r0, 2); | 597 DropAndApply(2, context, r0); |
636 } | 598 } |
637 } | 599 } |
638 | 600 |
639 | 601 |
640 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 602 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
641 Comment cmnt(masm_, "[ RegExpLiteral"); | 603 Comment cmnt(masm_, "[ RegExpLiteral"); |
642 Label done; | 604 Label done; |
643 // Registers will be used as follows: | 605 // Registers will be used as follows: |
644 // r4 = JS function, literals array | 606 // r4 = JS function, literals array |
645 // r3 = literal index | 607 // r3 = literal index |
646 // r2 = RegExp pattern | 608 // r2 = RegExp pattern |
647 // r1 = RegExp flags | 609 // r1 = RegExp flags |
648 // r0 = temp + return value (RegExp literal) | 610 // r0 = temp + return value (RegExp literal) |
649 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 611 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
650 __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); | 612 __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); |
651 int literal_offset = | 613 int literal_offset = |
652 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; | 614 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
653 __ ldr(r0, FieldMemOperand(r4, literal_offset)); | 615 __ ldr(r0, FieldMemOperand(r4, literal_offset)); |
654 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 616 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
655 __ cmp(r0, ip); | 617 __ cmp(r0, ip); |
656 __ b(ne, &done); | 618 __ b(ne, &done); |
657 __ mov(r3, Operand(Smi::FromInt(expr->literal_index()))); | 619 __ mov(r3, Operand(Smi::FromInt(expr->literal_index()))); |
658 __ mov(r2, Operand(expr->pattern())); | 620 __ mov(r2, Operand(expr->pattern())); |
659 __ mov(r1, Operand(expr->flags())); | 621 __ mov(r1, Operand(expr->flags())); |
660 __ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit()); | 622 __ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit()); |
661 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); | 623 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
662 __ bind(&done); | 624 __ bind(&done); |
663 Move(expr->context(), r0); | 625 Apply(expr->context(), r0); |
664 } | 626 } |
665 | 627 |
666 | 628 |
667 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 629 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
668 Comment cmnt(masm_, "[ ObjectLiteral"); | 630 Comment cmnt(masm_, "[ ObjectLiteral"); |
669 __ ldr(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 631 __ ldr(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
670 __ ldr(r2, FieldMemOperand(r2, JSFunction::kLiteralsOffset)); | 632 __ ldr(r2, FieldMemOperand(r2, JSFunction::kLiteralsOffset)); |
671 __ mov(r1, Operand(Smi::FromInt(expr->literal_index()))); | 633 __ mov(r1, Operand(Smi::FromInt(expr->literal_index()))); |
672 __ mov(r0, Operand(expr->constant_properties())); | 634 __ mov(r0, Operand(expr->constant_properties())); |
673 __ stm(db_w, sp, r2.bit() | r1.bit() | r0.bit()); | 635 __ stm(db_w, sp, r2.bit() | r1.bit() | r0.bit()); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
735 ASSERT_EQ(Expression::kValue, value->context()); | 697 ASSERT_EQ(Expression::kValue, value->context()); |
736 __ CallRuntime(Runtime::kDefineAccessor, 4); | 698 __ CallRuntime(Runtime::kDefineAccessor, 4); |
737 __ ldr(r0, MemOperand(sp)); // Restore result into r0 | 699 __ ldr(r0, MemOperand(sp)); // Restore result into r0 |
738 break; | 700 break; |
739 } | 701 } |
740 } | 702 } |
741 switch (expr->context()) { | 703 switch (expr->context()) { |
742 case Expression::kUninitialized: | 704 case Expression::kUninitialized: |
743 UNREACHABLE(); | 705 UNREACHABLE(); |
744 case Expression::kEffect: | 706 case Expression::kEffect: |
745 if (result_saved) __ pop(); | 707 if (result_saved) __ Drop(1); |
746 break; | 708 break; |
747 case Expression::kValue: | 709 case Expression::kValue: |
748 if (!result_saved) __ push(r0); | 710 if (!result_saved) __ push(r0); |
749 break; | 711 break; |
750 case Expression::kTest: | 712 case Expression::kTest: |
751 if (result_saved) __ pop(r0); | 713 if (result_saved) __ pop(r0); |
752 TestAndBranch(r0, true_label_, false_label_); | 714 TestAndBranch(r0, true_label_, false_label_); |
753 break; | 715 break; |
754 case Expression::kValueTest: { | 716 case Expression::kValueTest: { |
755 Label discard; | 717 Label discard; |
756 if (!result_saved) __ push(r0); | 718 if (!result_saved) __ push(r0); |
757 TestAndBranch(r0, true_label_, &discard); | 719 TestAndBranch(r0, true_label_, &discard); |
758 __ bind(&discard); | 720 __ bind(&discard); |
759 __ pop(); | 721 __ Drop(1); |
760 __ jmp(false_label_); | 722 __ jmp(false_label_); |
761 break; | 723 break; |
762 } | 724 } |
763 case Expression::kTestValue: { | 725 case Expression::kTestValue: { |
764 Label discard; | 726 Label discard; |
765 if (!result_saved) __ push(r0); | 727 if (!result_saved) __ push(r0); |
766 TestAndBranch(r0, &discard, false_label_); | 728 TestAndBranch(r0, &discard, false_label_); |
767 __ bind(&discard); | 729 __ bind(&discard); |
768 __ pop(); | 730 __ Drop(1); |
769 __ jmp(true_label_); | 731 __ jmp(true_label_); |
770 break; | 732 break; |
771 } | 733 } |
772 } | 734 } |
773 } | 735 } |
774 | 736 |
775 | 737 |
776 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 738 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
777 Comment cmnt(masm_, "[ ArrayLiteral"); | 739 Comment cmnt(masm_, "[ ArrayLiteral"); |
778 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 740 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
813 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); | 775 __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset)); |
814 int offset = FixedArray::kHeaderSize + (i * kPointerSize); | 776 int offset = FixedArray::kHeaderSize + (i * kPointerSize); |
815 __ str(r0, FieldMemOperand(r1, offset)); | 777 __ str(r0, FieldMemOperand(r1, offset)); |
816 | 778 |
817 // Update the write barrier for the array store with r0 as the scratch | 779 // Update the write barrier for the array store with r0 as the scratch |
818 // register. | 780 // register. |
819 __ mov(r2, Operand(offset)); | 781 __ mov(r2, Operand(offset)); |
820 __ RecordWrite(r1, r2, r0); | 782 __ RecordWrite(r1, r2, r0); |
821 } | 783 } |
822 | 784 |
823 switch (expr->context()) { | 785 switch (expr->context()) { |
Lasse Reichstein
2010/01/12 08:30:05
This switch is identical to the one at line 703. C
| |
824 case Expression::kUninitialized: | 786 case Expression::kUninitialized: |
825 UNREACHABLE(); | 787 UNREACHABLE(); |
826 case Expression::kEffect: | 788 case Expression::kEffect: |
827 if (result_saved) __ pop(); | 789 if (result_saved) __ Drop(1); |
828 break; | 790 break; |
829 case Expression::kValue: | 791 case Expression::kValue: |
830 if (!result_saved) __ push(r0); | 792 if (!result_saved) __ push(r0); |
831 break; | 793 break; |
832 case Expression::kTest: | 794 case Expression::kTest: |
833 if (result_saved) __ pop(r0); | 795 if (result_saved) __ pop(r0); |
834 TestAndBranch(r0, true_label_, false_label_); | 796 TestAndBranch(r0, true_label_, false_label_); |
835 break; | 797 break; |
836 case Expression::kValueTest: { | 798 case Expression::kValueTest: { |
837 Label discard; | 799 Label discard; |
838 if (!result_saved) __ push(r0); | 800 if (!result_saved) __ push(r0); |
839 TestAndBranch(r0, true_label_, &discard); | 801 TestAndBranch(r0, true_label_, &discard); |
840 __ bind(&discard); | 802 __ bind(&discard); |
841 __ pop(); | 803 __ Drop(1); |
842 __ jmp(false_label_); | 804 __ jmp(false_label_); |
843 break; | 805 break; |
844 } | 806 } |
845 case Expression::kTestValue: { | 807 case Expression::kTestValue: { |
846 Label discard; | 808 Label discard; |
847 if (!result_saved) __ push(r0); | 809 if (!result_saved) __ push(r0); |
848 TestAndBranch(r0, &discard, false_label_); | 810 TestAndBranch(r0, &discard, false_label_); |
849 __ bind(&discard); | 811 __ bind(&discard); |
850 __ pop(); | 812 __ Drop(1); |
851 __ jmp(true_label_); | 813 __ jmp(true_label_); |
852 break; | 814 break; |
853 } | 815 } |
854 } | 816 } |
855 } | 817 } |
856 | 818 |
857 | 819 |
858 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop, | 820 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop, |
859 Expression::Context context) { | 821 Expression::Context context) { |
860 SetSourcePosition(prop->position()); | 822 SetSourcePosition(prop->position()); |
861 Literal* key = prop->key()->AsLiteral(); | 823 Literal* key = prop->key()->AsLiteral(); |
862 __ mov(r2, Operand(key->handle())); | 824 __ mov(r2, Operand(key->handle())); |
863 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 825 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
864 __ Call(ic, RelocInfo::CODE_TARGET); | 826 __ Call(ic, RelocInfo::CODE_TARGET); |
865 Move(context, r0); | 827 Apply(context, r0); |
866 } | 828 } |
867 | 829 |
868 | 830 |
869 void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop, | 831 void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop, |
870 Expression::Context context) { | 832 Expression::Context context) { |
871 SetSourcePosition(prop->position()); | 833 SetSourcePosition(prop->position()); |
872 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 834 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
873 __ Call(ic, RelocInfo::CODE_TARGET); | 835 __ Call(ic, RelocInfo::CODE_TARGET); |
874 Move(context, r0); | 836 Apply(context, r0); |
875 } | 837 } |
876 | 838 |
877 | 839 |
878 void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op, | 840 void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op, |
879 Expression::Context context) { | 841 Expression::Context context) { |
880 __ pop(r0); | 842 __ pop(r0); |
881 __ pop(r1); | 843 __ pop(r1); |
882 GenericBinaryOpStub stub(op, | 844 GenericBinaryOpStub stub(op, |
883 NO_OVERWRITE); | 845 NO_OVERWRITE); |
884 __ CallStub(&stub); | 846 __ CallStub(&stub); |
885 Move(context, r0); | 847 Apply(context, r0); |
886 } | 848 } |
887 | 849 |
888 | 850 |
889 void FastCodeGenerator::EmitVariableAssignment(Variable* var, | 851 void FastCodeGenerator::EmitVariableAssignment(Variable* var, |
890 Expression::Context context) { | 852 Expression::Context context) { |
891 ASSERT(var != NULL); | 853 ASSERT(var != NULL); |
892 ASSERT(var->is_global() || var->slot() != NULL); | 854 ASSERT(var->is_global() || var->slot() != NULL); |
893 if (var->is_global()) { | 855 if (var->is_global()) { |
894 // Assignment to a global variable. Use inline caching for the | 856 // Assignment to a global variable. Use inline caching for the |
895 // assignment. Right-hand-side value is passed in r0, variable name in | 857 // assignment. Right-hand-side value is passed in r0, variable name in |
896 // r2, and the global object on the stack. | 858 // r2, and the global object on the stack. |
897 __ pop(r0); | 859 __ pop(r0); |
898 __ mov(r2, Operand(var->name())); | 860 __ mov(r2, Operand(var->name())); |
899 __ ldr(ip, CodeGenerator::GlobalObject()); | 861 __ ldr(ip, CodeGenerator::GlobalObject()); |
900 __ push(ip); | 862 __ push(ip); |
901 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 863 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
902 __ Call(ic, RelocInfo::CODE_TARGET); | 864 __ Call(ic, RelocInfo::CODE_TARGET); |
903 // Overwrite the global object on the stack with the result if needed. | 865 // Overwrite the global object on the stack with the result if needed. |
904 DropAndMove(context, r0); | 866 DropAndApply(1, context, r0); |
905 | 867 |
906 } else if (var->slot() != NULL) { | 868 } else if (var->slot() != NULL) { |
907 Slot* slot = var->slot(); | 869 Slot* slot = var->slot(); |
908 switch (slot->type()) { | 870 switch (slot->type()) { |
909 case Slot::LOCAL: | 871 case Slot::LOCAL: |
910 case Slot::PARAMETER: { | 872 case Slot::PARAMETER: { |
911 MemOperand target = MemOperand(fp, SlotOffset(slot)); | 873 MemOperand target = MemOperand(fp, SlotOffset(slot)); |
912 switch (context) { | 874 switch (context) { |
913 case Expression::kUninitialized: | 875 case Expression::kUninitialized: |
914 UNREACHABLE(); | 876 UNREACHABLE(); |
(...skipping 12 matching lines...) Expand all Loading... | |
927 __ pop(r0); | 889 __ pop(r0); |
928 __ str(r0, target); | 890 __ str(r0, target); |
929 TestAndBranch(r0, true_label_, false_label_); | 891 TestAndBranch(r0, true_label_, false_label_); |
930 break; | 892 break; |
931 case Expression::kValueTest: { | 893 case Expression::kValueTest: { |
932 Label discard; | 894 Label discard; |
933 __ ldr(r0, MemOperand(sp)); | 895 __ ldr(r0, MemOperand(sp)); |
934 __ str(r0, target); | 896 __ str(r0, target); |
935 TestAndBranch(r0, true_label_, &discard); | 897 TestAndBranch(r0, true_label_, &discard); |
936 __ bind(&discard); | 898 __ bind(&discard); |
937 __ pop(); | 899 __ Drop(1); |
938 __ jmp(false_label_); | 900 __ jmp(false_label_); |
939 break; | 901 break; |
940 } | 902 } |
941 case Expression::kTestValue: { | 903 case Expression::kTestValue: { |
942 Label discard; | 904 Label discard; |
943 __ ldr(r0, MemOperand(sp)); | 905 __ ldr(r0, MemOperand(sp)); |
944 __ str(r0, target); | 906 __ str(r0, target); |
945 TestAndBranch(r0, &discard, false_label_); | 907 TestAndBranch(r0, &discard, false_label_); |
946 __ bind(&discard); | 908 __ bind(&discard); |
947 __ pop(); | 909 __ Drop(1); |
948 __ jmp(true_label_); | 910 __ jmp(true_label_); |
949 break; | 911 break; |
950 } | 912 } |
951 } | 913 } |
952 break; | 914 break; |
953 } | 915 } |
954 | 916 |
955 case Slot::CONTEXT: { | 917 case Slot::CONTEXT: { |
956 MemOperand target = EmitSlotSearch(slot, r1); | 918 MemOperand target = EmitSlotSearch(slot, r1); |
957 __ pop(r0); | 919 __ pop(r0); |
(...skipping 11 matching lines...) Expand all Loading... | |
969 // register. Skip the write barrier if the value written (r1) is a smi. | 931 // register. Skip the write barrier if the value written (r1) is a smi. |
970 // The smi test is part of RecordWrite on other platforms, not on arm. | 932 // The smi test is part of RecordWrite on other platforms, not on arm. |
971 Label exit; | 933 Label exit; |
972 __ tst(r0, Operand(kSmiTagMask)); | 934 __ tst(r0, Operand(kSmiTagMask)); |
973 __ b(eq, &exit); | 935 __ b(eq, &exit); |
974 | 936 |
975 __ mov(r2, Operand(offset)); | 937 __ mov(r2, Operand(offset)); |
976 __ RecordWrite(r1, r2, r0); | 938 __ RecordWrite(r1, r2, r0); |
977 __ bind(&exit); | 939 __ bind(&exit); |
978 if (context != Expression::kEffect && context != Expression::kValue) { | 940 if (context != Expression::kEffect && context != Expression::kValue) { |
979 Move(context, r3); | 941 Apply(context, r3); |
980 } | 942 } |
981 break; | 943 break; |
982 } | 944 } |
983 | 945 |
984 case Slot::LOOKUP: | 946 case Slot::LOOKUP: |
985 UNREACHABLE(); | 947 UNREACHABLE(); |
986 break; | 948 break; |
987 } | 949 } |
988 } else { | 950 } else { |
989 // Variables rewritten as properties are not treated as variables in | 951 // Variables rewritten as properties are not treated as variables in |
(...skipping 25 matching lines...) Expand all Loading... | |
1015 | 977 |
1016 // If the assignment ends an initialization block, revert to fast case. | 978 // If the assignment ends an initialization block, revert to fast case. |
1017 if (expr->ends_initialization_block()) { | 979 if (expr->ends_initialization_block()) { |
1018 __ push(r0); // Result of assignment, saved even if not needed. | 980 __ push(r0); // Result of assignment, saved even if not needed. |
1019 __ ldr(ip, MemOperand(sp, kPointerSize)); // Receiver is under value. | 981 __ ldr(ip, MemOperand(sp, kPointerSize)); // Receiver is under value. |
1020 __ push(ip); | 982 __ push(ip); |
1021 __ CallRuntime(Runtime::kToFastProperties, 1); | 983 __ CallRuntime(Runtime::kToFastProperties, 1); |
1022 __ pop(r0); | 984 __ pop(r0); |
1023 } | 985 } |
1024 | 986 |
1025 DropAndMove(expr->context(), r0); | 987 DropAndApply(1, expr->context(), r0); |
1026 } | 988 } |
1027 | 989 |
1028 | 990 |
1029 void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 991 void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
1030 // Assignment to a property, using a keyed store IC. | 992 // Assignment to a property, using a keyed store IC. |
1031 | 993 |
1032 // If the assignment starts a block of assignments to the same object, | 994 // If the assignment starts a block of assignments to the same object, |
1033 // change to slow case to avoid the quadratic behavior of repeatedly | 995 // change to slow case to avoid the quadratic behavior of repeatedly |
1034 // adding fast properties. | 996 // adding fast properties. |
1035 if (expr->starts_initialization_block()) { | 997 if (expr->starts_initialization_block()) { |
(...skipping 11 matching lines...) Expand all Loading... | |
1047 if (expr->ends_initialization_block()) { | 1009 if (expr->ends_initialization_block()) { |
1048 __ push(r0); // Result of assignment, saved even if not needed. | 1010 __ push(r0); // Result of assignment, saved even if not needed. |
1049 // Reciever is under the key and value. | 1011 // Reciever is under the key and value. |
1050 __ ldr(ip, MemOperand(sp, 2 * kPointerSize)); | 1012 __ ldr(ip, MemOperand(sp, 2 * kPointerSize)); |
1051 __ push(ip); | 1013 __ push(ip); |
1052 __ CallRuntime(Runtime::kToFastProperties, 1); | 1014 __ CallRuntime(Runtime::kToFastProperties, 1); |
1053 __ pop(r0); | 1015 __ pop(r0); |
1054 } | 1016 } |
1055 | 1017 |
1056 // Receiver and key are still on stack. | 1018 // Receiver and key are still on stack. |
1057 __ add(sp, sp, Operand(2 * kPointerSize)); | 1019 DropAndApply(2, expr->context(), r0); |
1058 Move(expr->context(), r0); | |
1059 } | 1020 } |
1060 | 1021 |
1061 | 1022 |
1062 void FastCodeGenerator::VisitProperty(Property* expr) { | 1023 void FastCodeGenerator::VisitProperty(Property* expr) { |
1063 Comment cmnt(masm_, "[ Property"); | 1024 Comment cmnt(masm_, "[ Property"); |
1064 Expression* key = expr->key(); | 1025 Expression* key = expr->key(); |
1065 uint32_t dummy; | |
1066 | 1026 |
1067 // Record the source position for the property load. | 1027 // Record the source position for the property load. |
1068 SetSourcePosition(expr->position()); | 1028 SetSourcePosition(expr->position()); |
1069 | 1029 |
1070 // Evaluate receiver. | 1030 // Evaluate receiver. |
1071 Visit(expr->obj()); | 1031 Visit(expr->obj()); |
1072 | 1032 |
1073 if (key->AsLiteral() != NULL && key->AsLiteral()->handle()->IsSymbol() && | 1033 if (key->IsPropertyName()) { |
1074 !String::cast(*(key->AsLiteral()->handle()))->AsArrayIndex(&dummy)) { | 1034 // Do a named property load. The IC expects the property name in r2 and |
1075 // Do a NAMED property load. | 1035 // the receiver on the stack. |
1076 // The IC expects the property name in r2 and the receiver on the stack. | |
1077 __ mov(r2, Operand(key->AsLiteral()->handle())); | 1036 __ mov(r2, Operand(key->AsLiteral()->handle())); |
1078 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1037 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
1079 __ Call(ic, RelocInfo::CODE_TARGET); | 1038 __ Call(ic, RelocInfo::CODE_TARGET); |
1039 DropAndApply(1, expr->context(), r0); | |
1080 } else { | 1040 } else { |
1081 // Do a KEYED property load. | 1041 // Do a keyed property load. |
1082 Visit(expr->key()); | 1042 Visit(expr->key()); |
1083 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1043 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
1084 __ Call(ic, RelocInfo::CODE_TARGET); | 1044 __ Call(ic, RelocInfo::CODE_TARGET); |
1085 // Drop key and receiver left on the stack by IC. | 1045 // Drop key and receiver left on the stack by IC. |
1086 __ pop(); | 1046 DropAndApply(2, expr->context(), r0); |
1087 } | 1047 } |
1088 DropAndMove(expr->context(), r0); | |
1089 } | 1048 } |
1090 | 1049 |
1091 void FastCodeGenerator::EmitCallWithIC(Call* expr, | 1050 void FastCodeGenerator::EmitCallWithIC(Call* expr, |
1092 Handle<Object> ignored, | 1051 Handle<Object> ignored, |
1093 RelocInfo::Mode mode) { | 1052 RelocInfo::Mode mode) { |
1094 // Code common for calls using the IC. | 1053 // Code common for calls using the IC. |
1095 ZoneList<Expression*>* args = expr->arguments(); | 1054 ZoneList<Expression*>* args = expr->arguments(); |
1096 int arg_count = args->length(); | 1055 int arg_count = args->length(); |
1097 for (int i = 0; i < arg_count; i++) { | 1056 for (int i = 0; i < arg_count; i++) { |
1098 Visit(args->at(i)); | 1057 Visit(args->at(i)); |
1099 ASSERT_EQ(Expression::kValue, args->at(i)->context()); | 1058 ASSERT_EQ(Expression::kValue, args->at(i)->context()); |
1100 } | 1059 } |
1101 // Record source position for debugger. | 1060 // Record source position for debugger. |
1102 SetSourcePosition(expr->position()); | 1061 SetSourcePosition(expr->position()); |
1103 // Call the IC initialization code. | 1062 // Call the IC initialization code. |
1104 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, | 1063 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, |
1105 NOT_IN_LOOP); | 1064 NOT_IN_LOOP); |
1106 __ Call(ic, mode); | 1065 __ Call(ic, mode); |
1107 // Restore context register. | 1066 // Restore context register. |
1108 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1067 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
1109 // Discard the function left on TOS. | 1068 // Discard the function left on TOS. |
1110 DropAndMove(expr->context(), r0); | 1069 DropAndApply(1, expr->context(), r0); |
1111 } | 1070 } |
1112 | 1071 |
1113 | 1072 |
1114 void FastCodeGenerator::EmitCallWithStub(Call* expr) { | 1073 void FastCodeGenerator::EmitCallWithStub(Call* expr) { |
1115 // Code common for calls using the call stub. | 1074 // Code common for calls using the call stub. |
1116 ZoneList<Expression*>* args = expr->arguments(); | 1075 ZoneList<Expression*>* args = expr->arguments(); |
1117 int arg_count = args->length(); | 1076 int arg_count = args->length(); |
1118 for (int i = 0; i < arg_count; i++) { | 1077 for (int i = 0; i < arg_count; i++) { |
1119 Visit(args->at(i)); | 1078 Visit(args->at(i)); |
1120 } | 1079 } |
1121 // Record source position for debugger. | 1080 // Record source position for debugger. |
1122 SetSourcePosition(expr->position()); | 1081 SetSourcePosition(expr->position()); |
1123 CallFunctionStub stub(arg_count, NOT_IN_LOOP); | 1082 CallFunctionStub stub(arg_count, NOT_IN_LOOP); |
1124 __ CallStub(&stub); | 1083 __ CallStub(&stub); |
1125 // Restore context register. | 1084 // Restore context register. |
1126 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1085 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
1127 // Discard the function left on TOS. | 1086 // Discard the function left on TOS. |
1128 DropAndMove(expr->context(), r0); | 1087 DropAndApply(1, expr->context(), r0); |
1129 } | 1088 } |
1130 | 1089 |
1131 | 1090 |
1132 void FastCodeGenerator::VisitCall(Call* expr) { | 1091 void FastCodeGenerator::VisitCall(Call* expr) { |
1133 Comment cmnt(masm_, "[ Call"); | 1092 Comment cmnt(masm_, "[ Call"); |
1134 Expression* fun = expr->expression(); | 1093 Expression* fun = expr->expression(); |
1135 Variable* var = fun->AsVariableProxy()->AsVariable(); | 1094 Variable* var = fun->AsVariableProxy()->AsVariable(); |
1136 | 1095 |
1137 if (var != NULL && var->is_possibly_eval()) { | 1096 if (var != NULL && var->is_possibly_eval()) { |
1138 // Call to the identifier 'eval'. | 1097 // Call to the identifier 'eval'. |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1227 | 1186 |
1228 // Load function, arg_count into r1 and r0. | 1187 // Load function, arg_count into r1 and r0. |
1229 __ mov(r0, Operand(arg_count)); | 1188 __ mov(r0, Operand(arg_count)); |
1230 // Function is in sp[arg_count + 1]. | 1189 // Function is in sp[arg_count + 1]. |
1231 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); | 1190 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
1232 | 1191 |
1233 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); | 1192 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); |
1234 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); | 1193 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); |
1235 | 1194 |
1236 // Replace function on TOS with result in r0, or pop it. | 1195 // Replace function on TOS with result in r0, or pop it. |
1237 DropAndMove(expr->context(), r0); | 1196 DropAndApply(1, expr->context(), r0); |
1238 } | 1197 } |
1239 | 1198 |
1240 | 1199 |
1241 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 1200 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
1242 Comment cmnt(masm_, "[ CallRuntime"); | 1201 Comment cmnt(masm_, "[ CallRuntime"); |
1243 ZoneList<Expression*>* args = expr->arguments(); | 1202 ZoneList<Expression*>* args = expr->arguments(); |
1244 | 1203 |
1245 if (expr->is_jsruntime()) { | 1204 if (expr->is_jsruntime()) { |
1246 // Prepare for calling JS runtime function. | 1205 // Prepare for calling JS runtime function. |
1247 __ mov(r1, Operand(expr->name())); | 1206 __ mov(r1, Operand(expr->name())); |
(...skipping 10 matching lines...) Expand all Loading... | |
1258 } | 1217 } |
1259 | 1218 |
1260 if (expr->is_jsruntime()) { | 1219 if (expr->is_jsruntime()) { |
1261 // Call the JS runtime function. | 1220 // Call the JS runtime function. |
1262 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, | 1221 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, |
1263 NOT_IN_LOOP); | 1222 NOT_IN_LOOP); |
1264 __ Call(ic, RelocInfo::CODE_TARGET); | 1223 __ Call(ic, RelocInfo::CODE_TARGET); |
1265 // Restore context register. | 1224 // Restore context register. |
1266 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1225 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
1267 // Discard the function left on TOS. | 1226 // Discard the function left on TOS. |
1268 DropAndMove(expr->context(), r0); | 1227 DropAndApply(1, expr->context(), r0); |
1269 } else { | 1228 } else { |
1270 // Call the C runtime function. | 1229 // Call the C runtime function. |
1271 __ CallRuntime(expr->function(), arg_count); | 1230 __ CallRuntime(expr->function(), arg_count); |
1272 Move(expr->context(), r0); | 1231 Apply(expr->context(), r0); |
1273 } | 1232 } |
1274 } | 1233 } |
1275 | 1234 |
1276 | 1235 |
1277 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 1236 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
1278 switch (expr->op()) { | 1237 switch (expr->op()) { |
1279 case Token::VOID: { | 1238 case Token::VOID: { |
1280 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); | 1239 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); |
1281 Visit(expr->expression()); | 1240 Visit(expr->expression()); |
1282 ASSERT_EQ(Expression::kEffect, expr->expression()->context()); | 1241 ASSERT_EQ(Expression::kEffect, expr->expression()->context()); |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1391 __ mov(r0, Operand(proxy->name())); | 1350 __ mov(r0, Operand(proxy->name())); |
1392 __ stm(db_w, sp, cp.bit() | r0.bit()); | 1351 __ stm(db_w, sp, cp.bit() | r0.bit()); |
1393 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); | 1352 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); |
1394 __ push(r0); | 1353 __ push(r0); |
1395 } else { | 1354 } else { |
1396 // This expression cannot throw a reference error at the top level. | 1355 // This expression cannot throw a reference error at the top level. |
1397 Visit(expr->expression()); | 1356 Visit(expr->expression()); |
1398 } | 1357 } |
1399 | 1358 |
1400 __ CallRuntime(Runtime::kTypeof, 1); | 1359 __ CallRuntime(Runtime::kTypeof, 1); |
1401 Move(expr->context(), r0); | 1360 Apply(expr->context(), r0); |
1402 break; | 1361 break; |
1403 } | 1362 } |
1404 | 1363 |
1405 default: | 1364 default: |
1406 UNREACHABLE(); | 1365 UNREACHABLE(); |
1407 } | 1366 } |
1408 } | 1367 } |
1409 | 1368 |
1410 | 1369 |
1411 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { | 1370 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1492 // Store the value returned in r0. | 1451 // Store the value returned in r0. |
1493 switch (assign_type) { | 1452 switch (assign_type) { |
1494 case VARIABLE: | 1453 case VARIABLE: |
1495 __ push(r0); | 1454 __ push(r0); |
1496 if (expr->is_postfix()) { | 1455 if (expr->is_postfix()) { |
1497 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 1456 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
1498 Expression::kEffect); | 1457 Expression::kEffect); |
1499 // For all contexts except kEffect: We have the result on | 1458 // For all contexts except kEffect: We have the result on |
1500 // top of the stack. | 1459 // top of the stack. |
1501 if (expr->context() != Expression::kEffect) { | 1460 if (expr->context() != Expression::kEffect) { |
1502 MoveTOS(expr->context()); | 1461 ApplyTOS(expr->context()); |
1503 } | 1462 } |
1504 } else { | 1463 } else { |
1505 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 1464 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
1506 expr->context()); | 1465 expr->context()); |
1507 } | 1466 } |
1508 break; | 1467 break; |
1509 case NAMED_PROPERTY: { | 1468 case NAMED_PROPERTY: { |
1510 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); | 1469 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); |
1511 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1470 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
1512 __ Call(ic, RelocInfo::CODE_TARGET); | 1471 __ Call(ic, RelocInfo::CODE_TARGET); |
1513 if (expr->is_postfix()) { | 1472 if (expr->is_postfix()) { |
1514 __ Drop(1); // Result is on the stack under the receiver. | 1473 __ Drop(1); // Result is on the stack under the receiver. |
1515 if (expr->context() != Expression::kEffect) { | 1474 if (expr->context() != Expression::kEffect) { |
1516 MoveTOS(expr->context()); | 1475 ApplyTOS(expr->context()); |
1517 } | 1476 } |
1518 } else { | 1477 } else { |
1519 DropAndMove(expr->context(), r0); | 1478 DropAndApply(1, expr->context(), r0); |
1520 } | 1479 } |
1521 break; | 1480 break; |
1522 } | 1481 } |
1523 case KEYED_PROPERTY: { | 1482 case KEYED_PROPERTY: { |
1524 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 1483 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
1525 __ Call(ic, RelocInfo::CODE_TARGET); | 1484 __ Call(ic, RelocInfo::CODE_TARGET); |
1526 if (expr->is_postfix()) { | 1485 if (expr->is_postfix()) { |
1527 __ Drop(2); // Result is on the stack under the key and the receiver. | 1486 __ Drop(2); // Result is on the stack under the key and the receiver. |
1528 if (expr->context() != Expression::kEffect) { | 1487 if (expr->context() != Expression::kEffect) { |
1529 MoveTOS(expr->context()); | 1488 ApplyTOS(expr->context()); |
1530 } | 1489 } |
1531 } else { | 1490 } else { |
1532 DropAndMove(expr->context(), r0, 2); | 1491 DropAndApply(2, expr->context(), r0); |
1533 } | 1492 } |
1534 break; | 1493 break; |
1535 } | 1494 } |
1536 } | 1495 } |
1537 } | 1496 } |
1538 | 1497 |
1539 | 1498 |
1540 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 1499 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
1541 Comment cmnt(masm_, "[ BinaryOperation"); | 1500 Comment cmnt(masm_, "[ BinaryOperation"); |
1542 switch (expr->op()) { | 1501 switch (expr->op()) { |
(...skipping 23 matching lines...) Expand all Loading... | |
1566 ASSERT_EQ(Expression::kValue, expr->left()->context()); | 1525 ASSERT_EQ(Expression::kValue, expr->left()->context()); |
1567 ASSERT_EQ(Expression::kValue, expr->right()->context()); | 1526 ASSERT_EQ(Expression::kValue, expr->right()->context()); |
1568 | 1527 |
1569 Visit(expr->left()); | 1528 Visit(expr->left()); |
1570 Visit(expr->right()); | 1529 Visit(expr->right()); |
1571 __ pop(r0); | 1530 __ pop(r0); |
1572 __ pop(r1); | 1531 __ pop(r1); |
1573 GenericBinaryOpStub stub(expr->op(), | 1532 GenericBinaryOpStub stub(expr->op(), |
1574 NO_OVERWRITE); | 1533 NO_OVERWRITE); |
1575 __ CallStub(&stub); | 1534 __ CallStub(&stub); |
1576 Move(expr->context(), r0); | 1535 Apply(expr->context(), r0); |
1577 | 1536 |
1578 break; | 1537 break; |
1579 } | 1538 } |
1580 default: | 1539 default: |
1581 UNREACHABLE(); | 1540 UNREACHABLE(); |
1582 } | 1541 } |
1583 } | 1542 } |
1584 | 1543 |
1585 | 1544 |
1586 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 1545 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1741 break; | 1700 break; |
1742 } | 1701 } |
1743 true_label_ = saved_true; | 1702 true_label_ = saved_true; |
1744 false_label_ = saved_false; | 1703 false_label_ = saved_false; |
1745 // Convert current context to test context: End post-test code. | 1704 // Convert current context to test context: End post-test code. |
1746 } | 1705 } |
1747 | 1706 |
1748 | 1707 |
1749 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 1708 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
1750 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1709 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
1751 Move(expr->context(), r0); | 1710 Apply(expr->context(), r0); |
1752 } | 1711 } |
1753 | 1712 |
1754 | 1713 |
1755 Register FastCodeGenerator::result_register() { return r0; } | 1714 Register FastCodeGenerator::result_register() { return r0; } |
1756 | 1715 |
1757 | 1716 |
1758 Register FastCodeGenerator::context_register() { return cp; } | 1717 Register FastCodeGenerator::context_register() { return cp; } |
1759 | 1718 |
1760 | 1719 |
1761 void FastCodeGenerator::StoreToFrameField(int frame_offset, Register value) { | 1720 void FastCodeGenerator::StoreToFrameField(int frame_offset, Register value) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1793 __ pop(result_register()); | 1752 __ pop(result_register()); |
1794 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); | 1753 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); |
1795 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 1754 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
1796 __ add(pc, r1, Operand(masm_->CodeObject())); | 1755 __ add(pc, r1, Operand(masm_->CodeObject())); |
1797 } | 1756 } |
1798 | 1757 |
1799 | 1758 |
1800 #undef __ | 1759 #undef __ |
1801 | 1760 |
1802 } } // namespace v8::internal | 1761 } } // namespace v8::internal |
OLD | NEW |