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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 // | 45 // |
46 // The live registers are: | 46 // The live registers are: |
47 // o r1: the JS function object being called (ie, ourselves) | 47 // o r1: the JS function object being called (ie, ourselves) |
48 // o cp: our context | 48 // o cp: our context |
49 // o fp: our caller's frame pointer | 49 // o fp: our caller's frame pointer |
50 // o sp: stack pointer | 50 // o sp: stack pointer |
51 // o lr: return address | 51 // o lr: return address |
52 // | 52 // |
53 // The function builds a JS frame. Please see JavaScriptFrameConstants in | 53 // The function builds a JS frame. Please see JavaScriptFrameConstants in |
54 // frames-arm.h for its layout. | 54 // frames-arm.h for its layout. |
55 void FastCodeGenerator::Generate(FunctionLiteral* fun) { | 55 void FullCodeGenerator::Generate(FunctionLiteral* fun) { |
56 function_ = fun; | 56 function_ = fun; |
57 SetFunctionPosition(fun); | 57 SetFunctionPosition(fun); |
58 int locals_count = fun->scope()->num_stack_slots(); | 58 int locals_count = fun->scope()->num_stack_slots(); |
59 | 59 |
60 __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); | 60 __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); |
61 if (locals_count > 0) { | 61 if (locals_count > 0) { |
62 // Load undefined value here, so the value is ready for the loop below. | 62 // Load undefined value here, so the value is ready for the loop below. |
63 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 63 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
64 } | 64 } |
65 // Adjust fp to point to caller's fp. | 65 // Adjust fp to point to caller's fp. |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 | 160 |
161 { Comment cmnt(masm_, "[ return <undefined>;"); | 161 { Comment cmnt(masm_, "[ return <undefined>;"); |
162 // Emit a 'return undefined' in case control fell off the end of the | 162 // Emit a 'return undefined' in case control fell off the end of the |
163 // body. | 163 // body. |
164 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 164 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
165 } | 165 } |
166 EmitReturnSequence(function_->end_position()); | 166 EmitReturnSequence(function_->end_position()); |
167 } | 167 } |
168 | 168 |
169 | 169 |
170 void FastCodeGenerator::EmitReturnSequence(int position) { | 170 void FullCodeGenerator::EmitReturnSequence(int position) { |
171 Comment cmnt(masm_, "[ Return sequence"); | 171 Comment cmnt(masm_, "[ Return sequence"); |
172 if (return_label_.is_bound()) { | 172 if (return_label_.is_bound()) { |
173 __ b(&return_label_); | 173 __ b(&return_label_); |
174 } else { | 174 } else { |
175 __ bind(&return_label_); | 175 __ bind(&return_label_); |
176 if (FLAG_trace) { | 176 if (FLAG_trace) { |
177 // Push the return value on the stack as the parameter. | 177 // Push the return value on the stack as the parameter. |
178 // Runtime::TraceExit returns its parameter in r0. | 178 // Runtime::TraceExit returns its parameter in r0. |
179 __ push(r0); | 179 __ push(r0); |
180 __ CallRuntime(Runtime::kTraceExit, 1); | 180 __ CallRuntime(Runtime::kTraceExit, 1); |
(...skipping 26 matching lines...) Expand all 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::Apply(Expression::Context context, Register reg) { | 217 void FullCodeGenerator::Apply(Expression::Context context, Register reg) { |
218 switch (context) { | 218 switch (context) { |
219 case Expression::kUninitialized: | 219 case Expression::kUninitialized: |
220 UNREACHABLE(); | 220 UNREACHABLE(); |
221 | 221 |
222 case Expression::kEffect: | 222 case Expression::kEffect: |
223 // Nothing to do. | 223 // Nothing to do. |
224 break; | 224 break; |
225 | 225 |
226 case Expression::kValue: | 226 case Expression::kValue: |
227 // Move value into place. | 227 // Move value into place. |
(...skipping 15 matching lines...) Expand all Loading... |
243 | 243 |
244 case Expression::kTest: | 244 case Expression::kTest: |
245 // We always call the runtime on ARM, so push the value as argument. | 245 // We always call the runtime on ARM, so push the value as argument. |
246 __ push(reg); | 246 __ push(reg); |
247 DoTest(context); | 247 DoTest(context); |
248 break; | 248 break; |
249 } | 249 } |
250 } | 250 } |
251 | 251 |
252 | 252 |
253 void FastCodeGenerator::Apply(Expression::Context context, Slot* slot) { | 253 void FullCodeGenerator::Apply(Expression::Context context, Slot* slot) { |
254 switch (context) { | 254 switch (context) { |
255 case Expression::kUninitialized: | 255 case Expression::kUninitialized: |
256 UNREACHABLE(); | 256 UNREACHABLE(); |
257 case Expression::kEffect: | 257 case Expression::kEffect: |
258 // Nothing to do. | 258 // Nothing to do. |
259 break; | 259 break; |
260 case Expression::kValue: | 260 case Expression::kValue: |
261 case Expression::kTest: | 261 case Expression::kTest: |
262 case Expression::kValueTest: | 262 case Expression::kValueTest: |
263 case Expression::kTestValue: | 263 case Expression::kTestValue: |
264 // On ARM we have to move the value into a register to do anything | 264 // On ARM we have to move the value into a register to do anything |
265 // with it. | 265 // with it. |
266 Move(result_register(), slot); | 266 Move(result_register(), slot); |
267 Apply(context, result_register()); | 267 Apply(context, result_register()); |
268 break; | 268 break; |
269 } | 269 } |
270 } | 270 } |
271 | 271 |
272 | 272 |
273 void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) { | 273 void FullCodeGenerator::Apply(Expression::Context context, Literal* lit) { |
274 switch (context) { | 274 switch (context) { |
275 case Expression::kUninitialized: | 275 case Expression::kUninitialized: |
276 UNREACHABLE(); | 276 UNREACHABLE(); |
277 case Expression::kEffect: | 277 case Expression::kEffect: |
278 break; | 278 break; |
279 // Nothing to do. | 279 // Nothing to do. |
280 case Expression::kValue: | 280 case Expression::kValue: |
281 case Expression::kTest: | 281 case Expression::kTest: |
282 case Expression::kValueTest: | 282 case Expression::kValueTest: |
283 case Expression::kTestValue: | 283 case Expression::kTestValue: |
284 // On ARM we have to move the value into a register to do anything | 284 // On ARM we have to move the value into a register to do anything |
285 // with it. | 285 // with it. |
286 __ mov(result_register(), Operand(lit->handle())); | 286 __ mov(result_register(), Operand(lit->handle())); |
287 Apply(context, result_register()); | 287 Apply(context, result_register()); |
288 break; | 288 break; |
289 } | 289 } |
290 } | 290 } |
291 | 291 |
292 | 292 |
293 void FastCodeGenerator::ApplyTOS(Expression::Context context) { | 293 void FullCodeGenerator::ApplyTOS(Expression::Context context) { |
294 switch (context) { | 294 switch (context) { |
295 case Expression::kUninitialized: | 295 case Expression::kUninitialized: |
296 UNREACHABLE(); | 296 UNREACHABLE(); |
297 | 297 |
298 case Expression::kEffect: | 298 case Expression::kEffect: |
299 __ Drop(1); | 299 __ Drop(1); |
300 break; | 300 break; |
301 | 301 |
302 case Expression::kValue: | 302 case Expression::kValue: |
303 switch (location_) { | 303 switch (location_) { |
(...skipping 12 matching lines...) Expand all Loading... |
316 __ push(ip); | 316 __ push(ip); |
317 // Fall through. | 317 // Fall through. |
318 | 318 |
319 case Expression::kTest: | 319 case Expression::kTest: |
320 DoTest(context); | 320 DoTest(context); |
321 break; | 321 break; |
322 } | 322 } |
323 } | 323 } |
324 | 324 |
325 | 325 |
326 void FastCodeGenerator::DropAndApply(int count, | 326 void FullCodeGenerator::DropAndApply(int count, |
327 Expression::Context context, | 327 Expression::Context context, |
328 Register reg) { | 328 Register reg) { |
329 ASSERT(count > 0); | 329 ASSERT(count > 0); |
330 ASSERT(!reg.is(sp)); | 330 ASSERT(!reg.is(sp)); |
331 switch (context) { | 331 switch (context) { |
332 case Expression::kUninitialized: | 332 case Expression::kUninitialized: |
333 UNREACHABLE(); | 333 UNREACHABLE(); |
334 | 334 |
335 case Expression::kEffect: | 335 case Expression::kEffect: |
336 __ Drop(count); | 336 __ Drop(count); |
(...skipping 27 matching lines...) Expand all Loading... |
364 __ Drop(count - 2); | 364 __ Drop(count - 2); |
365 __ str(reg, MemOperand(sp, kPointerSize)); | 365 __ str(reg, MemOperand(sp, kPointerSize)); |
366 __ str(reg, MemOperand(sp)); | 366 __ str(reg, MemOperand(sp)); |
367 } | 367 } |
368 DoTest(context); | 368 DoTest(context); |
369 break; | 369 break; |
370 } | 370 } |
371 } | 371 } |
372 | 372 |
373 | 373 |
374 void FastCodeGenerator::Apply(Expression::Context context, | 374 void FullCodeGenerator::Apply(Expression::Context context, |
375 Label* materialize_true, | 375 Label* materialize_true, |
376 Label* materialize_false) { | 376 Label* materialize_false) { |
377 switch (context) { | 377 switch (context) { |
378 case Expression::kUninitialized: | 378 case Expression::kUninitialized: |
379 | 379 |
380 case Expression::kEffect: | 380 case Expression::kEffect: |
381 ASSERT_EQ(materialize_true, materialize_false); | 381 ASSERT_EQ(materialize_true, materialize_false); |
382 __ bind(materialize_true); | 382 __ bind(materialize_true); |
383 break; | 383 break; |
384 | 384 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
425 case kStack: | 425 case kStack: |
426 __ push(result_register()); | 426 __ push(result_register()); |
427 break; | 427 break; |
428 } | 428 } |
429 __ jmp(false_label_); | 429 __ jmp(false_label_); |
430 break; | 430 break; |
431 } | 431 } |
432 } | 432 } |
433 | 433 |
434 | 434 |
435 void FastCodeGenerator::DoTest(Expression::Context context) { | 435 void FullCodeGenerator::DoTest(Expression::Context context) { |
436 // The value to test is pushed on the stack, and duplicated on the stack | 436 // The value to test is pushed on the stack, and duplicated on the stack |
437 // if necessary (for value/test and test/value contexts). | 437 // if necessary (for value/test and test/value contexts). |
438 ASSERT_NE(NULL, true_label_); | 438 ASSERT_NE(NULL, true_label_); |
439 ASSERT_NE(NULL, false_label_); | 439 ASSERT_NE(NULL, false_label_); |
440 | 440 |
441 // Call the runtime to find the boolean value of the source and then | 441 // Call the runtime to find the boolean value of the source and then |
442 // translate it into control flow to the pair of labels. | 442 // translate it into control flow to the pair of labels. |
443 __ CallRuntime(Runtime::kToBool, 1); | 443 __ CallRuntime(Runtime::kToBool, 1); |
444 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 444 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
445 __ cmp(r0, ip); | 445 __ cmp(r0, ip); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
488 } | 488 } |
489 __ bind(&discard); | 489 __ bind(&discard); |
490 __ Drop(1); | 490 __ Drop(1); |
491 __ jmp(true_label_); | 491 __ jmp(true_label_); |
492 break; | 492 break; |
493 } | 493 } |
494 } | 494 } |
495 } | 495 } |
496 | 496 |
497 | 497 |
498 MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { | 498 MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { |
499 switch (slot->type()) { | 499 switch (slot->type()) { |
500 case Slot::PARAMETER: | 500 case Slot::PARAMETER: |
501 case Slot::LOCAL: | 501 case Slot::LOCAL: |
502 return MemOperand(fp, SlotOffset(slot)); | 502 return MemOperand(fp, SlotOffset(slot)); |
503 case Slot::CONTEXT: { | 503 case Slot::CONTEXT: { |
504 int context_chain_length = | 504 int context_chain_length = |
505 function_->scope()->ContextChainLength(slot->var()->scope()); | 505 function_->scope()->ContextChainLength(slot->var()->scope()); |
506 __ LoadContext(scratch, context_chain_length); | 506 __ LoadContext(scratch, context_chain_length); |
507 return CodeGenerator::ContextOperand(scratch, slot->index()); | 507 return CodeGenerator::ContextOperand(scratch, slot->index()); |
508 } | 508 } |
509 case Slot::LOOKUP: | 509 case Slot::LOOKUP: |
510 UNREACHABLE(); | 510 UNREACHABLE(); |
511 } | 511 } |
512 UNREACHABLE(); | 512 UNREACHABLE(); |
513 return MemOperand(r0, 0); | 513 return MemOperand(r0, 0); |
514 } | 514 } |
515 | 515 |
516 | 516 |
517 void FastCodeGenerator::Move(Register destination, Slot* source) { | 517 void FullCodeGenerator::Move(Register destination, Slot* source) { |
518 // Use destination as scratch. | 518 // Use destination as scratch. |
519 MemOperand slot_operand = EmitSlotSearch(source, destination); | 519 MemOperand slot_operand = EmitSlotSearch(source, destination); |
520 __ ldr(destination, slot_operand); | 520 __ ldr(destination, slot_operand); |
521 } | 521 } |
522 | 522 |
523 | 523 |
524 void FastCodeGenerator::Move(Slot* dst, | 524 void FullCodeGenerator::Move(Slot* dst, |
525 Register src, | 525 Register src, |
526 Register scratch1, | 526 Register scratch1, |
527 Register scratch2) { | 527 Register scratch2) { |
528 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. | 528 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. |
529 ASSERT(!scratch1.is(src) && !scratch2.is(src)); | 529 ASSERT(!scratch1.is(src) && !scratch2.is(src)); |
530 MemOperand location = EmitSlotSearch(dst, scratch1); | 530 MemOperand location = EmitSlotSearch(dst, scratch1); |
531 __ str(src, location); | 531 __ str(src, location); |
532 // Emit the write barrier code if the location is in the heap. | 532 // Emit the write barrier code if the location is in the heap. |
533 if (dst->type() == Slot::CONTEXT) { | 533 if (dst->type() == Slot::CONTEXT) { |
534 __ mov(scratch2, Operand(Context::SlotOffset(dst->index()))); | 534 __ mov(scratch2, Operand(Context::SlotOffset(dst->index()))); |
535 __ RecordWrite(scratch1, scratch2, src); | 535 __ RecordWrite(scratch1, scratch2, src); |
536 } | 536 } |
537 } | 537 } |
538 | 538 |
539 | 539 |
540 void FastCodeGenerator::VisitDeclaration(Declaration* decl) { | 540 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { |
541 Comment cmnt(masm_, "[ Declaration"); | 541 Comment cmnt(masm_, "[ Declaration"); |
542 Variable* var = decl->proxy()->var(); | 542 Variable* var = decl->proxy()->var(); |
543 ASSERT(var != NULL); // Must have been resolved. | 543 ASSERT(var != NULL); // Must have been resolved. |
544 Slot* slot = var->slot(); | 544 Slot* slot = var->slot(); |
545 Property* prop = var->AsProperty(); | 545 Property* prop = var->AsProperty(); |
546 | 546 |
547 if (slot != NULL) { | 547 if (slot != NULL) { |
548 switch (slot->type()) { | 548 switch (slot->type()) { |
549 case Slot::PARAMETER: | 549 case Slot::PARAMETER: |
550 case Slot::LOCAL: | 550 case Slot::LOCAL: |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
630 __ Call(ic, RelocInfo::CODE_TARGET); | 630 __ Call(ic, RelocInfo::CODE_TARGET); |
631 | 631 |
632 // Value in r0 is ignored (declarations are statements). Receiver | 632 // Value in r0 is ignored (declarations are statements). Receiver |
633 // and key on stack are discarded. | 633 // and key on stack are discarded. |
634 __ Drop(2); | 634 __ Drop(2); |
635 } | 635 } |
636 } | 636 } |
637 } | 637 } |
638 | 638 |
639 | 639 |
640 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 640 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
641 // Call the runtime to declare the globals. | 641 // Call the runtime to declare the globals. |
642 // The context is the first argument. | 642 // The context is the first argument. |
643 __ mov(r1, Operand(pairs)); | 643 __ mov(r1, Operand(pairs)); |
644 __ mov(r0, Operand(Smi::FromInt(is_eval_ ? 1 : 0))); | 644 __ mov(r0, Operand(Smi::FromInt(is_eval_ ? 1 : 0))); |
645 __ stm(db_w, sp, cp.bit() | r1.bit() | r0.bit()); | 645 __ stm(db_w, sp, cp.bit() | r1.bit() | r0.bit()); |
646 __ CallRuntime(Runtime::kDeclareGlobals, 3); | 646 __ CallRuntime(Runtime::kDeclareGlobals, 3); |
647 // Return value is ignored. | 647 // Return value is ignored. |
648 } | 648 } |
649 | 649 |
650 | 650 |
651 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { | 651 void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { |
652 Comment cmnt(masm_, "[ FunctionLiteral"); | 652 Comment cmnt(masm_, "[ FunctionLiteral"); |
653 | 653 |
654 // Build the function boilerplate and instantiate it. | 654 // Build the function boilerplate and instantiate it. |
655 Handle<JSFunction> boilerplate = | 655 Handle<JSFunction> boilerplate = |
656 Compiler::BuildBoilerplate(expr, script_, this); | 656 Compiler::BuildBoilerplate(expr, script_, this); |
657 if (HasStackOverflow()) return; | 657 if (HasStackOverflow()) return; |
658 | 658 |
659 ASSERT(boilerplate->IsBoilerplate()); | 659 ASSERT(boilerplate->IsBoilerplate()); |
660 | 660 |
661 // Create a new closure. | 661 // Create a new closure. |
662 __ mov(r0, Operand(boilerplate)); | 662 __ mov(r0, Operand(boilerplate)); |
663 __ stm(db_w, sp, cp.bit() | r0.bit()); | 663 __ stm(db_w, sp, cp.bit() | r0.bit()); |
664 __ CallRuntime(Runtime::kNewClosure, 2); | 664 __ CallRuntime(Runtime::kNewClosure, 2); |
665 Apply(context_, r0); | 665 Apply(context_, r0); |
666 } | 666 } |
667 | 667 |
668 | 668 |
669 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 669 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
670 Comment cmnt(masm_, "[ VariableProxy"); | 670 Comment cmnt(masm_, "[ VariableProxy"); |
671 EmitVariableLoad(expr->var(), context_); | 671 EmitVariableLoad(expr->var(), context_); |
672 } | 672 } |
673 | 673 |
674 | 674 |
675 void FastCodeGenerator::EmitVariableLoad(Variable* var, | 675 void FullCodeGenerator::EmitVariableLoad(Variable* var, |
676 Expression::Context context) { | 676 Expression::Context context) { |
677 Expression* rewrite = var->rewrite(); | 677 Expression* rewrite = var->rewrite(); |
678 if (rewrite == NULL) { | 678 if (rewrite == NULL) { |
679 ASSERT(var->is_global()); | 679 ASSERT(var->is_global()); |
680 Comment cmnt(masm_, "Global variable"); | 680 Comment cmnt(masm_, "Global variable"); |
681 // Use inline caching. Variable name is passed in r2 and the global | 681 // Use inline caching. Variable name is passed in r2 and the global |
682 // object on the stack. | 682 // object on the stack. |
683 __ ldr(ip, CodeGenerator::GlobalObject()); | 683 __ ldr(ip, CodeGenerator::GlobalObject()); |
684 __ push(ip); | 684 __ push(ip); |
685 __ mov(r2, Operand(var->name())); | 685 __ mov(r2, Operand(var->name())); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
738 // Do a keyed property load. | 738 // Do a keyed property load. |
739 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 739 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
740 __ Call(ic, RelocInfo::CODE_TARGET); | 740 __ Call(ic, RelocInfo::CODE_TARGET); |
741 | 741 |
742 // Drop key and object left on the stack by IC, and push the result. | 742 // Drop key and object left on the stack by IC, and push the result. |
743 DropAndApply(2, context, r0); | 743 DropAndApply(2, context, r0); |
744 } | 744 } |
745 } | 745 } |
746 | 746 |
747 | 747 |
748 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 748 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
749 Comment cmnt(masm_, "[ RegExpLiteral"); | 749 Comment cmnt(masm_, "[ RegExpLiteral"); |
750 Label done; | 750 Label done; |
751 // Registers will be used as follows: | 751 // Registers will be used as follows: |
752 // r4 = JS function, literals array | 752 // r4 = JS function, literals array |
753 // r3 = literal index | 753 // r3 = literal index |
754 // r2 = RegExp pattern | 754 // r2 = RegExp pattern |
755 // r1 = RegExp flags | 755 // r1 = RegExp flags |
756 // r0 = temp + return value (RegExp literal) | 756 // r0 = temp + return value (RegExp literal) |
757 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 757 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
758 __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); | 758 __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset)); |
759 int literal_offset = | 759 int literal_offset = |
760 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; | 760 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
761 __ ldr(r0, FieldMemOperand(r4, literal_offset)); | 761 __ ldr(r0, FieldMemOperand(r4, literal_offset)); |
762 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 762 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
763 __ cmp(r0, ip); | 763 __ cmp(r0, ip); |
764 __ b(ne, &done); | 764 __ b(ne, &done); |
765 __ mov(r3, Operand(Smi::FromInt(expr->literal_index()))); | 765 __ mov(r3, Operand(Smi::FromInt(expr->literal_index()))); |
766 __ mov(r2, Operand(expr->pattern())); | 766 __ mov(r2, Operand(expr->pattern())); |
767 __ mov(r1, Operand(expr->flags())); | 767 __ mov(r1, Operand(expr->flags())); |
768 __ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit()); | 768 __ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit()); |
769 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); | 769 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
770 __ bind(&done); | 770 __ bind(&done); |
771 Apply(context_, r0); | 771 Apply(context_, r0); |
772 } | 772 } |
773 | 773 |
774 | 774 |
775 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 775 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
776 Comment cmnt(masm_, "[ ObjectLiteral"); | 776 Comment cmnt(masm_, "[ ObjectLiteral"); |
777 __ ldr(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 777 __ ldr(r2, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
778 __ ldr(r2, FieldMemOperand(r2, JSFunction::kLiteralsOffset)); | 778 __ ldr(r2, FieldMemOperand(r2, JSFunction::kLiteralsOffset)); |
779 __ mov(r1, Operand(Smi::FromInt(expr->literal_index()))); | 779 __ mov(r1, Operand(Smi::FromInt(expr->literal_index()))); |
780 __ mov(r0, Operand(expr->constant_properties())); | 780 __ mov(r0, Operand(expr->constant_properties())); |
781 __ stm(db_w, sp, r2.bit() | r1.bit() | r0.bit()); | 781 __ stm(db_w, sp, r2.bit() | r1.bit() | r0.bit()); |
782 if (expr->depth() > 1) { | 782 if (expr->depth() > 1) { |
783 __ CallRuntime(Runtime::kCreateObjectLiteral, 3); | 783 __ CallRuntime(Runtime::kCreateObjectLiteral, 3); |
784 } else { | 784 } else { |
785 __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 3); | 785 __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 3); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
840 } | 840 } |
841 | 841 |
842 if (result_saved) { | 842 if (result_saved) { |
843 ApplyTOS(context_); | 843 ApplyTOS(context_); |
844 } else { | 844 } else { |
845 Apply(context_, r0); | 845 Apply(context_, r0); |
846 } | 846 } |
847 } | 847 } |
848 | 848 |
849 | 849 |
850 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 850 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
851 Comment cmnt(masm_, "[ ArrayLiteral"); | 851 Comment cmnt(masm_, "[ ArrayLiteral"); |
852 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 852 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
853 __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); | 853 __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); |
854 __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); | 854 __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); |
855 __ mov(r1, Operand(expr->constant_elements())); | 855 __ mov(r1, Operand(expr->constant_elements())); |
856 __ stm(db_w, sp, r3.bit() | r2.bit() | r1.bit()); | 856 __ stm(db_w, sp, r3.bit() | r2.bit() | r1.bit()); |
857 if (expr->depth() > 1) { | 857 if (expr->depth() > 1) { |
858 __ CallRuntime(Runtime::kCreateArrayLiteral, 3); | 858 __ CallRuntime(Runtime::kCreateArrayLiteral, 3); |
859 } else { | 859 } else { |
860 __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); | 860 __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
893 } | 893 } |
894 | 894 |
895 if (result_saved) { | 895 if (result_saved) { |
896 ApplyTOS(context_); | 896 ApplyTOS(context_); |
897 } else { | 897 } else { |
898 Apply(context_, r0); | 898 Apply(context_, r0); |
899 } | 899 } |
900 } | 900 } |
901 | 901 |
902 | 902 |
903 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 903 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
904 SetSourcePosition(prop->position()); | 904 SetSourcePosition(prop->position()); |
905 Literal* key = prop->key()->AsLiteral(); | 905 Literal* key = prop->key()->AsLiteral(); |
906 __ mov(r2, Operand(key->handle())); | 906 __ mov(r2, Operand(key->handle())); |
907 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 907 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
908 __ Call(ic, RelocInfo::CODE_TARGET); | 908 __ Call(ic, RelocInfo::CODE_TARGET); |
909 } | 909 } |
910 | 910 |
911 | 911 |
912 void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 912 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
913 SetSourcePosition(prop->position()); | 913 SetSourcePosition(prop->position()); |
914 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 914 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
915 __ Call(ic, RelocInfo::CODE_TARGET); | 915 __ Call(ic, RelocInfo::CODE_TARGET); |
916 } | 916 } |
917 | 917 |
918 | 918 |
919 void FastCodeGenerator::EmitBinaryOp(Token::Value op, | 919 void FullCodeGenerator::EmitBinaryOp(Token::Value op, |
920 Expression::Context context) { | 920 Expression::Context context) { |
921 __ pop(r1); | 921 __ pop(r1); |
922 GenericBinaryOpStub stub(op, NO_OVERWRITE); | 922 GenericBinaryOpStub stub(op, NO_OVERWRITE); |
923 __ CallStub(&stub); | 923 __ CallStub(&stub); |
924 Apply(context, r0); | 924 Apply(context, r0); |
925 } | 925 } |
926 | 926 |
927 | 927 |
928 void FastCodeGenerator::EmitVariableAssignment(Variable* var, | 928 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
929 Expression::Context context) { | 929 Expression::Context context) { |
930 ASSERT(var != NULL); | 930 ASSERT(var != NULL); |
931 ASSERT(var->is_global() || var->slot() != NULL); | 931 ASSERT(var->is_global() || var->slot() != NULL); |
932 if (var->is_global()) { | 932 if (var->is_global()) { |
933 // Assignment to a global variable. Use inline caching for the | 933 // Assignment to a global variable. Use inline caching for the |
934 // assignment. Right-hand-side value is passed in r0, variable name in | 934 // assignment. Right-hand-side value is passed in r0, variable name in |
935 // r2, and the global object on the stack. | 935 // r2, and the global object on the stack. |
936 __ mov(r2, Operand(var->name())); | 936 __ mov(r2, Operand(var->name())); |
937 __ ldr(ip, CodeGenerator::GlobalObject()); | 937 __ ldr(ip, CodeGenerator::GlobalObject()); |
938 __ push(ip); | 938 __ push(ip); |
(...skipping 29 matching lines...) Expand all Loading... |
968 } | 968 } |
969 Apply(context, result_register()); | 969 Apply(context, result_register()); |
970 } else { | 970 } else { |
971 // Variables rewritten as properties are not treated as variables in | 971 // Variables rewritten as properties are not treated as variables in |
972 // assignments. | 972 // assignments. |
973 UNREACHABLE(); | 973 UNREACHABLE(); |
974 } | 974 } |
975 } | 975 } |
976 | 976 |
977 | 977 |
978 void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 978 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
979 // Assignment to a property, using a named store IC. | 979 // Assignment to a property, using a named store IC. |
980 Property* prop = expr->target()->AsProperty(); | 980 Property* prop = expr->target()->AsProperty(); |
981 ASSERT(prop != NULL); | 981 ASSERT(prop != NULL); |
982 ASSERT(prop->key()->AsLiteral() != NULL); | 982 ASSERT(prop->key()->AsLiteral() != NULL); |
983 | 983 |
984 // If the assignment starts a block of assignments to the same object, | 984 // If the assignment starts a block of assignments to the same object, |
985 // change to slow case to avoid the quadratic behavior of repeatedly | 985 // change to slow case to avoid the quadratic behavior of repeatedly |
986 // adding fast properties. | 986 // adding fast properties. |
987 if (expr->starts_initialization_block()) { | 987 if (expr->starts_initialization_block()) { |
988 __ push(result_register()); | 988 __ push(result_register()); |
(...skipping 15 matching lines...) Expand all Loading... |
1004 __ ldr(ip, MemOperand(sp, kPointerSize)); // Receiver is under value. | 1004 __ ldr(ip, MemOperand(sp, kPointerSize)); // Receiver is under value. |
1005 __ push(ip); | 1005 __ push(ip); |
1006 __ CallRuntime(Runtime::kToFastProperties, 1); | 1006 __ CallRuntime(Runtime::kToFastProperties, 1); |
1007 __ pop(r0); | 1007 __ pop(r0); |
1008 } | 1008 } |
1009 | 1009 |
1010 DropAndApply(1, context_, r0); | 1010 DropAndApply(1, context_, r0); |
1011 } | 1011 } |
1012 | 1012 |
1013 | 1013 |
1014 void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 1014 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
1015 // Assignment to a property, using a keyed store IC. | 1015 // Assignment to a property, using a keyed store IC. |
1016 | 1016 |
1017 // If the assignment starts a block of assignments to the same object, | 1017 // If the assignment starts a block of assignments to the same object, |
1018 // change to slow case to avoid the quadratic behavior of repeatedly | 1018 // change to slow case to avoid the quadratic behavior of repeatedly |
1019 // adding fast properties. | 1019 // adding fast properties. |
1020 if (expr->starts_initialization_block()) { | 1020 if (expr->starts_initialization_block()) { |
1021 __ push(result_register()); | 1021 __ push(result_register()); |
1022 // Receiver is now under the key and value. | 1022 // Receiver is now under the key and value. |
1023 __ ldr(ip, MemOperand(sp, 2 * kPointerSize)); | 1023 __ ldr(ip, MemOperand(sp, 2 * kPointerSize)); |
1024 __ push(ip); | 1024 __ push(ip); |
(...skipping 14 matching lines...) Expand all Loading... |
1039 __ push(ip); | 1039 __ push(ip); |
1040 __ CallRuntime(Runtime::kToFastProperties, 1); | 1040 __ CallRuntime(Runtime::kToFastProperties, 1); |
1041 __ pop(r0); | 1041 __ pop(r0); |
1042 } | 1042 } |
1043 | 1043 |
1044 // Receiver and key are still on stack. | 1044 // Receiver and key are still on stack. |
1045 DropAndApply(2, context_, r0); | 1045 DropAndApply(2, context_, r0); |
1046 } | 1046 } |
1047 | 1047 |
1048 | 1048 |
1049 void FastCodeGenerator::VisitProperty(Property* expr) { | 1049 void FullCodeGenerator::VisitProperty(Property* expr) { |
1050 Comment cmnt(masm_, "[ Property"); | 1050 Comment cmnt(masm_, "[ Property"); |
1051 Expression* key = expr->key(); | 1051 Expression* key = expr->key(); |
1052 | 1052 |
1053 // Evaluate receiver. | 1053 // Evaluate receiver. |
1054 VisitForValue(expr->obj(), kStack); | 1054 VisitForValue(expr->obj(), kStack); |
1055 | 1055 |
1056 if (key->IsPropertyName()) { | 1056 if (key->IsPropertyName()) { |
1057 EmitNamedPropertyLoad(expr); | 1057 EmitNamedPropertyLoad(expr); |
1058 // Drop receiver left on the stack by IC. | 1058 // Drop receiver left on the stack by IC. |
1059 DropAndApply(1, context_, r0); | 1059 DropAndApply(1, context_, r0); |
1060 } else { | 1060 } else { |
1061 VisitForValue(expr->key(), kStack); | 1061 VisitForValue(expr->key(), kStack); |
1062 EmitKeyedPropertyLoad(expr); | 1062 EmitKeyedPropertyLoad(expr); |
1063 // Drop key and receiver left on the stack by IC. | 1063 // Drop key and receiver left on the stack by IC. |
1064 DropAndApply(2, context_, r0); | 1064 DropAndApply(2, context_, r0); |
1065 } | 1065 } |
1066 } | 1066 } |
1067 | 1067 |
1068 void FastCodeGenerator::EmitCallWithIC(Call* expr, | 1068 void FullCodeGenerator::EmitCallWithIC(Call* expr, |
1069 Handle<Object> ignored, | 1069 Handle<Object> ignored, |
1070 RelocInfo::Mode mode) { | 1070 RelocInfo::Mode mode) { |
1071 // Code common for calls using the IC. | 1071 // Code common for calls using the IC. |
1072 ZoneList<Expression*>* args = expr->arguments(); | 1072 ZoneList<Expression*>* args = expr->arguments(); |
1073 int arg_count = args->length(); | 1073 int arg_count = args->length(); |
1074 for (int i = 0; i < arg_count; i++) { | 1074 for (int i = 0; i < arg_count; i++) { |
1075 VisitForValue(args->at(i), kStack); | 1075 VisitForValue(args->at(i), kStack); |
1076 } | 1076 } |
1077 // Record source position for debugger. | 1077 // Record source position for debugger. |
1078 SetSourcePosition(expr->position()); | 1078 SetSourcePosition(expr->position()); |
1079 // Call the IC initialization code. | 1079 // Call the IC initialization code. |
1080 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, | 1080 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, |
1081 NOT_IN_LOOP); | 1081 NOT_IN_LOOP); |
1082 __ Call(ic, mode); | 1082 __ Call(ic, mode); |
1083 // Restore context register. | 1083 // Restore context register. |
1084 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1084 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
1085 // Discard the function left on TOS. | 1085 // Discard the function left on TOS. |
1086 DropAndApply(1, context_, r0); | 1086 DropAndApply(1, context_, r0); |
1087 } | 1087 } |
1088 | 1088 |
1089 | 1089 |
1090 void FastCodeGenerator::EmitCallWithStub(Call* expr) { | 1090 void FullCodeGenerator::EmitCallWithStub(Call* expr) { |
1091 // Code common for calls using the call stub. | 1091 // Code common for calls using the call stub. |
1092 ZoneList<Expression*>* args = expr->arguments(); | 1092 ZoneList<Expression*>* args = expr->arguments(); |
1093 int arg_count = args->length(); | 1093 int arg_count = args->length(); |
1094 for (int i = 0; i < arg_count; i++) { | 1094 for (int i = 0; i < arg_count; i++) { |
1095 VisitForValue(args->at(i), kStack); | 1095 VisitForValue(args->at(i), kStack); |
1096 } | 1096 } |
1097 // Record source position for debugger. | 1097 // Record source position for debugger. |
1098 SetSourcePosition(expr->position()); | 1098 SetSourcePosition(expr->position()); |
1099 CallFunctionStub stub(arg_count, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE); | 1099 CallFunctionStub stub(arg_count, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE); |
1100 __ CallStub(&stub); | 1100 __ CallStub(&stub); |
1101 // Restore context register. | 1101 // Restore context register. |
1102 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1102 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
1103 // Discard the function left on TOS. | 1103 // Discard the function left on TOS. |
1104 DropAndApply(1, context_, r0); | 1104 DropAndApply(1, context_, r0); |
1105 } | 1105 } |
1106 | 1106 |
1107 | 1107 |
1108 void FastCodeGenerator::VisitCall(Call* expr) { | 1108 void FullCodeGenerator::VisitCall(Call* expr) { |
1109 Comment cmnt(masm_, "[ Call"); | 1109 Comment cmnt(masm_, "[ Call"); |
1110 Expression* fun = expr->expression(); | 1110 Expression* fun = expr->expression(); |
1111 Variable* var = fun->AsVariableProxy()->AsVariable(); | 1111 Variable* var = fun->AsVariableProxy()->AsVariable(); |
1112 | 1112 |
1113 if (var != NULL && var->is_possibly_eval()) { | 1113 if (var != NULL && var->is_possibly_eval()) { |
1114 // Call to the identifier 'eval'. | 1114 // Call to the identifier 'eval'. |
1115 UNREACHABLE(); | 1115 UNREACHABLE(); |
1116 } else if (var != NULL && !var->is_this() && var->is_global()) { | 1116 } else if (var != NULL && !var->is_this() && var->is_global()) { |
1117 // Call to a global variable. | 1117 // Call to a global variable. |
1118 __ mov(r1, Operand(var->name())); | 1118 __ mov(r1, Operand(var->name())); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1169 // Load global receiver object. | 1169 // Load global receiver object. |
1170 __ ldr(r1, CodeGenerator::GlobalObject()); | 1170 __ ldr(r1, CodeGenerator::GlobalObject()); |
1171 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); | 1171 __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); |
1172 __ push(r1); | 1172 __ push(r1); |
1173 // Emit function call. | 1173 // Emit function call. |
1174 EmitCallWithStub(expr); | 1174 EmitCallWithStub(expr); |
1175 } | 1175 } |
1176 } | 1176 } |
1177 | 1177 |
1178 | 1178 |
1179 void FastCodeGenerator::VisitCallNew(CallNew* expr) { | 1179 void FullCodeGenerator::VisitCallNew(CallNew* expr) { |
1180 Comment cmnt(masm_, "[ CallNew"); | 1180 Comment cmnt(masm_, "[ CallNew"); |
1181 // According to ECMA-262, section 11.2.2, page 44, the function | 1181 // According to ECMA-262, section 11.2.2, page 44, the function |
1182 // expression in new calls must be evaluated before the | 1182 // expression in new calls must be evaluated before the |
1183 // arguments. | 1183 // arguments. |
1184 // Push function on the stack. | 1184 // Push function on the stack. |
1185 VisitForValue(expr->expression(), kStack); | 1185 VisitForValue(expr->expression(), kStack); |
1186 | 1186 |
1187 // Push global object (receiver). | 1187 // Push global object (receiver). |
1188 __ ldr(r0, CodeGenerator::GlobalObject()); | 1188 __ ldr(r0, CodeGenerator::GlobalObject()); |
1189 __ push(r0); | 1189 __ push(r0); |
(...skipping 14 matching lines...) Expand all Loading... |
1204 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); | 1204 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
1205 | 1205 |
1206 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); | 1206 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); |
1207 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); | 1207 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); |
1208 | 1208 |
1209 // Replace function on TOS with result in r0, or pop it. | 1209 // Replace function on TOS with result in r0, or pop it. |
1210 DropAndApply(1, context_, r0); | 1210 DropAndApply(1, context_, r0); |
1211 } | 1211 } |
1212 | 1212 |
1213 | 1213 |
1214 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 1214 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
1215 Comment cmnt(masm_, "[ CallRuntime"); | 1215 Comment cmnt(masm_, "[ CallRuntime"); |
1216 ZoneList<Expression*>* args = expr->arguments(); | 1216 ZoneList<Expression*>* args = expr->arguments(); |
1217 | 1217 |
1218 if (expr->is_jsruntime()) { | 1218 if (expr->is_jsruntime()) { |
1219 // Prepare for calling JS runtime function. | 1219 // Prepare for calling JS runtime function. |
1220 __ mov(r1, Operand(expr->name())); | 1220 __ mov(r1, Operand(expr->name())); |
1221 __ ldr(r0, CodeGenerator::GlobalObject()); | 1221 __ ldr(r0, CodeGenerator::GlobalObject()); |
1222 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset)); | 1222 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset)); |
1223 __ stm(db_w, sp, r1.bit() | r0.bit()); | 1223 __ stm(db_w, sp, r1.bit() | r0.bit()); |
1224 } | 1224 } |
(...skipping 14 matching lines...) Expand all Loading... |
1239 // Discard the function left on TOS. | 1239 // Discard the function left on TOS. |
1240 DropAndApply(1, context_, r0); | 1240 DropAndApply(1, context_, r0); |
1241 } else { | 1241 } else { |
1242 // Call the C runtime function. | 1242 // Call the C runtime function. |
1243 __ CallRuntime(expr->function(), arg_count); | 1243 __ CallRuntime(expr->function(), arg_count); |
1244 Apply(context_, r0); | 1244 Apply(context_, r0); |
1245 } | 1245 } |
1246 } | 1246 } |
1247 | 1247 |
1248 | 1248 |
1249 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 1249 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
1250 switch (expr->op()) { | 1250 switch (expr->op()) { |
1251 case Token::VOID: { | 1251 case Token::VOID: { |
1252 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); | 1252 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); |
1253 VisitForEffect(expr->expression()); | 1253 VisitForEffect(expr->expression()); |
1254 switch (context_) { | 1254 switch (context_) { |
1255 case Expression::kUninitialized: | 1255 case Expression::kUninitialized: |
1256 UNREACHABLE(); | 1256 UNREACHABLE(); |
1257 break; | 1257 break; |
1258 case Expression::kEffect: | 1258 case Expression::kEffect: |
1259 break; | 1259 break; |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1350 Apply(context_, r0); | 1350 Apply(context_, r0); |
1351 break; | 1351 break; |
1352 } | 1352 } |
1353 | 1353 |
1354 default: | 1354 default: |
1355 UNREACHABLE(); | 1355 UNREACHABLE(); |
1356 } | 1356 } |
1357 } | 1357 } |
1358 | 1358 |
1359 | 1359 |
1360 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { | 1360 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
1361 Comment cmnt(masm_, "[ CountOperation"); | 1361 Comment cmnt(masm_, "[ CountOperation"); |
1362 | 1362 |
1363 // Expression can only be a property, a global or a (parameter or local) | 1363 // Expression can only be a property, a global or a (parameter or local) |
1364 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. | 1364 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. |
1365 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1365 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
1366 LhsKind assign_type = VARIABLE; | 1366 LhsKind assign_type = VARIABLE; |
1367 Property* prop = expr->expression()->AsProperty(); | 1367 Property* prop = expr->expression()->AsProperty(); |
1368 // In case of a property we use the uninitialized expression context | 1368 // In case of a property we use the uninitialized expression context |
1369 // of the key to detect a named property. | 1369 // of the key to detect a named property. |
1370 if (prop != NULL) { | 1370 if (prop != NULL) { |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1476 } | 1476 } |
1477 } else { | 1477 } else { |
1478 DropAndApply(2, context_, r0); | 1478 DropAndApply(2, context_, r0); |
1479 } | 1479 } |
1480 break; | 1480 break; |
1481 } | 1481 } |
1482 } | 1482 } |
1483 } | 1483 } |
1484 | 1484 |
1485 | 1485 |
1486 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 1486 void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
1487 Comment cmnt(masm_, "[ BinaryOperation"); | 1487 Comment cmnt(masm_, "[ BinaryOperation"); |
1488 switch (expr->op()) { | 1488 switch (expr->op()) { |
1489 case Token::COMMA: | 1489 case Token::COMMA: |
1490 VisitForEffect(expr->left()); | 1490 VisitForEffect(expr->left()); |
1491 Visit(expr->right()); | 1491 Visit(expr->right()); |
1492 break; | 1492 break; |
1493 | 1493 |
1494 case Token::OR: | 1494 case Token::OR: |
1495 case Token::AND: | 1495 case Token::AND: |
1496 EmitLogicalOperation(expr); | 1496 EmitLogicalOperation(expr); |
(...skipping 14 matching lines...) Expand all Loading... |
1511 VisitForValue(expr->right(), kAccumulator); | 1511 VisitForValue(expr->right(), kAccumulator); |
1512 EmitBinaryOp(expr->op(), context_); | 1512 EmitBinaryOp(expr->op(), context_); |
1513 break; | 1513 break; |
1514 | 1514 |
1515 default: | 1515 default: |
1516 UNREACHABLE(); | 1516 UNREACHABLE(); |
1517 } | 1517 } |
1518 } | 1518 } |
1519 | 1519 |
1520 | 1520 |
1521 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 1521 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
1522 Comment cmnt(masm_, "[ CompareOperation"); | 1522 Comment cmnt(masm_, "[ CompareOperation"); |
1523 | 1523 |
1524 // Always perform the comparison for its control flow. Pack the result | 1524 // Always perform the comparison for its control flow. Pack the result |
1525 // into the expression's context after the comparison is performed. | 1525 // into the expression's context after the comparison is performed. |
1526 Label materialize_true, materialize_false, done; | 1526 Label materialize_true, materialize_false, done; |
1527 // Initially assume we are in a test context. | 1527 // Initially assume we are in a test context. |
1528 Label* if_true = true_label_; | 1528 Label* if_true = true_label_; |
1529 Label* if_false = false_label_; | 1529 Label* if_false = false_label_; |
1530 switch (context_) { | 1530 switch (context_) { |
1531 case Expression::kUninitialized: | 1531 case Expression::kUninitialized: |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1626 __ jmp(if_false); | 1626 __ jmp(if_false); |
1627 } | 1627 } |
1628 } | 1628 } |
1629 | 1629 |
1630 // Convert the result of the comparison into one expected for this | 1630 // Convert the result of the comparison into one expected for this |
1631 // expression's context. | 1631 // expression's context. |
1632 Apply(context_, if_true, if_false); | 1632 Apply(context_, if_true, if_false); |
1633 } | 1633 } |
1634 | 1634 |
1635 | 1635 |
1636 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 1636 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
1637 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1637 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
1638 Apply(context_, r0); | 1638 Apply(context_, r0); |
1639 } | 1639 } |
1640 | 1640 |
1641 | 1641 |
1642 Register FastCodeGenerator::result_register() { return r0; } | 1642 Register FullCodeGenerator::result_register() { return r0; } |
1643 | 1643 |
1644 | 1644 |
1645 Register FastCodeGenerator::context_register() { return cp; } | 1645 Register FullCodeGenerator::context_register() { return cp; } |
1646 | 1646 |
1647 | 1647 |
1648 void FastCodeGenerator::StoreToFrameField(int frame_offset, Register value) { | 1648 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { |
1649 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); | 1649 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); |
1650 __ str(value, MemOperand(fp, frame_offset)); | 1650 __ str(value, MemOperand(fp, frame_offset)); |
1651 } | 1651 } |
1652 | 1652 |
1653 | 1653 |
1654 void FastCodeGenerator::LoadContextField(Register dst, int context_index) { | 1654 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { |
1655 __ ldr(dst, CodeGenerator::ContextOperand(cp, context_index)); | 1655 __ ldr(dst, CodeGenerator::ContextOperand(cp, context_index)); |
1656 } | 1656 } |
1657 | 1657 |
1658 | 1658 |
1659 // ---------------------------------------------------------------------------- | 1659 // ---------------------------------------------------------------------------- |
1660 // Non-local control flow support. | 1660 // Non-local control flow support. |
1661 | 1661 |
1662 void FastCodeGenerator::EnterFinallyBlock() { | 1662 void FullCodeGenerator::EnterFinallyBlock() { |
1663 ASSERT(!result_register().is(r1)); | 1663 ASSERT(!result_register().is(r1)); |
1664 // Store result register while executing finally block. | 1664 // Store result register while executing finally block. |
1665 __ push(result_register()); | 1665 __ push(result_register()); |
1666 // Cook return address in link register to stack (smi encoded Code* delta) | 1666 // Cook return address in link register to stack (smi encoded Code* delta) |
1667 __ sub(r1, lr, Operand(masm_->CodeObject())); | 1667 __ sub(r1, lr, Operand(masm_->CodeObject())); |
1668 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); | 1668 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); |
1669 ASSERT_EQ(0, kSmiTag); | 1669 ASSERT_EQ(0, kSmiTag); |
1670 __ add(r1, r1, Operand(r1)); // Convert to smi. | 1670 __ add(r1, r1, Operand(r1)); // Convert to smi. |
1671 __ push(r1); | 1671 __ push(r1); |
1672 } | 1672 } |
1673 | 1673 |
1674 | 1674 |
1675 void FastCodeGenerator::ExitFinallyBlock() { | 1675 void FullCodeGenerator::ExitFinallyBlock() { |
1676 ASSERT(!result_register().is(r1)); | 1676 ASSERT(!result_register().is(r1)); |
1677 // Restore result register from stack. | 1677 // Restore result register from stack. |
1678 __ pop(r1); | 1678 __ pop(r1); |
1679 // Uncook return address and return. | 1679 // Uncook return address and return. |
1680 __ pop(result_register()); | 1680 __ pop(result_register()); |
1681 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); | 1681 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); |
1682 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 1682 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
1683 __ add(pc, r1, Operand(masm_->CodeObject())); | 1683 __ add(pc, r1, Operand(masm_->CodeObject())); |
1684 } | 1684 } |
1685 | 1685 |
1686 | 1686 |
1687 #undef __ | 1687 #undef __ |
1688 | 1688 |
1689 } } // namespace v8::internal | 1689 } } // namespace v8::internal |
OLD | NEW |