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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 // formal parameter count expected by the function. | 44 // formal parameter count expected by the function. |
45 // | 45 // |
46 // The live registers are: | 46 // The live registers are: |
47 // o edi: the JS function object being called (ie, ourselves) | 47 // o edi: the JS function object being called (ie, ourselves) |
48 // o esi: our context | 48 // o esi: our context |
49 // o ebp: our caller's frame pointer | 49 // o ebp: our caller's frame pointer |
50 // o esp: stack pointer (pointing to return address) | 50 // o esp: stack pointer (pointing to return address) |
51 // | 51 // |
52 // The function builds a JS frame. Please see JavaScriptFrameConstants in | 52 // The function builds a JS frame. Please see JavaScriptFrameConstants in |
53 // frames-ia32.h for its layout. | 53 // frames-ia32.h for its layout. |
54 void FastCodeGenerator::Generate(FunctionLiteral* fun) { | 54 void FullCodeGenerator::Generate(FunctionLiteral* fun) { |
55 function_ = fun; | 55 function_ = fun; |
56 SetFunctionPosition(fun); | 56 SetFunctionPosition(fun); |
57 | 57 |
58 __ push(ebp); // Caller's frame pointer. | 58 __ push(ebp); // Caller's frame pointer. |
59 __ mov(ebp, esp); | 59 __ mov(ebp, esp); |
60 __ push(esi); // Callee's context. | 60 __ push(esi); // Callee's context. |
61 __ push(edi); // Callee's JS Function. | 61 __ push(edi); // Callee's JS Function. |
62 | 62 |
63 { Comment cmnt(masm_, "[ Allocate locals"); | 63 { Comment cmnt(masm_, "[ Allocate locals"); |
64 int locals_count = fun->scope()->num_stack_slots(); | 64 int locals_count = fun->scope()->num_stack_slots(); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 } | 153 } |
154 | 154 |
155 { Comment cmnt(masm_, "[ return <undefined>;"); | 155 { Comment cmnt(masm_, "[ return <undefined>;"); |
156 // Emit a 'return undefined' in case control fell off the end of the body. | 156 // Emit a 'return undefined' in case control fell off the end of the body. |
157 __ mov(eax, Factory::undefined_value()); | 157 __ mov(eax, Factory::undefined_value()); |
158 EmitReturnSequence(function_->end_position()); | 158 EmitReturnSequence(function_->end_position()); |
159 } | 159 } |
160 } | 160 } |
161 | 161 |
162 | 162 |
163 void FastCodeGenerator::EmitReturnSequence(int position) { | 163 void FullCodeGenerator::EmitReturnSequence(int position) { |
164 Comment cmnt(masm_, "[ Return sequence"); | 164 Comment cmnt(masm_, "[ Return sequence"); |
165 if (return_label_.is_bound()) { | 165 if (return_label_.is_bound()) { |
166 __ jmp(&return_label_); | 166 __ jmp(&return_label_); |
167 } else { | 167 } else { |
168 // Common return label | 168 // Common return label |
169 __ bind(&return_label_); | 169 __ bind(&return_label_); |
170 if (FLAG_trace) { | 170 if (FLAG_trace) { |
171 __ push(eax); | 171 __ push(eax); |
172 __ CallRuntime(Runtime::kTraceExit, 1); | 172 __ CallRuntime(Runtime::kTraceExit, 1); |
173 } | 173 } |
(...skipping 12 matching lines...) Expand all Loading... |
186 #ifdef ENABLE_DEBUGGER_SUPPORT | 186 #ifdef ENABLE_DEBUGGER_SUPPORT |
187 // Check that the size of the code used for returning matches what is | 187 // Check that the size of the code used for returning matches what is |
188 // expected by the debugger. | 188 // expected by the debugger. |
189 ASSERT_EQ(Assembler::kJSReturnSequenceLength, | 189 ASSERT_EQ(Assembler::kJSReturnSequenceLength, |
190 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); | 190 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); |
191 #endif | 191 #endif |
192 } | 192 } |
193 } | 193 } |
194 | 194 |
195 | 195 |
196 void FastCodeGenerator::Apply(Expression::Context context, Register reg) { | 196 void FullCodeGenerator::Apply(Expression::Context context, Register reg) { |
197 switch (context) { | 197 switch (context) { |
198 case Expression::kUninitialized: | 198 case Expression::kUninitialized: |
199 UNREACHABLE(); | 199 UNREACHABLE(); |
200 | 200 |
201 case Expression::kEffect: | 201 case Expression::kEffect: |
202 // Nothing to do. | 202 // Nothing to do. |
203 break; | 203 break; |
204 | 204 |
205 case Expression::kValue: | 205 case Expression::kValue: |
206 // Move value into place. | 206 // Move value into place. |
(...skipping 22 matching lines...) Expand all Loading... |
229 case kStack: | 229 case kStack: |
230 __ push(result_register()); | 230 __ push(result_register()); |
231 break; | 231 break; |
232 } | 232 } |
233 DoTest(context); | 233 DoTest(context); |
234 break; | 234 break; |
235 } | 235 } |
236 } | 236 } |
237 | 237 |
238 | 238 |
239 void FastCodeGenerator::Apply(Expression::Context context, Slot* slot) { | 239 void FullCodeGenerator::Apply(Expression::Context context, Slot* slot) { |
240 switch (context) { | 240 switch (context) { |
241 case Expression::kUninitialized: | 241 case Expression::kUninitialized: |
242 UNREACHABLE(); | 242 UNREACHABLE(); |
243 case Expression::kEffect: | 243 case Expression::kEffect: |
244 // Nothing to do. | 244 // Nothing to do. |
245 break; | 245 break; |
246 case Expression::kValue: { | 246 case Expression::kValue: { |
247 MemOperand slot_operand = EmitSlotSearch(slot, result_register()); | 247 MemOperand slot_operand = EmitSlotSearch(slot, result_register()); |
248 switch (location_) { | 248 switch (location_) { |
249 case kAccumulator: | 249 case kAccumulator: |
(...skipping 22 matching lines...) Expand all Loading... |
272 case kStack: | 272 case kStack: |
273 __ push(result_register()); | 273 __ push(result_register()); |
274 break; | 274 break; |
275 } | 275 } |
276 DoTest(context); | 276 DoTest(context); |
277 break; | 277 break; |
278 } | 278 } |
279 } | 279 } |
280 | 280 |
281 | 281 |
282 void FastCodeGenerator::Apply(Expression::Context context, Literal* lit) { | 282 void FullCodeGenerator::Apply(Expression::Context context, Literal* lit) { |
283 switch (context) { | 283 switch (context) { |
284 case Expression::kUninitialized: | 284 case Expression::kUninitialized: |
285 UNREACHABLE(); | 285 UNREACHABLE(); |
286 case Expression::kEffect: | 286 case Expression::kEffect: |
287 // Nothing to do. | 287 // Nothing to do. |
288 break; | 288 break; |
289 case Expression::kValue: | 289 case Expression::kValue: |
290 switch (location_) { | 290 switch (location_) { |
291 case kAccumulator: | 291 case kAccumulator: |
292 __ mov(result_register(), lit->handle()); | 292 __ mov(result_register(), lit->handle()); |
(...skipping 20 matching lines...) Expand all Loading... |
313 case kStack: | 313 case kStack: |
314 __ push(result_register()); | 314 __ push(result_register()); |
315 break; | 315 break; |
316 } | 316 } |
317 DoTest(context); | 317 DoTest(context); |
318 break; | 318 break; |
319 } | 319 } |
320 } | 320 } |
321 | 321 |
322 | 322 |
323 void FastCodeGenerator::ApplyTOS(Expression::Context context) { | 323 void FullCodeGenerator::ApplyTOS(Expression::Context context) { |
324 switch (context) { | 324 switch (context) { |
325 case Expression::kUninitialized: | 325 case Expression::kUninitialized: |
326 UNREACHABLE(); | 326 UNREACHABLE(); |
327 | 327 |
328 case Expression::kEffect: | 328 case Expression::kEffect: |
329 __ Drop(1); | 329 __ Drop(1); |
330 break; | 330 break; |
331 | 331 |
332 case Expression::kValue: | 332 case Expression::kValue: |
333 switch (location_) { | 333 switch (location_) { |
(...skipping 20 matching lines...) Expand all Loading... |
354 case kStack: | 354 case kStack: |
355 __ mov(result_register(), Operand(esp, 0)); | 355 __ mov(result_register(), Operand(esp, 0)); |
356 break; | 356 break; |
357 } | 357 } |
358 DoTest(context); | 358 DoTest(context); |
359 break; | 359 break; |
360 } | 360 } |
361 } | 361 } |
362 | 362 |
363 | 363 |
364 void FastCodeGenerator::DropAndApply(int count, | 364 void FullCodeGenerator::DropAndApply(int count, |
365 Expression::Context context, | 365 Expression::Context context, |
366 Register reg) { | 366 Register reg) { |
367 ASSERT(count > 0); | 367 ASSERT(count > 0); |
368 ASSERT(!reg.is(esp)); | 368 ASSERT(!reg.is(esp)); |
369 switch (context) { | 369 switch (context) { |
370 case Expression::kUninitialized: | 370 case Expression::kUninitialized: |
371 UNREACHABLE(); | 371 UNREACHABLE(); |
372 | 372 |
373 case Expression::kEffect: | 373 case Expression::kEffect: |
374 __ Drop(count); | 374 __ Drop(count); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 __ mov(result_register(), reg); | 406 __ mov(result_register(), reg); |
407 __ mov(Operand(esp, 0), result_register()); | 407 __ mov(Operand(esp, 0), result_register()); |
408 break; | 408 break; |
409 } | 409 } |
410 DoTest(context); | 410 DoTest(context); |
411 break; | 411 break; |
412 } | 412 } |
413 } | 413 } |
414 | 414 |
415 | 415 |
416 void FastCodeGenerator::Apply(Expression::Context context, | 416 void FullCodeGenerator::Apply(Expression::Context context, |
417 Label* materialize_true, | 417 Label* materialize_true, |
418 Label* materialize_false) { | 418 Label* materialize_false) { |
419 switch (context) { | 419 switch (context) { |
420 case Expression::kUninitialized: | 420 case Expression::kUninitialized: |
421 | 421 |
422 case Expression::kEffect: | 422 case Expression::kEffect: |
423 ASSERT_EQ(materialize_true, materialize_false); | 423 ASSERT_EQ(materialize_true, materialize_false); |
424 __ bind(materialize_true); | 424 __ bind(materialize_true); |
425 break; | 425 break; |
426 | 426 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
471 case kStack: | 471 case kStack: |
472 __ push(Immediate(Factory::false_value())); | 472 __ push(Immediate(Factory::false_value())); |
473 break; | 473 break; |
474 } | 474 } |
475 __ jmp(false_label_); | 475 __ jmp(false_label_); |
476 break; | 476 break; |
477 } | 477 } |
478 } | 478 } |
479 | 479 |
480 | 480 |
481 void FastCodeGenerator::DoTest(Expression::Context context) { | 481 void FullCodeGenerator::DoTest(Expression::Context context) { |
482 // The value to test is in the accumulator. If the value might be needed | 482 // The value to test is in the accumulator. If the value might be needed |
483 // on the stack (value/test and test/value contexts with a stack location | 483 // on the stack (value/test and test/value contexts with a stack location |
484 // desired), then the value is already duplicated on the stack. | 484 // desired), then the value is already duplicated on the stack. |
485 ASSERT_NE(NULL, true_label_); | 485 ASSERT_NE(NULL, true_label_); |
486 ASSERT_NE(NULL, false_label_); | 486 ASSERT_NE(NULL, false_label_); |
487 | 487 |
488 // In value/test and test/value expression contexts with stack as the | 488 // In value/test and test/value expression contexts with stack as the |
489 // desired location, there is already an extra value on the stack. Use a | 489 // desired location, there is already an extra value on the stack. Use a |
490 // label to discard it if unneeded. | 490 // label to discard it if unneeded. |
491 Label discard; | 491 Label discard; |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
605 break; | 605 break; |
606 } | 606 } |
607 __ bind(&discard); | 607 __ bind(&discard); |
608 __ Drop(1); | 608 __ Drop(1); |
609 __ jmp(true_label_); | 609 __ jmp(true_label_); |
610 break; | 610 break; |
611 } | 611 } |
612 } | 612 } |
613 | 613 |
614 | 614 |
615 MemOperand FastCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { | 615 MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) { |
616 switch (slot->type()) { | 616 switch (slot->type()) { |
617 case Slot::PARAMETER: | 617 case Slot::PARAMETER: |
618 case Slot::LOCAL: | 618 case Slot::LOCAL: |
619 return Operand(ebp, SlotOffset(slot)); | 619 return Operand(ebp, SlotOffset(slot)); |
620 case Slot::CONTEXT: { | 620 case Slot::CONTEXT: { |
621 int context_chain_length = | 621 int context_chain_length = |
622 function_->scope()->ContextChainLength(slot->var()->scope()); | 622 function_->scope()->ContextChainLength(slot->var()->scope()); |
623 __ LoadContext(scratch, context_chain_length); | 623 __ LoadContext(scratch, context_chain_length); |
624 return CodeGenerator::ContextOperand(scratch, slot->index()); | 624 return CodeGenerator::ContextOperand(scratch, slot->index()); |
625 } | 625 } |
626 case Slot::LOOKUP: | 626 case Slot::LOOKUP: |
627 UNREACHABLE(); | 627 UNREACHABLE(); |
628 } | 628 } |
629 UNREACHABLE(); | 629 UNREACHABLE(); |
630 return Operand(eax, 0); | 630 return Operand(eax, 0); |
631 } | 631 } |
632 | 632 |
633 | 633 |
634 void FastCodeGenerator::Move(Register destination, Slot* source) { | 634 void FullCodeGenerator::Move(Register destination, Slot* source) { |
635 MemOperand location = EmitSlotSearch(source, destination); | 635 MemOperand location = EmitSlotSearch(source, destination); |
636 __ mov(destination, location); | 636 __ mov(destination, location); |
637 } | 637 } |
638 | 638 |
639 | 639 |
640 void FastCodeGenerator::Move(Slot* dst, | 640 void FullCodeGenerator::Move(Slot* dst, |
641 Register src, | 641 Register src, |
642 Register scratch1, | 642 Register scratch1, |
643 Register scratch2) { | 643 Register scratch2) { |
644 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. | 644 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. |
645 ASSERT(!scratch1.is(src) && !scratch2.is(src)); | 645 ASSERT(!scratch1.is(src) && !scratch2.is(src)); |
646 MemOperand location = EmitSlotSearch(dst, scratch1); | 646 MemOperand location = EmitSlotSearch(dst, scratch1); |
647 __ mov(location, src); | 647 __ mov(location, src); |
648 // Emit the write barrier code if the location is in the heap. | 648 // Emit the write barrier code if the location is in the heap. |
649 if (dst->type() == Slot::CONTEXT) { | 649 if (dst->type() == Slot::CONTEXT) { |
650 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; | 650 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; |
651 __ RecordWrite(scratch1, offset, src, scratch2); | 651 __ RecordWrite(scratch1, offset, src, scratch2); |
652 } | 652 } |
653 } | 653 } |
654 | 654 |
655 | 655 |
656 void FastCodeGenerator::VisitDeclaration(Declaration* decl) { | 656 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { |
657 Comment cmnt(masm_, "[ Declaration"); | 657 Comment cmnt(masm_, "[ Declaration"); |
658 Variable* var = decl->proxy()->var(); | 658 Variable* var = decl->proxy()->var(); |
659 ASSERT(var != NULL); // Must have been resolved. | 659 ASSERT(var != NULL); // Must have been resolved. |
660 Slot* slot = var->slot(); | 660 Slot* slot = var->slot(); |
661 Property* prop = var->AsProperty(); | 661 Property* prop = var->AsProperty(); |
662 | 662 |
663 if (slot != NULL) { | 663 if (slot != NULL) { |
664 switch (slot->type()) { | 664 switch (slot->type()) { |
665 case Slot::PARAMETER: | 665 case Slot::PARAMETER: |
666 case Slot::LOCAL: | 666 case Slot::LOCAL: |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
744 __ nop(); | 744 __ nop(); |
745 | 745 |
746 // Value in eax is ignored (declarations are statements). Receiver | 746 // Value in eax is ignored (declarations are statements). Receiver |
747 // and key on stack are discarded. | 747 // and key on stack are discarded. |
748 __ Drop(2); | 748 __ Drop(2); |
749 } | 749 } |
750 } | 750 } |
751 } | 751 } |
752 | 752 |
753 | 753 |
754 void FastCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { | 754 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { |
755 // Call the runtime to declare the globals. | 755 // Call the runtime to declare the globals. |
756 __ push(esi); // The context is the first argument. | 756 __ push(esi); // The context is the first argument. |
757 __ push(Immediate(pairs)); | 757 __ push(Immediate(pairs)); |
758 __ push(Immediate(Smi::FromInt(is_eval_ ? 1 : 0))); | 758 __ push(Immediate(Smi::FromInt(is_eval_ ? 1 : 0))); |
759 __ CallRuntime(Runtime::kDeclareGlobals, 3); | 759 __ CallRuntime(Runtime::kDeclareGlobals, 3); |
760 // Return value is ignored. | 760 // Return value is ignored. |
761 } | 761 } |
762 | 762 |
763 | 763 |
764 void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { | 764 void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { |
765 Comment cmnt(masm_, "[ FunctionLiteral"); | 765 Comment cmnt(masm_, "[ FunctionLiteral"); |
766 | 766 |
767 // Build the function boilerplate and instantiate it. | 767 // Build the function boilerplate and instantiate it. |
768 Handle<JSFunction> boilerplate = | 768 Handle<JSFunction> boilerplate = |
769 Compiler::BuildBoilerplate(expr, script_, this); | 769 Compiler::BuildBoilerplate(expr, script_, this); |
770 if (HasStackOverflow()) return; | 770 if (HasStackOverflow()) return; |
771 | 771 |
772 ASSERT(boilerplate->IsBoilerplate()); | 772 ASSERT(boilerplate->IsBoilerplate()); |
773 | 773 |
774 // Create a new closure. | 774 // Create a new closure. |
775 __ push(esi); | 775 __ push(esi); |
776 __ push(Immediate(boilerplate)); | 776 __ push(Immediate(boilerplate)); |
777 __ CallRuntime(Runtime::kNewClosure, 2); | 777 __ CallRuntime(Runtime::kNewClosure, 2); |
778 Apply(context_, eax); | 778 Apply(context_, eax); |
779 } | 779 } |
780 | 780 |
781 | 781 |
782 void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 782 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
783 Comment cmnt(masm_, "[ VariableProxy"); | 783 Comment cmnt(masm_, "[ VariableProxy"); |
784 EmitVariableLoad(expr->var(), context_); | 784 EmitVariableLoad(expr->var(), context_); |
785 } | 785 } |
786 | 786 |
787 | 787 |
788 void FastCodeGenerator::EmitVariableLoad(Variable* var, | 788 void FullCodeGenerator::EmitVariableLoad(Variable* var, |
789 Expression::Context context) { | 789 Expression::Context context) { |
790 Expression* rewrite = var->rewrite(); | 790 Expression* rewrite = var->rewrite(); |
791 if (rewrite == NULL) { | 791 if (rewrite == NULL) { |
792 ASSERT(var->is_global()); | 792 ASSERT(var->is_global()); |
793 Comment cmnt(masm_, "Global variable"); | 793 Comment cmnt(masm_, "Global variable"); |
794 // Use inline caching. Variable name is passed in ecx and the global | 794 // Use inline caching. Variable name is passed in ecx and the global |
795 // object on the stack. | 795 // object on the stack. |
796 __ push(CodeGenerator::GlobalObject()); | 796 __ push(CodeGenerator::GlobalObject()); |
797 __ mov(ecx, var->name()); | 797 __ mov(ecx, var->name()); |
798 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 798 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
855 __ call(ic, RelocInfo::CODE_TARGET); | 855 __ call(ic, RelocInfo::CODE_TARGET); |
856 // Notice: We must not have a "test eax, ..." instruction after the | 856 // Notice: We must not have a "test eax, ..." instruction after the |
857 // call. It is treated specially by the LoadIC code. | 857 // call. It is treated specially by the LoadIC code. |
858 __ nop(); | 858 __ nop(); |
859 // Drop key and object left on the stack by IC. | 859 // Drop key and object left on the stack by IC. |
860 DropAndApply(2, context, eax); | 860 DropAndApply(2, context, eax); |
861 } | 861 } |
862 } | 862 } |
863 | 863 |
864 | 864 |
865 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 865 void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
866 Comment cmnt(masm_, "[ RegExpLiteral"); | 866 Comment cmnt(masm_, "[ RegExpLiteral"); |
867 Label done; | 867 Label done; |
868 // Registers will be used as follows: | 868 // Registers will be used as follows: |
869 // edi = JS function. | 869 // edi = JS function. |
870 // ebx = literals array. | 870 // ebx = literals array. |
871 // eax = regexp literal. | 871 // eax = regexp literal. |
872 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 872 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
873 __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset)); | 873 __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset)); |
874 int literal_offset = | 874 int literal_offset = |
875 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; | 875 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
876 __ mov(eax, FieldOperand(ebx, literal_offset)); | 876 __ mov(eax, FieldOperand(ebx, literal_offset)); |
877 __ cmp(eax, Factory::undefined_value()); | 877 __ cmp(eax, Factory::undefined_value()); |
878 __ j(not_equal, &done); | 878 __ j(not_equal, &done); |
879 // Create regexp literal using runtime function | 879 // Create regexp literal using runtime function |
880 // Result will be in eax. | 880 // Result will be in eax. |
881 __ push(ebx); | 881 __ push(ebx); |
882 __ push(Immediate(Smi::FromInt(expr->literal_index()))); | 882 __ push(Immediate(Smi::FromInt(expr->literal_index()))); |
883 __ push(Immediate(expr->pattern())); | 883 __ push(Immediate(expr->pattern())); |
884 __ push(Immediate(expr->flags())); | 884 __ push(Immediate(expr->flags())); |
885 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); | 885 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
886 // Label done: | 886 // Label done: |
887 __ bind(&done); | 887 __ bind(&done); |
888 Apply(context_, eax); | 888 Apply(context_, eax); |
889 } | 889 } |
890 | 890 |
891 | 891 |
892 void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 892 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
893 Comment cmnt(masm_, "[ ObjectLiteral"); | 893 Comment cmnt(masm_, "[ ObjectLiteral"); |
894 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 894 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
895 __ push(FieldOperand(edi, JSFunction::kLiteralsOffset)); | 895 __ push(FieldOperand(edi, JSFunction::kLiteralsOffset)); |
896 __ push(Immediate(Smi::FromInt(expr->literal_index()))); | 896 __ push(Immediate(Smi::FromInt(expr->literal_index()))); |
897 __ push(Immediate(expr->constant_properties())); | 897 __ push(Immediate(expr->constant_properties())); |
898 if (expr->depth() > 1) { | 898 if (expr->depth() > 1) { |
899 __ CallRuntime(Runtime::kCreateObjectLiteral, 3); | 899 __ CallRuntime(Runtime::kCreateObjectLiteral, 3); |
900 } else { | 900 } else { |
901 __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 3); | 901 __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 3); |
902 } | 902 } |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
951 } | 951 } |
952 | 952 |
953 if (result_saved) { | 953 if (result_saved) { |
954 ApplyTOS(context_); | 954 ApplyTOS(context_); |
955 } else { | 955 } else { |
956 Apply(context_, eax); | 956 Apply(context_, eax); |
957 } | 957 } |
958 } | 958 } |
959 | 959 |
960 | 960 |
961 void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 961 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
962 Comment cmnt(masm_, "[ ArrayLiteral"); | 962 Comment cmnt(masm_, "[ ArrayLiteral"); |
963 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 963 __ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
964 __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset)); | 964 __ push(FieldOperand(ebx, JSFunction::kLiteralsOffset)); |
965 __ push(Immediate(Smi::FromInt(expr->literal_index()))); | 965 __ push(Immediate(Smi::FromInt(expr->literal_index()))); |
966 __ push(Immediate(expr->constant_elements())); | 966 __ push(Immediate(expr->constant_elements())); |
967 if (expr->depth() > 1) { | 967 if (expr->depth() > 1) { |
968 __ CallRuntime(Runtime::kCreateArrayLiteral, 3); | 968 __ CallRuntime(Runtime::kCreateArrayLiteral, 3); |
969 } else { | 969 } else { |
970 __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); | 970 __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); |
971 } | 971 } |
(...skipping 29 matching lines...) Expand all Loading... |
1001 } | 1001 } |
1002 | 1002 |
1003 if (result_saved) { | 1003 if (result_saved) { |
1004 ApplyTOS(context_); | 1004 ApplyTOS(context_); |
1005 } else { | 1005 } else { |
1006 Apply(context_, eax); | 1006 Apply(context_, eax); |
1007 } | 1007 } |
1008 } | 1008 } |
1009 | 1009 |
1010 | 1010 |
1011 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 1011 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
1012 SetSourcePosition(prop->position()); | 1012 SetSourcePosition(prop->position()); |
1013 Literal* key = prop->key()->AsLiteral(); | 1013 Literal* key = prop->key()->AsLiteral(); |
1014 __ mov(ecx, Immediate(key->handle())); | 1014 __ mov(ecx, Immediate(key->handle())); |
1015 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1015 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
1016 __ call(ic, RelocInfo::CODE_TARGET); | 1016 __ call(ic, RelocInfo::CODE_TARGET); |
1017 __ nop(); | 1017 __ nop(); |
1018 } | 1018 } |
1019 | 1019 |
1020 | 1020 |
1021 void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 1021 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
1022 SetSourcePosition(prop->position()); | 1022 SetSourcePosition(prop->position()); |
1023 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1023 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
1024 __ call(ic, RelocInfo::CODE_TARGET); | 1024 __ call(ic, RelocInfo::CODE_TARGET); |
1025 __ nop(); | 1025 __ nop(); |
1026 } | 1026 } |
1027 | 1027 |
1028 | 1028 |
1029 void FastCodeGenerator::EmitBinaryOp(Token::Value op, | 1029 void FullCodeGenerator::EmitBinaryOp(Token::Value op, |
1030 Expression::Context context) { | 1030 Expression::Context context) { |
1031 __ push(result_register()); | 1031 __ push(result_register()); |
1032 GenericBinaryOpStub stub(op, | 1032 GenericBinaryOpStub stub(op, |
1033 NO_OVERWRITE, | 1033 NO_OVERWRITE, |
1034 NO_GENERIC_BINARY_FLAGS); | 1034 NO_GENERIC_BINARY_FLAGS); |
1035 __ CallStub(&stub); | 1035 __ CallStub(&stub); |
1036 Apply(context, eax); | 1036 Apply(context, eax); |
1037 } | 1037 } |
1038 | 1038 |
1039 | 1039 |
1040 void FastCodeGenerator::EmitVariableAssignment(Variable* var, | 1040 void FullCodeGenerator::EmitVariableAssignment(Variable* var, |
1041 Expression::Context context) { | 1041 Expression::Context context) { |
1042 ASSERT(var != NULL); | 1042 ASSERT(var != NULL); |
1043 ASSERT(var->is_global() || var->slot() != NULL); | 1043 ASSERT(var->is_global() || var->slot() != NULL); |
1044 if (var->is_global()) { | 1044 if (var->is_global()) { |
1045 // Assignment to a global variable. Use inline caching for the | 1045 // Assignment to a global variable. Use inline caching for the |
1046 // assignment. Right-hand-side value is passed in eax, variable name in | 1046 // assignment. Right-hand-side value is passed in eax, variable name in |
1047 // ecx, and the global object on the stack. | 1047 // ecx, and the global object on the stack. |
1048 __ mov(ecx, var->name()); | 1048 __ mov(ecx, var->name()); |
1049 __ push(CodeGenerator::GlobalObject()); | 1049 __ push(CodeGenerator::GlobalObject()); |
1050 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1050 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
(...skipping 28 matching lines...) Expand all Loading... |
1079 Apply(context, result_register()); | 1079 Apply(context, result_register()); |
1080 | 1080 |
1081 } else { | 1081 } else { |
1082 // Variables rewritten as properties are not treated as variables in | 1082 // Variables rewritten as properties are not treated as variables in |
1083 // assignments. | 1083 // assignments. |
1084 UNREACHABLE(); | 1084 UNREACHABLE(); |
1085 } | 1085 } |
1086 } | 1086 } |
1087 | 1087 |
1088 | 1088 |
1089 void FastCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 1089 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
1090 // Assignment to a property, using a named store IC. | 1090 // Assignment to a property, using a named store IC. |
1091 Property* prop = expr->target()->AsProperty(); | 1091 Property* prop = expr->target()->AsProperty(); |
1092 ASSERT(prop != NULL); | 1092 ASSERT(prop != NULL); |
1093 ASSERT(prop->key()->AsLiteral() != NULL); | 1093 ASSERT(prop->key()->AsLiteral() != NULL); |
1094 | 1094 |
1095 // If the assignment starts a block of assignments to the same object, | 1095 // If the assignment starts a block of assignments to the same object, |
1096 // change to slow case to avoid the quadratic behavior of repeatedly | 1096 // change to slow case to avoid the quadratic behavior of repeatedly |
1097 // adding fast properties. | 1097 // adding fast properties. |
1098 if (expr->starts_initialization_block()) { | 1098 if (expr->starts_initialization_block()) { |
1099 __ push(result_register()); | 1099 __ push(result_register()); |
(...skipping 14 matching lines...) Expand all Loading... |
1114 __ push(eax); // Result of assignment, saved even if not needed. | 1114 __ push(eax); // Result of assignment, saved even if not needed. |
1115 __ push(Operand(esp, kPointerSize)); // Receiver is under value. | 1115 __ push(Operand(esp, kPointerSize)); // Receiver is under value. |
1116 __ CallRuntime(Runtime::kToFastProperties, 1); | 1116 __ CallRuntime(Runtime::kToFastProperties, 1); |
1117 __ pop(eax); | 1117 __ pop(eax); |
1118 } | 1118 } |
1119 | 1119 |
1120 DropAndApply(1, context_, eax); | 1120 DropAndApply(1, context_, eax); |
1121 } | 1121 } |
1122 | 1122 |
1123 | 1123 |
1124 void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 1124 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
1125 // Assignment to a property, using a keyed store IC. | 1125 // Assignment to a property, using a keyed store IC. |
1126 | 1126 |
1127 // If the assignment starts a block of assignments to the same object, | 1127 // If the assignment starts a block of assignments to the same object, |
1128 // change to slow case to avoid the quadratic behavior of repeatedly | 1128 // change to slow case to avoid the quadratic behavior of repeatedly |
1129 // adding fast properties. | 1129 // adding fast properties. |
1130 if (expr->starts_initialization_block()) { | 1130 if (expr->starts_initialization_block()) { |
1131 __ push(result_register()); | 1131 __ push(result_register()); |
1132 // Receiver is now under the key and value. | 1132 // Receiver is now under the key and value. |
1133 __ push(Operand(esp, 2 * kPointerSize)); | 1133 __ push(Operand(esp, 2 * kPointerSize)); |
1134 __ CallRuntime(Runtime::kToSlowProperties, 1); | 1134 __ CallRuntime(Runtime::kToSlowProperties, 1); |
(...skipping 15 matching lines...) Expand all Loading... |
1150 __ push(Operand(esp, 2 * kPointerSize)); | 1150 __ push(Operand(esp, 2 * kPointerSize)); |
1151 __ CallRuntime(Runtime::kToFastProperties, 1); | 1151 __ CallRuntime(Runtime::kToFastProperties, 1); |
1152 __ pop(eax); | 1152 __ pop(eax); |
1153 } | 1153 } |
1154 | 1154 |
1155 // Receiver and key are still on stack. | 1155 // Receiver and key are still on stack. |
1156 DropAndApply(2, context_, eax); | 1156 DropAndApply(2, context_, eax); |
1157 } | 1157 } |
1158 | 1158 |
1159 | 1159 |
1160 void FastCodeGenerator::VisitProperty(Property* expr) { | 1160 void FullCodeGenerator::VisitProperty(Property* expr) { |
1161 Comment cmnt(masm_, "[ Property"); | 1161 Comment cmnt(masm_, "[ Property"); |
1162 Expression* key = expr->key(); | 1162 Expression* key = expr->key(); |
1163 | 1163 |
1164 // Evaluate the receiver. | 1164 // Evaluate the receiver. |
1165 VisitForValue(expr->obj(), kStack); | 1165 VisitForValue(expr->obj(), kStack); |
1166 | 1166 |
1167 if (key->IsPropertyName()) { | 1167 if (key->IsPropertyName()) { |
1168 EmitNamedPropertyLoad(expr); | 1168 EmitNamedPropertyLoad(expr); |
1169 // Drop receiver left on the stack by IC. | 1169 // Drop receiver left on the stack by IC. |
1170 DropAndApply(1, context_, eax); | 1170 DropAndApply(1, context_, eax); |
1171 } else { | 1171 } else { |
1172 VisitForValue(expr->key(), kStack); | 1172 VisitForValue(expr->key(), kStack); |
1173 EmitKeyedPropertyLoad(expr); | 1173 EmitKeyedPropertyLoad(expr); |
1174 // Drop key and receiver left on the stack by IC. | 1174 // Drop key and receiver left on the stack by IC. |
1175 DropAndApply(2, context_, eax); | 1175 DropAndApply(2, context_, eax); |
1176 } | 1176 } |
1177 } | 1177 } |
1178 | 1178 |
1179 | 1179 |
1180 void FastCodeGenerator::EmitCallWithIC(Call* expr, | 1180 void FullCodeGenerator::EmitCallWithIC(Call* expr, |
1181 Handle<Object> name, | 1181 Handle<Object> name, |
1182 RelocInfo::Mode mode) { | 1182 RelocInfo::Mode mode) { |
1183 // Code common for calls using the IC. | 1183 // Code common for calls using the IC. |
1184 ZoneList<Expression*>* args = expr->arguments(); | 1184 ZoneList<Expression*>* args = expr->arguments(); |
1185 int arg_count = args->length(); | 1185 int arg_count = args->length(); |
1186 for (int i = 0; i < arg_count; i++) { | 1186 for (int i = 0; i < arg_count; i++) { |
1187 VisitForValue(args->at(i), kStack); | 1187 VisitForValue(args->at(i), kStack); |
1188 } | 1188 } |
1189 __ Set(ecx, Immediate(name)); | 1189 __ Set(ecx, Immediate(name)); |
1190 // Record source position of the IC call. | 1190 // Record source position of the IC call. |
1191 SetSourcePosition(expr->position()); | 1191 SetSourcePosition(expr->position()); |
1192 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 1192 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
1193 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); | 1193 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); |
1194 __ call(ic, mode); | 1194 __ call(ic, mode); |
1195 // Restore context register. | 1195 // Restore context register. |
1196 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 1196 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
1197 Apply(context_, eax); | 1197 Apply(context_, eax); |
1198 } | 1198 } |
1199 | 1199 |
1200 | 1200 |
1201 void FastCodeGenerator::EmitCallWithStub(Call* expr) { | 1201 void FullCodeGenerator::EmitCallWithStub(Call* expr) { |
1202 // Code common for calls using the call stub. | 1202 // Code common for calls using the call stub. |
1203 ZoneList<Expression*>* args = expr->arguments(); | 1203 ZoneList<Expression*>* args = expr->arguments(); |
1204 int arg_count = args->length(); | 1204 int arg_count = args->length(); |
1205 for (int i = 0; i < arg_count; i++) { | 1205 for (int i = 0; i < arg_count; i++) { |
1206 VisitForValue(args->at(i), kStack); | 1206 VisitForValue(args->at(i), kStack); |
1207 } | 1207 } |
1208 // Record source position for debugger. | 1208 // Record source position for debugger. |
1209 SetSourcePosition(expr->position()); | 1209 SetSourcePosition(expr->position()); |
1210 CallFunctionStub stub(arg_count, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE); | 1210 CallFunctionStub stub(arg_count, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE); |
1211 __ CallStub(&stub); | 1211 __ CallStub(&stub); |
1212 // Restore context register. | 1212 // Restore context register. |
1213 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 1213 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
1214 DropAndApply(1, context_, eax); | 1214 DropAndApply(1, context_, eax); |
1215 } | 1215 } |
1216 | 1216 |
1217 | 1217 |
1218 void FastCodeGenerator::VisitCall(Call* expr) { | 1218 void FullCodeGenerator::VisitCall(Call* expr) { |
1219 Comment cmnt(masm_, "[ Call"); | 1219 Comment cmnt(masm_, "[ Call"); |
1220 Expression* fun = expr->expression(); | 1220 Expression* fun = expr->expression(); |
1221 Variable* var = fun->AsVariableProxy()->AsVariable(); | 1221 Variable* var = fun->AsVariableProxy()->AsVariable(); |
1222 | 1222 |
1223 if (var != NULL && var->is_possibly_eval()) { | 1223 if (var != NULL && var->is_possibly_eval()) { |
1224 // Call to the identifier 'eval'. | 1224 // Call to the identifier 'eval'. |
1225 UNREACHABLE(); | 1225 UNREACHABLE(); |
1226 } else if (var != NULL && !var->is_this() && var->is_global()) { | 1226 } else if (var != NULL && !var->is_this() && var->is_global()) { |
1227 // Push global object as receiver for the call IC. | 1227 // Push global object as receiver for the call IC. |
1228 __ push(CodeGenerator::GlobalObject()); | 1228 __ push(CodeGenerator::GlobalObject()); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1279 VisitForValue(fun, kStack); | 1279 VisitForValue(fun, kStack); |
1280 // Load global receiver object. | 1280 // Load global receiver object. |
1281 __ mov(ebx, CodeGenerator::GlobalObject()); | 1281 __ mov(ebx, CodeGenerator::GlobalObject()); |
1282 __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); | 1282 __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); |
1283 // Emit function call. | 1283 // Emit function call. |
1284 EmitCallWithStub(expr); | 1284 EmitCallWithStub(expr); |
1285 } | 1285 } |
1286 } | 1286 } |
1287 | 1287 |
1288 | 1288 |
1289 void FastCodeGenerator::VisitCallNew(CallNew* expr) { | 1289 void FullCodeGenerator::VisitCallNew(CallNew* expr) { |
1290 Comment cmnt(masm_, "[ CallNew"); | 1290 Comment cmnt(masm_, "[ CallNew"); |
1291 // According to ECMA-262, section 11.2.2, page 44, the function | 1291 // According to ECMA-262, section 11.2.2, page 44, the function |
1292 // expression in new calls must be evaluated before the | 1292 // expression in new calls must be evaluated before the |
1293 // arguments. | 1293 // arguments. |
1294 // Push function on the stack. | 1294 // Push function on the stack. |
1295 VisitForValue(expr->expression(), kStack); | 1295 VisitForValue(expr->expression(), kStack); |
1296 | 1296 |
1297 // Push global object (receiver). | 1297 // Push global object (receiver). |
1298 __ push(CodeGenerator::GlobalObject()); | 1298 __ push(CodeGenerator::GlobalObject()); |
1299 | 1299 |
(...skipping 14 matching lines...) Expand all Loading... |
1314 __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize)); | 1314 __ mov(edi, Operand(esp, eax, times_pointer_size, kPointerSize)); |
1315 | 1315 |
1316 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); | 1316 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); |
1317 __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL); | 1317 __ call(construct_builtin, RelocInfo::CONSTRUCT_CALL); |
1318 | 1318 |
1319 // Replace function on TOS with result in eax, or pop it. | 1319 // Replace function on TOS with result in eax, or pop it. |
1320 DropAndApply(1, context_, eax); | 1320 DropAndApply(1, context_, eax); |
1321 } | 1321 } |
1322 | 1322 |
1323 | 1323 |
1324 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 1324 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
1325 Comment cmnt(masm_, "[ CallRuntime"); | 1325 Comment cmnt(masm_, "[ CallRuntime"); |
1326 ZoneList<Expression*>* args = expr->arguments(); | 1326 ZoneList<Expression*>* args = expr->arguments(); |
1327 | 1327 |
1328 if (expr->is_jsruntime()) { | 1328 if (expr->is_jsruntime()) { |
1329 // Prepare for calling JS runtime function. | 1329 // Prepare for calling JS runtime function. |
1330 __ mov(eax, CodeGenerator::GlobalObject()); | 1330 __ mov(eax, CodeGenerator::GlobalObject()); |
1331 __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset)); | 1331 __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset)); |
1332 } | 1332 } |
1333 | 1333 |
1334 // Push the arguments ("left-to-right"). | 1334 // Push the arguments ("left-to-right"). |
(...skipping 11 matching lines...) Expand all Loading... |
1346 // Restore context register. | 1346 // Restore context register. |
1347 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 1347 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
1348 } else { | 1348 } else { |
1349 // Call the C runtime function. | 1349 // Call the C runtime function. |
1350 __ CallRuntime(expr->function(), arg_count); | 1350 __ CallRuntime(expr->function(), arg_count); |
1351 } | 1351 } |
1352 Apply(context_, eax); | 1352 Apply(context_, eax); |
1353 } | 1353 } |
1354 | 1354 |
1355 | 1355 |
1356 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 1356 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
1357 switch (expr->op()) { | 1357 switch (expr->op()) { |
1358 case Token::VOID: { | 1358 case Token::VOID: { |
1359 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); | 1359 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); |
1360 VisitForEffect(expr->expression()); | 1360 VisitForEffect(expr->expression()); |
1361 switch (context_) { | 1361 switch (context_) { |
1362 case Expression::kUninitialized: | 1362 case Expression::kUninitialized: |
1363 UNREACHABLE(); | 1363 UNREACHABLE(); |
1364 break; | 1364 break; |
1365 case Expression::kEffect: | 1365 case Expression::kEffect: |
1366 break; | 1366 break; |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1456 Apply(context_, eax); | 1456 Apply(context_, eax); |
1457 break; | 1457 break; |
1458 } | 1458 } |
1459 | 1459 |
1460 default: | 1460 default: |
1461 UNREACHABLE(); | 1461 UNREACHABLE(); |
1462 } | 1462 } |
1463 } | 1463 } |
1464 | 1464 |
1465 | 1465 |
1466 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { | 1466 void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { |
1467 Comment cmnt(masm_, "[ CountOperation"); | 1467 Comment cmnt(masm_, "[ CountOperation"); |
1468 | 1468 |
1469 // Expression can only be a property, a global or a (parameter or local) | 1469 // Expression can only be a property, a global or a (parameter or local) |
1470 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. | 1470 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. |
1471 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 1471 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
1472 LhsKind assign_type = VARIABLE; | 1472 LhsKind assign_type = VARIABLE; |
1473 Property* prop = expr->expression()->AsProperty(); | 1473 Property* prop = expr->expression()->AsProperty(); |
1474 // In case of a property we use the uninitialized expression context | 1474 // In case of a property we use the uninitialized expression context |
1475 // of the key to detect a named property. | 1475 // of the key to detect a named property. |
1476 if (prop != NULL) { | 1476 if (prop != NULL) { |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1588 } | 1588 } |
1589 } else { | 1589 } else { |
1590 DropAndApply(2, context_, eax); | 1590 DropAndApply(2, context_, eax); |
1591 } | 1591 } |
1592 break; | 1592 break; |
1593 } | 1593 } |
1594 } | 1594 } |
1595 } | 1595 } |
1596 | 1596 |
1597 | 1597 |
1598 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 1598 void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
1599 Comment cmnt(masm_, "[ BinaryOperation"); | 1599 Comment cmnt(masm_, "[ BinaryOperation"); |
1600 switch (expr->op()) { | 1600 switch (expr->op()) { |
1601 case Token::COMMA: | 1601 case Token::COMMA: |
1602 VisitForEffect(expr->left()); | 1602 VisitForEffect(expr->left()); |
1603 Visit(expr->right()); | 1603 Visit(expr->right()); |
1604 break; | 1604 break; |
1605 | 1605 |
1606 case Token::OR: | 1606 case Token::OR: |
1607 case Token::AND: | 1607 case Token::AND: |
1608 EmitLogicalOperation(expr); | 1608 EmitLogicalOperation(expr); |
(...skipping 14 matching lines...) Expand all Loading... |
1623 VisitForValue(expr->right(), kAccumulator); | 1623 VisitForValue(expr->right(), kAccumulator); |
1624 EmitBinaryOp(expr->op(), context_); | 1624 EmitBinaryOp(expr->op(), context_); |
1625 break; | 1625 break; |
1626 | 1626 |
1627 default: | 1627 default: |
1628 UNREACHABLE(); | 1628 UNREACHABLE(); |
1629 } | 1629 } |
1630 } | 1630 } |
1631 | 1631 |
1632 | 1632 |
1633 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 1633 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
1634 Comment cmnt(masm_, "[ CompareOperation"); | 1634 Comment cmnt(masm_, "[ CompareOperation"); |
1635 | 1635 |
1636 // Always perform the comparison for its control flow. Pack the result | 1636 // Always perform the comparison for its control flow. Pack the result |
1637 // into the expression's context after the comparison is performed. | 1637 // into the expression's context after the comparison is performed. |
1638 Label materialize_true, materialize_false, done; | 1638 Label materialize_true, materialize_false, done; |
1639 // Initially assume we are in a test context. | 1639 // Initially assume we are in a test context. |
1640 Label* if_true = true_label_; | 1640 Label* if_true = true_label_; |
1641 Label* if_false = false_label_; | 1641 Label* if_false = false_label_; |
1642 switch (context_) { | 1642 switch (context_) { |
1643 case Expression::kUninitialized: | 1643 case Expression::kUninitialized: |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1738 __ jmp(if_false); | 1738 __ jmp(if_false); |
1739 } | 1739 } |
1740 } | 1740 } |
1741 | 1741 |
1742 // Convert the result of the comparison into one expected for this | 1742 // Convert the result of the comparison into one expected for this |
1743 // expression's context. | 1743 // expression's context. |
1744 Apply(context_, if_true, if_false); | 1744 Apply(context_, if_true, if_false); |
1745 } | 1745 } |
1746 | 1746 |
1747 | 1747 |
1748 void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 1748 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
1749 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 1749 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
1750 Apply(context_, eax); | 1750 Apply(context_, eax); |
1751 } | 1751 } |
1752 | 1752 |
1753 | 1753 |
1754 Register FastCodeGenerator::result_register() { return eax; } | 1754 Register FullCodeGenerator::result_register() { return eax; } |
1755 | 1755 |
1756 | 1756 |
1757 Register FastCodeGenerator::context_register() { return esi; } | 1757 Register FullCodeGenerator::context_register() { return esi; } |
1758 | 1758 |
1759 | 1759 |
1760 void FastCodeGenerator::StoreToFrameField(int frame_offset, Register value) { | 1760 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { |
1761 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); | 1761 ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); |
1762 __ mov(Operand(ebp, frame_offset), value); | 1762 __ mov(Operand(ebp, frame_offset), value); |
1763 } | 1763 } |
1764 | 1764 |
1765 | 1765 |
1766 void FastCodeGenerator::LoadContextField(Register dst, int context_index) { | 1766 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { |
1767 __ mov(dst, CodeGenerator::ContextOperand(esi, context_index)); | 1767 __ mov(dst, CodeGenerator::ContextOperand(esi, context_index)); |
1768 } | 1768 } |
1769 | 1769 |
1770 | 1770 |
1771 // ---------------------------------------------------------------------------- | 1771 // ---------------------------------------------------------------------------- |
1772 // Non-local control flow support. | 1772 // Non-local control flow support. |
1773 | 1773 |
1774 void FastCodeGenerator::EnterFinallyBlock() { | 1774 void FullCodeGenerator::EnterFinallyBlock() { |
1775 // Cook return address on top of stack (smi encoded Code* delta) | 1775 // Cook return address on top of stack (smi encoded Code* delta) |
1776 ASSERT(!result_register().is(edx)); | 1776 ASSERT(!result_register().is(edx)); |
1777 __ mov(edx, Operand(esp, 0)); | 1777 __ mov(edx, Operand(esp, 0)); |
1778 __ sub(Operand(edx), Immediate(masm_->CodeObject())); | 1778 __ sub(Operand(edx), Immediate(masm_->CodeObject())); |
1779 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); | 1779 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); |
1780 ASSERT_EQ(0, kSmiTag); | 1780 ASSERT_EQ(0, kSmiTag); |
1781 __ add(edx, Operand(edx)); // Convert to smi. | 1781 __ add(edx, Operand(edx)); // Convert to smi. |
1782 __ mov(Operand(esp, 0), edx); | 1782 __ mov(Operand(esp, 0), edx); |
1783 // Store result register while executing finally block. | 1783 // Store result register while executing finally block. |
1784 __ push(result_register()); | 1784 __ push(result_register()); |
1785 } | 1785 } |
1786 | 1786 |
1787 | 1787 |
1788 void FastCodeGenerator::ExitFinallyBlock() { | 1788 void FullCodeGenerator::ExitFinallyBlock() { |
1789 ASSERT(!result_register().is(edx)); | 1789 ASSERT(!result_register().is(edx)); |
1790 // Restore result register from stack. | 1790 // Restore result register from stack. |
1791 __ pop(result_register()); | 1791 __ pop(result_register()); |
1792 // Uncook return address. | 1792 // Uncook return address. |
1793 __ mov(edx, Operand(esp, 0)); | 1793 __ mov(edx, Operand(esp, 0)); |
1794 __ sar(edx, 1); // Convert smi to int. | 1794 __ sar(edx, 1); // Convert smi to int. |
1795 __ add(Operand(edx), Immediate(masm_->CodeObject())); | 1795 __ add(Operand(edx), Immediate(masm_->CodeObject())); |
1796 __ mov(Operand(esp, 0), edx); | 1796 __ mov(Operand(esp, 0), edx); |
1797 // And return. | 1797 // And return. |
1798 __ ret(0); | 1798 __ ret(0); |
1799 } | 1799 } |
1800 | 1800 |
1801 | 1801 |
1802 #undef __ | 1802 #undef __ |
1803 | 1803 |
1804 } } // namespace v8::internal | 1804 } } // namespace v8::internal |
OLD | NEW |