OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/compiler.h" | 7 #include "src/compiler.h" |
8 #include "src/interpreter/bytecode-array-iterator.h" | 8 #include "src/interpreter/bytecode-array-iterator.h" |
9 #include "src/interpreter/bytecode-generator.h" | 9 #include "src/interpreter/bytecode-generator.h" |
10 #include "src/interpreter/interpreter.h" | 10 #include "src/interpreter/interpreter.h" |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 CompileRun(script); | 48 CompileRun(script); |
49 v8::Local<v8::Context> context = | 49 v8::Local<v8::Context> context = |
50 v8::Isolate::GetCurrent()->GetCurrentContext(); | 50 v8::Isolate::GetCurrent()->GetCurrentContext(); |
51 Local<Function> function = Local<Function>::Cast( | 51 Local<Function> function = Local<Function>::Cast( |
52 CcTest::global()->Get(context, v8_str(function_name)).ToLocalChecked()); | 52 CcTest::global()->Get(context, v8_str(function_name)).ToLocalChecked()); |
53 i::Handle<i::JSFunction> js_function = | 53 i::Handle<i::JSFunction> js_function = |
54 i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*function)); | 54 i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*function)); |
55 return handle(js_function->shared()->bytecode_array(), CcTest::i_isolate()); | 55 return handle(js_function->shared()->bytecode_array(), CcTest::i_isolate()); |
56 } | 56 } |
57 | 57 |
| 58 Handle<BytecodeArray> MakeBytecode(const char* script, const char* filter, |
| 59 const char* function_name) { |
| 60 const char* old_ignition_filter = i::FLAG_ignition_filter; |
| 61 i::FLAG_ignition_filter = filter; |
| 62 CompileRun(script); |
| 63 i::FLAG_ignition_filter = old_ignition_filter; |
| 64 v8::Local<v8::Context> context = |
| 65 v8::Isolate::GetCurrent()->GetCurrentContext(); |
| 66 Local<Function> function = Local<Function>::Cast( |
| 67 CcTest::global()->Get(context, v8_str(function_name)).ToLocalChecked()); |
| 68 i::Handle<i::JSFunction> js_function = |
| 69 i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*function)); |
| 70 return handle(js_function->shared()->bytecode_array(), CcTest::i_isolate()); |
| 71 } |
| 72 |
58 Handle<BytecodeArray> MakeBytecodeForFunctionBody(const char* body) { | 73 Handle<BytecodeArray> MakeBytecodeForFunctionBody(const char* body) { |
59 ScopedVector<char> program(3072); | 74 ScopedVector<char> program(3072); |
60 SNPrintF(program, "function %s() { %s }\n%s();", kFunctionName, body, | 75 SNPrintF(program, "function %s() { %s }\n%s();", kFunctionName, body, |
61 kFunctionName); | 76 kFunctionName); |
62 return MakeBytecode(program.start(), kFunctionName); | 77 return MakeBytecode(program.start(), kFunctionName); |
63 } | 78 } |
64 | 79 |
65 Handle<BytecodeArray> MakeBytecodeForFunction(const char* function) { | 80 Handle<BytecodeArray> MakeBytecodeForFunction(const char* function) { |
66 ScopedVector<char> program(3072); | 81 ScopedVector<char> program(3072); |
67 SNPrintF(program, "%s\n%s();", function, kFunctionName); | 82 SNPrintF(program, "%s\n%s();", function, kFunctionName); |
(...skipping 5490 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5558 B(Mov), R(1), R(4), // | 5573 B(Mov), R(1), R(4), // |
5559 B(Mov), R(3), R(5), // | 5574 B(Mov), R(3), R(5), // |
5560 B(Mov), R(closure), R(6), // | 5575 B(Mov), R(closure), R(6), // |
5561 B(LdaZero), // | 5576 B(LdaZero), // |
5562 B(Star), R(7), // | 5577 B(Star), R(7), // |
5563 B(LdaSmi8), U8(10), // | 5578 B(LdaSmi8), U8(10), // |
5564 B(Star), R(8), // | 5579 B(Star), R(8), // |
5565 B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), // | 5580 B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), // |
5566 U8(5), // | 5581 U8(5), // |
5567 B(Star), R(1), // | 5582 B(Star), R(1), // |
5568 B(Call), R(1), R(2), U8(1), U8(2), // | 5583 B(Call), R(1), R(2), U8(1), U8(0), // |
5569 B(Return), // | 5584 B(Return), // |
5570 }, | 5585 }, |
5571 2, | 5586 2, |
5572 {"eval", "1;"}}, | 5587 {"eval", "1;"}}, |
5573 }; | 5588 }; |
5574 | 5589 |
5575 for (size_t i = 0; i < arraysize(snippets); i++) { | 5590 for (size_t i = 0; i < arraysize(snippets); i++) { |
5576 Handle<BytecodeArray> bytecode_array = | 5591 Handle<BytecodeArray> bytecode_array = |
5577 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); | 5592 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); |
5578 CheckBytecodeArrayEqual(snippets[i], bytecode_array); | 5593 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
5579 } | 5594 } |
5580 } | 5595 } |
5581 | 5596 |
| 5597 |
| 5598 TEST(StoreLookupSlotSloppy) { |
| 5599 InitializedHandleScope handle_scope; |
| 5600 BytecodeGeneratorHelper helper; |
| 5601 |
| 5602 int closure = Register::function_closure().index(); |
| 5603 int first_context_slot = Context::MIN_CONTEXT_SLOTS; |
| 5604 int context = Register::function_context().index(); |
| 5605 int new_target = Register::new_target().index(); |
| 5606 |
| 5607 ExpectedSnippet<const char*> snippets[] = { |
| 5608 {"x = 20; return eval('');", |
| 5609 9 * kPointerSize, |
| 5610 1, |
| 5611 80, |
| 5612 { |
| 5613 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // |
| 5614 U8(1), // |
| 5615 B(PushContext), R(0), // |
| 5616 B(Ldar), THIS(1), // |
| 5617 B(StaContextSlot), R(0), U8(first_context_slot), // |
| 5618 B(CreateMappedArguments), // |
| 5619 B(StaContextSlot), R(0), U8(first_context_slot + 1), // |
| 5620 B(Ldar), R(new_target), // |
| 5621 B(StaContextSlot), R(0), U8(first_context_slot + 2), // |
| 5622 B(LdaSmi8), U8(20), // |
| 5623 B(StaLookupSlotSloppy), U8(0), R(0), // |
| 5624 B(Mov), R(context), R(3), // |
| 5625 B(LdaConstant), U8(1), // |
| 5626 B(Star), R(4), // |
| 5627 B(CallRuntime), U16(Runtime::kInterpreterLoadLookupSlotCallee), // |
| 5628 R(3), U8(2), // |
| 5629 B(Star), R(1), // |
| 5630 B(CallRuntime), U16(Runtime::kInterpreterLoadLookupSlotReceiver), // |
| 5631 R(3), U8(2), // |
| 5632 B(Star), R(2), // |
| 5633 B(LdaConstant), U8(2), // |
| 5634 B(Star), R(3), // |
| 5635 B(Mov), R(1), R(4), // |
| 5636 B(Mov), R(3), R(5), // |
| 5637 B(Mov), R(closure), R(6), // |
| 5638 B(LdaZero), // |
| 5639 B(Star), R(7), // |
| 5640 B(LdaSmi8), U8(10), // |
| 5641 B(Star), R(8), // |
| 5642 B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), // |
| 5643 U8(5), // |
| 5644 B(Star), R(1), // |
| 5645 B(Call), R(1), R(2), U8(1), U8(0), // |
| 5646 B(Return), // |
| 5647 }, |
| 5648 3, |
| 5649 {"x", "eval", ""}}, |
| 5650 }; |
| 5651 |
| 5652 for (size_t i = 0; i < arraysize(snippets); i++) { |
| 5653 Handle<BytecodeArray> bytecode_array = |
| 5654 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); |
| 5655 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
| 5656 } |
| 5657 } |
| 5658 |
| 5659 |
| 5660 TEST(LdaLookupSlot) { |
| 5661 InitializedHandleScope handle_scope; |
| 5662 BytecodeGeneratorHelper helper; |
| 5663 |
| 5664 int closure = Register::function_closure().index(); |
| 5665 int first_context_slot = Context::MIN_CONTEXT_SLOTS; |
| 5666 int context = Register::function_context().index(); |
| 5667 int new_target = Register::new_target().index(); |
| 5668 |
| 5669 ExpectedSnippet<const char*> snippets[] = { |
| 5670 {"eval('var x = 10;'); return x;", |
| 5671 9 * kPointerSize, |
| 5672 1, |
| 5673 78, |
| 5674 { |
| 5675 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // |
| 5676 U8(1), // |
| 5677 B(PushContext), R(0), // |
| 5678 B(Ldar), THIS(1), // |
| 5679 B(StaContextSlot), R(0), U8(first_context_slot), // |
| 5680 B(CreateMappedArguments), // |
| 5681 B(StaContextSlot), R(0), U8(first_context_slot + 1), // |
| 5682 B(Ldar), R(new_target), // |
| 5683 B(StaContextSlot), R(0), U8(first_context_slot + 2), // |
| 5684 B(Mov), R(context), R(3), // |
| 5685 B(LdaConstant), U8(0), // |
| 5686 B(Star), R(4), // |
| 5687 B(CallRuntime), U16(Runtime::kInterpreterLoadLookupSlotCallee), // |
| 5688 R(3), U8(2), // |
| 5689 B(Star), R(1), // |
| 5690 B(CallRuntime), U16(Runtime::kInterpreterLoadLookupSlotReceiver), // |
| 5691 R(3), U8(2), // |
| 5692 B(Star), R(2), // |
| 5693 B(LdaConstant), U8(1), // |
| 5694 B(Star), R(3), // |
| 5695 B(Mov), R(1), R(4), // |
| 5696 B(Mov), R(3), R(5), // |
| 5697 B(Mov), R(closure), R(6), // |
| 5698 B(LdaZero), // |
| 5699 B(Star), R(7), // |
| 5700 B(LdaSmi8), U8(10), // |
| 5701 B(Star), R(8), // |
| 5702 B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), // |
| 5703 U8(5), // |
| 5704 B(Star), R(1), // |
| 5705 B(Call), R(1), R(2), U8(1), U8(0), // |
| 5706 B(LdaLookupSlot), U8(2), R(0), // |
| 5707 B(Return), // |
| 5708 }, |
| 5709 3, |
| 5710 {"eval", "var x = 10;", "x"}}, |
| 5711 }; |
| 5712 |
| 5713 for (size_t i = 0; i < arraysize(snippets); i++) { |
| 5714 Handle<BytecodeArray> bytecode_array = |
| 5715 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); |
| 5716 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
| 5717 } |
| 5718 } |
| 5719 |
| 5720 |
| 5721 TEST(LdaLookupSlotInsideTypeOf) { |
| 5722 InitializedHandleScope handle_scope; |
| 5723 BytecodeGeneratorHelper helper; |
| 5724 |
| 5725 int closure = Register::function_closure().index(); |
| 5726 int first_context_slot = Context::MIN_CONTEXT_SLOTS; |
| 5727 int context = Register::function_context().index(); |
| 5728 int new_target = Register::new_target().index(); |
| 5729 |
| 5730 ExpectedSnippet<const char*> snippets[] = { |
| 5731 {"eval('var x = 10;'); return typeof x;", |
| 5732 9 * kPointerSize, |
| 5733 1, |
| 5734 79, |
| 5735 { |
| 5736 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // |
| 5737 U8(1), // |
| 5738 B(PushContext), R(0), // |
| 5739 B(Ldar), THIS(1), // |
| 5740 B(StaContextSlot), R(0), U8(first_context_slot), // |
| 5741 B(CreateMappedArguments), // |
| 5742 B(StaContextSlot), R(0), U8(first_context_slot + 1), // |
| 5743 B(Ldar), R(new_target), // |
| 5744 B(StaContextSlot), R(0), U8(first_context_slot + 2), // |
| 5745 B(Mov), R(context), R(3), // |
| 5746 B(LdaConstant), U8(0), // |
| 5747 B(Star), R(4), // |
| 5748 B(CallRuntime), U16(Runtime::kInterpreterLoadLookupSlotCallee), // |
| 5749 R(3), U8(2), // |
| 5750 B(Star), R(1), // |
| 5751 B(CallRuntime), U16(Runtime::kInterpreterLoadLookupSlotReceiver), // |
| 5752 R(3), U8(2), // |
| 5753 B(Star), R(2), // |
| 5754 B(LdaConstant), U8(1), // |
| 5755 B(Star), R(3), // |
| 5756 B(Mov), R(1), R(4), // |
| 5757 B(Mov), R(3), R(5), // |
| 5758 B(Mov), R(closure), R(6), // |
| 5759 B(LdaZero), // |
| 5760 B(Star), R(7), // |
| 5761 B(LdaSmi8), U8(10), // |
| 5762 B(Star), R(8), // |
| 5763 B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), // |
| 5764 U8(5), // |
| 5765 B(Star), R(1), // |
| 5766 B(Call), R(1), R(2), U8(1), U8(0), // |
| 5767 B(LdaLookupSlotInsideTypeof), U8(2), R(0), // |
| 5768 B(TypeOf), // |
| 5769 B(Return), // |
| 5770 }, |
| 5771 3, |
| 5772 {"eval", "var x = 10;", "x"}}, |
| 5773 }; |
| 5774 |
| 5775 for (size_t i = 0; i < arraysize(snippets); i++) { |
| 5776 Handle<BytecodeArray> bytecode_array = |
| 5777 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); |
| 5778 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
| 5779 } |
| 5780 } |
| 5781 |
| 5782 |
| 5783 TEST(LookupSlotInEval) { |
| 5784 InitializedHandleScope handle_scope; |
| 5785 BytecodeGeneratorHelper helper; |
| 5786 |
| 5787 int context = Register::function_context().index(); |
| 5788 |
| 5789 const char* function_prologue = "var f;" |
| 5790 "var x = 1;" |
| 5791 "function f1() {" |
| 5792 " eval(\"function t() {"; |
| 5793 const char* function_epilogue = " }; f = t; f();\");" |
| 5794 "}" |
| 5795 "f1();"; |
| 5796 |
| 5797 ExpectedSnippet<const char*> snippets[] = { |
| 5798 {"return x;", |
| 5799 0 * kPointerSize, |
| 5800 1, |
| 5801 4, |
| 5802 { |
| 5803 B(LdaLookupSlot), U8(0), R(context), // |
| 5804 B(Return) // |
| 5805 }, |
| 5806 1, |
| 5807 {"x"}}, |
| 5808 {"x = 10;", |
| 5809 0 * kPointerSize, |
| 5810 1, |
| 5811 7, |
| 5812 { |
| 5813 B(LdaSmi8), U8(10), // |
| 5814 B(StaLookupSlotSloppy), U8(0), R(context), // |
| 5815 B(LdaUndefined), // |
| 5816 B(Return), // |
| 5817 }, |
| 5818 1, |
| 5819 {"x"}}, |
| 5820 {"'use strict'; x = 10;", |
| 5821 0 * kPointerSize, |
| 5822 1, |
| 5823 7, |
| 5824 { |
| 5825 B(LdaSmi8), U8(10), // |
| 5826 B(StaLookupSlotStrict), U8(0), R(context), // |
| 5827 B(LdaUndefined), // |
| 5828 B(Return), // |
| 5829 }, |
| 5830 1, |
| 5831 {"x"}}, |
| 5832 {"return typeof x;", |
| 5833 0 * kPointerSize, |
| 5834 1, |
| 5835 5, |
| 5836 { |
| 5837 B(LdaLookupSlotInsideTypeof), U8(0), R(context), // |
| 5838 B(TypeOf), // |
| 5839 B(Return), // |
| 5840 }, |
| 5841 1, |
| 5842 {"x"}}, |
| 5843 }; |
| 5844 |
| 5845 for (size_t i = 0; i < arraysize(snippets); i++) { |
| 5846 std::string script = std::string(function_prologue) + |
| 5847 std::string(snippets[i].code_snippet) + |
| 5848 std::string(function_epilogue); |
| 5849 // TODO(mythria): use * as filter when function declarations are supported |
| 5850 // inside eval. |
| 5851 Handle<BytecodeArray> bytecode_array = |
| 5852 helper.MakeBytecode(script.c_str(), "t", "f"); |
| 5853 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
| 5854 } |
| 5855 } |
| 5856 |
5582 } // namespace interpreter | 5857 } // namespace interpreter |
5583 } // namespace internal | 5858 } // namespace internal |
5584 } // namespace v8 | 5859 } // namespace v8 |
OLD | NEW |