Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(161)

Side by Side Diff: test/cctest/interpreter/test-bytecode-generator.cc

Issue 1474103002: Re-reland "[Interpreter] Add CreateClosure to BytecodeGraphBuilder." (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 // TODO(rmcilroy): Remove this define after this flag is turned on globally 5 // TODO(rmcilroy): Remove this define after this flag is turned on globally
6 #define V8_IMMINENT_DEPRECATION_WARNINGS 6 #define V8_IMMINENT_DEPRECATION_WARNINGS
7 7
8 #include "src/v8.h" 8 #include "src/v8.h"
9 9
10 #include "src/compiler.h" 10 #include "src/compiler.h"
(...skipping 2647 matching lines...) Expand 10 before | Expand all | Expand 10 after
2658 B(LdaFalse), // 2658 B(LdaFalse), //
2659 B(Return) 2659 B(Return)
2660 }, 2660 },
2661 0}, 2661 0},
2662 {"'use strict';" 2662 {"'use strict';"
2663 "var a = {1:10};" 2663 "var a = {1:10};"
2664 "(function f1() {return a;});" 2664 "(function f1() {return a;});"
2665 "return delete a[1];", 2665 "return delete a[1];",
2666 2 * kPointerSize, 2666 2 * kPointerSize,
2667 1, 2667 1,
2668 29, 2668 28,
2669 { 2669 {
2670 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 2670 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
2671 R(closure), U8(1), // 2671 R(closure), U8(1), //
2672 B(PushContext), R(0), // 2672 B(PushContext), R(0), //
2673 B(LdaConstant), U8(0), // 2673 B(LdaConstant), U8(0), //
2674 B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), // 2674 B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), //
2675 B(StaContextSlot), R(0), U8(first_context_slot), // 2675 B(StaContextSlot), R(0), U8(first_context_slot), //
2676 B(LdaConstant), U8(1), // 2676 B(CreateClosure), U8(1), U8(0), //
2677 B(CreateClosure), U8(0), //
2678 B(LdaContextSlot), R(0), U8(first_context_slot), // 2677 B(LdaContextSlot), R(0), U8(first_context_slot), //
2679 B(Star), R(1), // 2678 B(Star), R(1), //
2680 B(LdaSmi8), U8(1), // 2679 B(LdaSmi8), U8(1), //
2681 B(DeletePropertyStrict), R(1), // 2680 B(DeletePropertyStrict), R(1), //
2682 B(Return) 2681 B(Return)
2683 }, 2682 },
2684 2, 2683 2,
2685 {InstanceType::FIXED_ARRAY_TYPE, 2684 {InstanceType::FIXED_ARRAY_TYPE,
2686 InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 2685 InstanceType::SHARED_FUNCTION_INFO_TYPE}},
2687 {"return delete 'test';", 2686 {"return delete 'test';",
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
2788 FeedbackVectorSpec feedback_spec(&zone); 2787 FeedbackVectorSpec feedback_spec(&zone);
2789 FeedbackVectorSlot slot = feedback_spec.AddCallICSlot(); 2788 FeedbackVectorSlot slot = feedback_spec.AddCallICSlot();
2790 2789
2791 Handle<i::TypeFeedbackVector> vector = 2790 Handle<i::TypeFeedbackVector> vector =
2792 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); 2791 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
2793 2792
2794 ExpectedSnippet<InstanceType> snippets[] = { 2793 ExpectedSnippet<InstanceType> snippets[] = {
2795 {"return function(){ }", 2794 {"return function(){ }",
2796 0, 2795 0,
2797 1, 2796 1,
2798 5, 2797 4,
2799 { 2798 {
2800 B(LdaConstant), U8(0), // 2799 B(CreateClosure), U8(0), U8(0), //
2801 B(CreateClosure), U8(0), // 2800 B(Return) //
2802 B(Return) //
2803 }, 2801 },
2804 1, 2802 1,
2805 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 2803 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
2806 {"return (function(){ })()", 2804 {"return (function(){ })()",
2807 2 * kPointerSize, 2805 2 * kPointerSize,
2808 1, 2806 1,
2809 15, 2807 14,
2810 { 2808 {
2811 B(LdaUndefined), // 2809 B(LdaUndefined), //
2812 B(Star), R(1), // 2810 B(Star), R(1), //
2813 B(LdaConstant), U8(0), // 2811 B(CreateClosure), U8(0), U8(0), //
2814 B(CreateClosure), U8(0), //
2815 B(Star), R(0), // 2812 B(Star), R(0), //
2816 B(Call), R(0), R(1), U8(0), U8(vector->GetIndex(slot)), // 2813 B(Call), R(0), R(1), U8(0), U8(vector->GetIndex(slot)), //
2817 B(Return) // 2814 B(Return) //
2818 }, 2815 },
2819 1, 2816 1,
2820 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 2817 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
2821 {"return (function(x){ return x; })(1)", 2818 {"return (function(x){ return x; })(1)",
2822 3 * kPointerSize, 2819 3 * kPointerSize,
2823 1, 2820 1,
2824 19, 2821 18,
2825 { 2822 {
2826 B(LdaUndefined), // 2823 B(LdaUndefined), //
2827 B(Star), R(1), // 2824 B(Star), R(1), //
2828 B(LdaConstant), U8(0), // 2825 B(CreateClosure), U8(0), U8(0), //
2829 B(CreateClosure), U8(0), //
2830 B(Star), R(0), // 2826 B(Star), R(0), //
2831 B(LdaSmi8), U8(1), // 2827 B(LdaSmi8), U8(1), //
2832 B(Star), R(2), // 2828 B(Star), R(2), //
2833 B(Call), R(0), R(1), U8(1), U8(vector->GetIndex(slot)), // 2829 B(Call), R(0), R(1), U8(1), U8(vector->GetIndex(slot)), //
2834 B(Return) // 2830 B(Return) //
2835 }, 2831 },
2836 1, 2832 1,
2837 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 2833 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
2838 }; 2834 };
2839 2835
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after
3092 B(StoreICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), // 3088 B(StoreICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), //
3093 B(Ldar), R(1), // 3089 B(Ldar), R(1), //
3094 B(Return), // 3090 B(Return), //
3095 }, 3091 },
3096 2, 3092 2,
3097 {InstanceType::FIXED_ARRAY_TYPE, 3093 {InstanceType::FIXED_ARRAY_TYPE,
3098 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 3094 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
3099 {"return { func: function() { } };", 3095 {"return { func: function() { } };",
3100 1 * kPointerSize, 3096 1 * kPointerSize,
3101 1, 3097 1,
3102 18, 3098 17,
3103 { 3099 {
3104 B(LdaConstant), U8(0), // 3100 B(LdaConstant), U8(0), //
3105 B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), // 3101 B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), //
3106 B(Star), R(0), // 3102 B(Star), R(0), //
3107 B(LdaConstant), U8(2), // 3103 B(CreateClosure), U8(2), U8(0), //
3108 B(CreateClosure), U8(0), //
3109 B(StoreICSloppy), R(0), U8(1), U8(vector->GetIndex(slot1)), // 3104 B(StoreICSloppy), R(0), U8(1), U8(vector->GetIndex(slot1)), //
3110 B(Ldar), R(0), // 3105 B(Ldar), R(0), //
3111 B(Return), // 3106 B(Return), //
3112 }, 3107 },
3113 3, 3108 3,
3114 {InstanceType::FIXED_ARRAY_TYPE, 3109 {InstanceType::FIXED_ARRAY_TYPE,
3115 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 3110 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
3116 InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3111 InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3117 {"return { func(a) { return a; } };", 3112 {"return { func(a) { return a; } };",
3118 1 * kPointerSize, 3113 1 * kPointerSize,
3119 1, 3114 1,
3120 18, 3115 17,
3121 { 3116 {
3122 B(LdaConstant), U8(0), // 3117 B(LdaConstant), U8(0), //
3123 B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), // 3118 B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), //
3124 B(Star), R(0), // 3119 B(Star), R(0), //
3125 B(LdaConstant), U8(2), // 3120 B(CreateClosure), U8(2), U8(0), //
3126 B(CreateClosure), U8(0), //
3127 B(StoreICSloppy), R(0), U8(1), U8(vector->GetIndex(slot1)), // 3121 B(StoreICSloppy), R(0), U8(1), U8(vector->GetIndex(slot1)), //
3128 B(Ldar), R(0), // 3122 B(Ldar), R(0), //
3129 B(Return), // 3123 B(Return), //
3130 }, 3124 },
3131 3, 3125 3,
3132 {InstanceType::FIXED_ARRAY_TYPE, 3126 {InstanceType::FIXED_ARRAY_TYPE,
3133 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 3127 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
3134 InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3128 InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3135 {"return { get a() { return 2; } };", 3129 {"return { get a() { return 2; } };",
3136 5 * kPointerSize, 3130 5 * kPointerSize,
3137 1, 3131 1,
3138 31, 3132 30,
3139 { 3133 {
3140 B(LdaConstant), U8(0), // 3134 B(LdaConstant), U8(0), //
3141 B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), // 3135 B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), //
3142 B(Star), R(0), // 3136 B(Star), R(0), //
3143 B(LdaConstant), U8(1), // 3137 B(LdaConstant), U8(1), //
3144 B(Star), R(1), // 3138 B(Star), R(1), //
3145 B(LdaConstant), U8(2), // 3139 B(CreateClosure), U8(2), U8(0), //
3146 B(CreateClosure), U8(0), //
3147 B(Star), R(2), // 3140 B(Star), R(2), //
3148 B(LdaNull), // 3141 B(LdaNull), //
3149 B(Star), R(3), // 3142 B(Star), R(3), //
3150 B(LdaZero), // 3143 B(LdaZero), //
3151 B(Star), R(4), // 3144 B(Star), R(4), //
3152 B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), // 3145 B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), //
3153 R(0), U8(5), // 3146 R(0), U8(5), //
3154 B(Ldar), R(0), // 3147 B(Ldar), R(0), //
3155 B(Return), // 3148 B(Return), //
3156 }, 3149 },
3157 3, 3150 3,
3158 {InstanceType::FIXED_ARRAY_TYPE, 3151 {InstanceType::FIXED_ARRAY_TYPE,
3159 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 3152 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
3160 InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3153 InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3161 {"return { get a() { return this.x; }, set a(val) { this.x = val } };", 3154 {"return { get a() { return this.x; }, set a(val) { this.x = val } };",
3162 5 * kPointerSize, 3155 5 * kPointerSize,
3163 1, 3156 1,
3164 34, 3157 32,
3165 { 3158 {
3166 B(LdaConstant), U8(0), // 3159 B(LdaConstant), U8(0), //
3167 B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), // 3160 B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), //
3168 B(Star), R(0), // 3161 B(Star), R(0), //
3169 B(LdaConstant), U8(1), // 3162 B(LdaConstant), U8(1), //
3170 B(Star), R(1), // 3163 B(Star), R(1), //
3171 B(LdaConstant), U8(2), // 3164 B(CreateClosure), U8(2), U8(0), //
3172 B(CreateClosure), U8(0), //
3173 B(Star), R(2), // 3165 B(Star), R(2), //
3174 B(LdaConstant), U8(3), // 3166 B(CreateClosure), U8(3), U8(0), //
3175 B(CreateClosure), U8(0), //
3176 B(Star), R(3), // 3167 B(Star), R(3), //
3177 B(LdaZero), // 3168 B(LdaZero), //
3178 B(Star), R(4), // 3169 B(Star), R(4), //
3179 B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), // 3170 B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), //
3180 R(0), U8(5), // 3171 R(0), U8(5), //
3181 B(Ldar), R(0), // 3172 B(Ldar), R(0), //
3182 B(Return), // 3173 B(Return), //
3183 }, 3174 },
3184 4, 3175 4,
3185 {InstanceType::FIXED_ARRAY_TYPE, 3176 {InstanceType::FIXED_ARRAY_TYPE,
3186 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 3177 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
3187 InstanceType::SHARED_FUNCTION_INFO_TYPE, 3178 InstanceType::SHARED_FUNCTION_INFO_TYPE,
3188 InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3179 InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3189 {"return { set b(val) { this.y = val } };", 3180 {"return { set b(val) { this.y = val } };",
3190 5 * kPointerSize, 3181 5 * kPointerSize,
3191 1, 3182 1,
3192 31, 3183 30,
3193 { 3184 {
3194 B(LdaConstant), U8(0), // 3185 B(LdaConstant), U8(0), //
3195 B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), // 3186 B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), //
3196 B(Star), R(0), // 3187 B(Star), R(0), //
3197 B(LdaConstant), U8(1), // 3188 B(LdaConstant), U8(1), //
3198 B(Star), R(1), // 3189 B(Star), R(1), //
3199 B(LdaNull), // 3190 B(LdaNull), //
3200 B(Star), R(2), // 3191 B(Star), R(2), //
3201 B(LdaConstant), U8(2), // 3192 B(CreateClosure), U8(2), U8(0), //
3202 B(CreateClosure), U8(0), //
3203 B(Star), R(3), // 3193 B(Star), R(3), //
3204 B(LdaZero), // 3194 B(LdaZero), //
3205 B(Star), R(4), // 3195 B(Star), R(4), //
3206 B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), // 3196 B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), //
3207 R(0), U8(5), // 3197 R(0), U8(5), //
3208 B(Ldar), R(0), // 3198 B(Ldar), R(0), //
3209 B(Return), // 3199 B(Return), //
3210 }, 3200 },
3211 3, 3201 3,
3212 {InstanceType::FIXED_ARRAY_TYPE, 3202 {InstanceType::FIXED_ARRAY_TYPE,
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
3327 B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(1), U8(2), // 3317 B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(1), U8(2), //
3328 B(Ldar), R(1), // 3318 B(Ldar), R(1), //
3329 B(Return), // 3319 B(Return), //
3330 }, 3320 },
3331 2, 3321 2,
3332 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 3322 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
3333 InstanceType::FIXED_ARRAY_TYPE}}, 3323 InstanceType::FIXED_ARRAY_TYPE}},
3334 {"var n = 'name'; return { [n]: 'val', get a() { }, set a(b) {} };", 3324 {"var n = 'name'; return { [n]: 'val', get a() { }, set a(b) {} };",
3335 5 * kPointerSize, 3325 5 * kPointerSize,
3336 1, 3326 1,
3337 69, 3327 67,
3338 { 3328 {
3339 B(LdaConstant), U8(0), // 3329 B(LdaConstant), U8(0), //
3340 B(Star), R(0), // 3330 B(Star), R(0), //
3341 B(LdaConstant), U8(1), // 3331 B(LdaConstant), U8(1), //
3342 B(CreateObjectLiteral), U8(0), U8(simple_flags), // 3332 B(CreateObjectLiteral), U8(0), U8(simple_flags), //
3343 B(Star), R(1), // 3333 B(Star), R(1), //
3344 B(Ldar), R(0), // 3334 B(Ldar), R(0), //
3345 B(ToName), // 3335 B(ToName), //
3346 B(Star), R(2), // 3336 B(Star), R(2), //
3347 B(LdaConstant), U8(2), // 3337 B(LdaConstant), U8(2), //
3348 B(Star), R(3), // 3338 B(Star), R(3), //
3349 B(LdaZero), // 3339 B(LdaZero), //
3350 B(Star), R(4), // 3340 B(Star), R(4), //
3351 B(CallRuntime), U16(Runtime::kDefineDataPropertyUnchecked), R(1), // 3341 B(CallRuntime), U16(Runtime::kDefineDataPropertyUnchecked), R(1), //
3352 U8(4), // 3342 U8(4), //
3353 B(LdaConstant), U8(3), // 3343 B(LdaConstant), U8(3), //
3354 B(ToName), // 3344 B(ToName), //
3355 B(Star), R(2), // 3345 B(Star), R(2), //
3356 B(LdaConstant), U8(4), // 3346 B(CreateClosure), U8(4), U8(0), //
3357 B(CreateClosure), U8(0), //
3358 B(Star), R(3), // 3347 B(Star), R(3), //
3359 B(LdaZero), // 3348 B(LdaZero), //
3360 B(Star), R(4), // 3349 B(Star), R(4), //
3361 B(CallRuntime), U16(Runtime::kDefineGetterPropertyUnchecked), // 3350 B(CallRuntime), U16(Runtime::kDefineGetterPropertyUnchecked), //
3362 R(1), U8(4), // 3351 R(1), U8(4), //
3363 B(LdaConstant), U8(3), // 3352 B(LdaConstant), U8(3), //
3364 B(ToName), // 3353 B(ToName), //
3365 B(Star), R(2), // 3354 B(Star), R(2), //
3366 B(LdaConstant), U8(5), // 3355 B(CreateClosure), U8(5), U8(0), //
3367 B(CreateClosure), U8(0), //
3368 B(Star), R(3), // 3356 B(Star), R(3), //
3369 B(LdaZero), // 3357 B(LdaZero), //
3370 B(Star), R(4), // 3358 B(Star), R(4), //
3371 B(CallRuntime), U16(Runtime::kDefineSetterPropertyUnchecked), // 3359 B(CallRuntime), U16(Runtime::kDefineSetterPropertyUnchecked), //
3372 R(1), U8(4), // 3360 R(1), U8(4), //
3373 B(Ldar), R(1), // 3361 B(Ldar), R(1), //
3374 B(Return), // 3362 B(Return), //
3375 }, 3363 },
3376 6, 3364 6,
3377 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 3365 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
(...skipping 16 matching lines...) Expand all
3394 InitializedHandleScope handle_scope; 3382 InitializedHandleScope handle_scope;
3395 BytecodeGeneratorHelper helper; 3383 BytecodeGeneratorHelper helper;
3396 3384
3397 int has_function_flags = ObjectLiteral::kFastElements | 3385 int has_function_flags = ObjectLiteral::kFastElements |
3398 ObjectLiteral::kHasFunction | 3386 ObjectLiteral::kHasFunction |
3399 ObjectLiteral::kDisableMementos; 3387 ObjectLiteral::kDisableMementos;
3400 ExpectedSnippet<InstanceType> snippets[] = { 3388 ExpectedSnippet<InstanceType> snippets[] = {
3401 {"var a = { func: function() { } };", 3389 {"var a = { func: function() { } };",
3402 5 * kPointerSize, 3390 5 * kPointerSize,
3403 1, 3391 1,
3404 50, 3392 49,
3405 { 3393 {
3406 B(LdaConstant), U8(0), // 3394 B(LdaConstant), U8(0), //
3407 B(Star), R(1), // 3395 B(Star), R(1), //
3408 B(LdaZero), // 3396 B(LdaZero), //
3409 B(Star), R(2), // 3397 B(Star), R(2), //
3410 B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2), // 3398 B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2), //
3411 B(LdaConstant), U8(1), // 3399 B(LdaConstant), U8(1), //
3412 B(Star), R(1), // 3400 B(Star), R(1), //
3413 B(LdaZero), // 3401 B(LdaZero), //
3414 B(Star), R(2), // 3402 B(Star), R(2), //
3415 B(LdaConstant), U8(2), // 3403 B(LdaConstant), U8(2), //
3416 B(CreateObjectLiteral), U8(0), U8(has_function_flags), // 3404 B(CreateObjectLiteral), U8(0), U8(has_function_flags), //
3417 B(Star), R(4), // 3405 B(Star), R(4), //
3418 B(LdaConstant), U8(4), // 3406 B(CreateClosure), U8(4), U8(1), //
3419 B(CreateClosure), U8(1), //
3420 B(StoreICSloppy), R(4), U8(3), U8(5), // 3407 B(StoreICSloppy), R(4), U8(3), U8(5), //
3421 B(CallRuntime), U16(Runtime::kToFastProperties), R(4), U8(1), // 3408 B(CallRuntime), U16(Runtime::kToFastProperties), R(4), U8(1), //
3422 B(Ldar), R(4), // 3409 B(Ldar), R(4), //
3423 B(Star), R(3), // 3410 B(Star), R(3), //
3424 B(CallRuntime), U16(Runtime::kInitializeVarGlobal), R(1), U8(3), // 3411 B(CallRuntime), U16(Runtime::kInitializeVarGlobal), R(1), U8(3), //
3425 B(LdaUndefined), // 3412 B(LdaUndefined), //
3426 B(Return), // 3413 B(Return), //
3427 }, 3414 },
3428 5, 3415 5,
3429 {InstanceType::FIXED_ARRAY_TYPE, 3416 {InstanceType::FIXED_ARRAY_TYPE,
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
3651 3638
3652 Handle<i::TypeFeedbackVector> vector = 3639 Handle<i::TypeFeedbackVector> vector =
3653 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); 3640 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
3654 3641
3655 int closure = Register::function_closure().index(); 3642 int closure = Register::function_closure().index();
3656 int first_context_slot = Context::MIN_CONTEXT_SLOTS; 3643 int first_context_slot = Context::MIN_CONTEXT_SLOTS;
3657 ExpectedSnippet<InstanceType> snippets[] = { 3644 ExpectedSnippet<InstanceType> snippets[] = {
3658 {"var a; return function() { a = 1; };", 3645 {"var a; return function() { a = 1; };",
3659 1 * kPointerSize, 3646 1 * kPointerSize,
3660 1, 3647 1,
3661 12, 3648 11,
3662 { 3649 {
3663 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 3650 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
3664 R(closure), U8(1), // 3651 R(closure), U8(1), //
3665 B(PushContext), R(0), // 3652 B(PushContext), R(0), //
3666 B(LdaConstant), U8(0), // 3653 B(CreateClosure), U8(0), U8(0), //
3667 B(CreateClosure), U8(0), //
3668 B(Return), // 3654 B(Return), //
3669 }, 3655 },
3670 1, 3656 1,
3671 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3657 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3672 {"var a = 1; return function() { a = 2; };", 3658 {"var a = 1; return function() { a = 2; };",
3673 1 * kPointerSize, 3659 1 * kPointerSize,
3674 1, 3660 1,
3675 17, 3661 16,
3676 { 3662 {
3677 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 3663 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
3678 R(closure), U8(1), // 3664 R(closure), U8(1), //
3679 B(PushContext), R(0), // 3665 B(PushContext), R(0), //
3680 B(LdaSmi8), U8(1), // 3666 B(LdaSmi8), U8(1), //
3681 B(StaContextSlot), R(0), U8(first_context_slot), // 3667 B(StaContextSlot), R(0), U8(first_context_slot), //
3682 B(LdaConstant), U8(0), // 3668 B(CreateClosure), U8(0), U8(0), //
3683 B(CreateClosure), U8(0), //
3684 B(Return), // 3669 B(Return), //
3685 }, 3670 },
3686 1, 3671 1,
3687 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3672 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3688 {"var a = 1; var b = 2; return function() { a = 2; b = 3 };", 3673 {"var a = 1; var b = 2; return function() { a = 2; b = 3 };",
3689 1 * kPointerSize, 3674 1 * kPointerSize,
3690 1, 3675 1,
3691 22, 3676 21,
3692 { 3677 {
3693 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 3678 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
3694 R(closure), U8(1), // 3679 R(closure), U8(1), //
3695 B(PushContext), R(0), // 3680 B(PushContext), R(0), //
3696 B(LdaSmi8), U8(1), // 3681 B(LdaSmi8), U8(1), //
3697 B(StaContextSlot), R(0), U8(first_context_slot), // 3682 B(StaContextSlot), R(0), U8(first_context_slot), //
3698 B(LdaSmi8), U8(2), // 3683 B(LdaSmi8), U8(2), //
3699 B(StaContextSlot), R(0), U8(first_context_slot + 1), // 3684 B(StaContextSlot), R(0), U8(first_context_slot + 1), //
3700 B(LdaConstant), U8(0), // 3685 B(CreateClosure), U8(0), U8(0), //
3701 B(CreateClosure), U8(0), //
3702 B(Return), // 3686 B(Return), //
3703 }, 3687 },
3704 1, 3688 1,
3705 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3689 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3706 {"var a; (function() { a = 2; })(); return a;", 3690 {"var a; (function() { a = 2; })(); return a;",
3707 3 * kPointerSize, 3691 3 * kPointerSize,
3708 1, 3692 1,
3709 25, 3693 24,
3710 { 3694 {
3711 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 3695 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
3712 R(closure), U8(1), // 3696 R(closure), U8(1), //
3713 B(PushContext), R(0), // 3697 B(PushContext), R(0), //
3714 B(LdaUndefined), // 3698 B(LdaUndefined), //
3715 B(Star), R(2), // 3699 B(Star), R(2), //
3716 B(LdaConstant), U8(0), // 3700 B(CreateClosure), U8(0), U8(0), //
3717 B(CreateClosure), U8(0), //
3718 B(Star), R(1), // 3701 B(Star), R(1), //
3719 B(Call), R(1), R(2), U8(0), U8(vector->GetIndex(slot)), // 3702 B(Call), R(1), R(2), U8(0), U8(vector->GetIndex(slot)), //
3720 B(LdaContextSlot), R(0), U8(first_context_slot), // 3703 B(LdaContextSlot), R(0), U8(first_context_slot), //
3721 B(Return), // 3704 B(Return), //
3722 }, 3705 },
3723 1, 3706 1,
3724 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3707 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3725 {"'use strict'; let a = 1; { let b = 2; return function() { a + b; }; }", 3708 {"'use strict'; let a = 1; { let b = 2; return function() { a + b; }; }",
3726 4 * kPointerSize, 3709 4 * kPointerSize,
3727 1, 3710 1,
3728 45, 3711 44,
3729 { 3712 {
3730 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 3713 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
3731 R(closure), U8(1), // 3714 R(closure), U8(1), //
3732 B(PushContext), R(0), // 3715 B(PushContext), R(0), //
3733 B(LdaTheHole), // 3716 B(LdaTheHole), //
3734 B(StaContextSlot), R(0), U8(first_context_slot), // 3717 B(StaContextSlot), R(0), U8(first_context_slot), //
3735 B(LdaSmi8), U8(1), // 3718 B(LdaSmi8), U8(1), //
3736 B(StaContextSlot), R(0), U8(first_context_slot), // 3719 B(StaContextSlot), R(0), U8(first_context_slot), //
3737 B(LdaConstant), U8(0), // 3720 B(LdaConstant), U8(0), //
3738 B(Star), R(2), // 3721 B(Star), R(2), //
3739 B(Ldar), R(closure), // 3722 B(Ldar), R(closure), //
3740 B(Star), R(3), // 3723 B(Star), R(3), //
3741 B(CallRuntime), U16(Runtime::kPushBlockContext), R(2), U8(2), // 3724 B(CallRuntime), U16(Runtime::kPushBlockContext), R(2), U8(2), //
3742 B(PushContext), R(1), // 3725 B(PushContext), R(1), //
3743 B(LdaTheHole), // 3726 B(LdaTheHole), //
3744 B(StaContextSlot), R(1), U8(first_context_slot), // 3727 B(StaContextSlot), R(1), U8(first_context_slot), //
3745 B(LdaSmi8), U8(2), // 3728 B(LdaSmi8), U8(2), //
3746 B(StaContextSlot), R(1), U8(first_context_slot), // 3729 B(StaContextSlot), R(1), U8(first_context_slot), //
3747 B(LdaConstant), U8(1), // 3730 B(CreateClosure), U8(1), U8(0), //
3748 B(CreateClosure), U8(0), //
3749 B(Return), // 3731 B(Return), //
3750 }, 3732 },
3751 2, 3733 2,
3752 {InstanceType::FIXED_ARRAY_TYPE, 3734 {InstanceType::FIXED_ARRAY_TYPE,
3753 InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3735 InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3754 }; 3736 };
3755 3737
3756 for (size_t i = 0; i < arraysize(snippets); i++) { 3738 for (size_t i = 0; i < arraysize(snippets); i++) {
3757 Handle<BytecodeArray> bytecode_array = 3739 Handle<BytecodeArray> bytecode_array =
3758 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 3740 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
3759 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 3741 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
3760 } 3742 }
3761 } 3743 }
3762 3744
3763 3745
3764 TEST(ContextParameters) { 3746 TEST(ContextParameters) {
3765 InitializedHandleScope handle_scope; 3747 InitializedHandleScope handle_scope;
3766 BytecodeGeneratorHelper helper; 3748 BytecodeGeneratorHelper helper;
3767 3749
3768 int closure = Register::function_closure().index(); 3750 int closure = Register::function_closure().index();
3769 int first_context_slot = Context::MIN_CONTEXT_SLOTS; 3751 int first_context_slot = Context::MIN_CONTEXT_SLOTS;
3770 3752
3771 ExpectedSnippet<InstanceType> snippets[] = { 3753 ExpectedSnippet<InstanceType> snippets[] = {
3772 {"function f(arg1) { return function() { arg1 = 2; }; }", 3754 {"function f(arg1) { return function() { arg1 = 2; }; }",
3773 1 * kPointerSize, 3755 1 * kPointerSize,
3774 2, 3756 2,
3775 17, 3757 16,
3776 { 3758 {
3777 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 3759 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
3778 R(closure), U8(1), // 3760 R(closure), U8(1), //
3779 B(PushContext), R(0), // 3761 B(PushContext), R(0), //
3780 B(Ldar), R(helper.kLastParamIndex), // 3762 B(Ldar), R(helper.kLastParamIndex), //
3781 B(StaContextSlot), R(0), U8(first_context_slot), // 3763 B(StaContextSlot), R(0), U8(first_context_slot), //
3782 B(LdaConstant), U8(0), // 3764 B(CreateClosure), U8(0), U8(0), //
3783 B(CreateClosure), U8(0), //
3784 B(Return), // 3765 B(Return), //
3785 }, 3766 },
3786 1, 3767 1,
3787 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3768 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3788 {"function f(arg1) { var a = function() { arg1 = 2; }; return arg1; }", 3769 {"function f(arg1) { var a = function() { arg1 = 2; }; return arg1; }",
3789 2 * kPointerSize, 3770 2 * kPointerSize,
3790 2, 3771 2,
3791 22, 3772 21,
3792 { 3773 {
3793 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 3774 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
3794 R(closure), U8(1), // 3775 R(closure), U8(1), //
3795 B(PushContext), R(1), // 3776 B(PushContext), R(1), //
3796 B(Ldar), R(helper.kLastParamIndex), // 3777 B(Ldar), R(helper.kLastParamIndex), //
3797 B(StaContextSlot), R(1), U8(first_context_slot), // 3778 B(StaContextSlot), R(1), U8(first_context_slot), //
3798 B(LdaConstant), U8(0), // 3779 B(CreateClosure), U8(0), U8(0), //
3799 B(CreateClosure), U8(0), //
3800 B(Star), R(0), // 3780 B(Star), R(0), //
3801 B(LdaContextSlot), R(1), U8(first_context_slot), // 3781 B(LdaContextSlot), R(1), U8(first_context_slot), //
3802 B(Return), // 3782 B(Return), //
3803 }, 3783 },
3804 1, 3784 1,
3805 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3785 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3806 {"function f(a1, a2, a3, a4) { return function() { a1 = a3; }; }", 3786 {"function f(a1, a2, a3, a4) { return function() { a1 = a3; }; }",
3807 1 * kPointerSize, 3787 1 * kPointerSize,
3808 5, 3788 5,
3809 22, 3789 21,
3810 { 3790 {
3811 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 3791 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
3812 R(closure), U8(1), // 3792 R(closure), U8(1), //
3813 B(PushContext), R(0), // 3793 B(PushContext), R(0), //
3814 B(Ldar), R(helper.kLastParamIndex - 3), // 3794 B(Ldar), R(helper.kLastParamIndex - 3), //
3815 B(StaContextSlot), R(0), U8(first_context_slot + 1), // 3795 B(StaContextSlot), R(0), U8(first_context_slot + 1), //
3816 B(Ldar), R(helper.kLastParamIndex -1), // 3796 B(Ldar), R(helper.kLastParamIndex -1), //
3817 B(StaContextSlot), R(0), U8(first_context_slot), // 3797 B(StaContextSlot), R(0), U8(first_context_slot), //
3818 B(LdaConstant), U8(0), // 3798 B(CreateClosure), U8(0), U8(0), //
3819 B(CreateClosure), U8(0), //
3820 B(Return), // 3799 B(Return), //
3821 }, 3800 },
3822 1, 3801 1,
3823 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3802 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3824 {"function f() { var self = this; return function() { self = 2; }; }", 3803 {"function f() { var self = this; return function() { self = 2; }; }",
3825 1 * kPointerSize, 3804 1 * kPointerSize,
3826 1, 3805 1,
3827 17, 3806 16,
3828 { 3807 {
3829 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 3808 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
3830 R(closure), U8(1), // 3809 R(closure), U8(1), //
3831 B(PushContext), R(0), // 3810 B(PushContext), R(0), //
3832 B(Ldar), R(helper.kLastParamIndex), // 3811 B(Ldar), R(helper.kLastParamIndex), //
3833 B(StaContextSlot), R(0), U8(first_context_slot), // 3812 B(StaContextSlot), R(0), U8(first_context_slot), //
3834 B(LdaConstant), U8(0), // 3813 B(CreateClosure), U8(0), U8(0), //
3835 B(CreateClosure), U8(0), //
3836 B(Return), // 3814 B(Return), //
3837 }, 3815 },
3838 1, 3816 1,
3839 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3817 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3840 }; 3818 };
3841 3819
3842 for (size_t i = 0; i < arraysize(snippets); i++) { 3820 for (size_t i = 0; i < arraysize(snippets); i++) {
3843 Handle<BytecodeArray> bytecode_array = 3821 Handle<BytecodeArray> bytecode_array =
3844 helper.MakeBytecodeForFunction(snippets[i].code_snippet); 3822 helper.MakeBytecodeForFunction(snippets[i].code_snippet);
3845 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 3823 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
4063 B(Inc), // 4041 B(Inc), //
4064 B(KeyedStoreICSloppy), R(1), R(2), U8(vector->GetIndex(slot2)), // 4042 B(KeyedStoreICSloppy), R(1), R(2), U8(vector->GetIndex(slot2)), //
4065 B(Return), // 4043 B(Return), //
4066 }, 4044 },
4067 2, 4045 2,
4068 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 4046 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
4069 InstanceType::FIXED_ARRAY_TYPE}}, 4047 InstanceType::FIXED_ARRAY_TYPE}},
4070 {"var a = 1; var b = function() { return a }; return ++a;", 4048 {"var a = 1; var b = function() { return a }; return ++a;",
4071 2 * kPointerSize, 4049 2 * kPointerSize,
4072 1, 4050 1,
4073 27, 4051 26,
4074 { 4052 {
4075 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // 4053 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
4076 U8(1), // 4054 U8(1), //
4077 B(PushContext), R(1), // 4055 B(PushContext), R(1), //
4078 B(LdaSmi8), U8(1), // 4056 B(LdaSmi8), U8(1), //
4079 B(StaContextSlot), R(1), U8(first_context_slot), // 4057 B(StaContextSlot), R(1), U8(first_context_slot), //
4080 B(LdaConstant), U8(0), // 4058 B(CreateClosure), U8(0), U8(0), //
4081 B(CreateClosure), U8(0), //
4082 B(Star), R(0), // 4059 B(Star), R(0), //
4083 B(LdaContextSlot), R(1), U8(first_context_slot), // 4060 B(LdaContextSlot), R(1), U8(first_context_slot), //
4084 B(ToNumber), // 4061 B(ToNumber), //
4085 B(Inc), // 4062 B(Inc), //
4086 B(StaContextSlot), R(1), U8(first_context_slot), // 4063 B(StaContextSlot), R(1), U8(first_context_slot), //
4087 B(Return), // 4064 B(Return), //
4088 }, 4065 },
4089 1, 4066 1,
4090 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 4067 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
4091 {"var a = 1; var b = function() { return a }; return a--;", 4068 {"var a = 1; var b = function() { return a }; return a--;",
4092 3 * kPointerSize, 4069 3 * kPointerSize,
4093 1, 4070 1,
4094 31, 4071 30,
4095 { 4072 {
4096 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // 4073 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
4097 U8(1), // 4074 U8(1), //
4098 B(PushContext), R(1), // 4075 B(PushContext), R(1), //
4099 B(LdaSmi8), U8(1), // 4076 B(LdaSmi8), U8(1), //
4100 B(StaContextSlot), R(1), U8(first_context_slot), // 4077 B(StaContextSlot), R(1), U8(first_context_slot), //
4101 B(LdaConstant), U8(0), // 4078 B(CreateClosure), U8(0), U8(0), //
4102 B(CreateClosure), U8(0), //
4103 B(Star), R(0), // 4079 B(Star), R(0), //
4104 B(LdaContextSlot), R(1), U8(first_context_slot), // 4080 B(LdaContextSlot), R(1), U8(first_context_slot), //
4105 B(ToNumber), // 4081 B(ToNumber), //
4106 B(Star), R(2), // 4082 B(Star), R(2), //
4107 B(Dec), // 4083 B(Dec), //
4108 B(StaContextSlot), R(1), U8(first_context_slot), // 4084 B(StaContextSlot), R(1), U8(first_context_slot), //
4109 B(Ldar), R(2), // 4085 B(Ldar), R(2), //
4110 B(Return), // 4086 B(Return), //
4111 }, 4087 },
4112 1, 4088 1,
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
4302 B(BitwiseXor), R(2), // 4278 B(BitwiseXor), R(2), //
4303 B(KeyedStoreICSloppy), R(0), R(1), U8(vector->GetIndex(slot2)), // 4279 B(KeyedStoreICSloppy), R(0), R(1), U8(vector->GetIndex(slot2)), //
4304 B(LdaUndefined), // 4280 B(LdaUndefined), //
4305 B(Return), // 4281 B(Return), //
4306 }, 4282 },
4307 1, 4283 1,
4308 {InstanceType::FIXED_ARRAY_TYPE}}, 4284 {InstanceType::FIXED_ARRAY_TYPE}},
4309 {"var a = 1; (function f() { return a; }); a |= 24;", 4285 {"var a = 1; (function f() { return a; }); a |= 24;",
4310 2 * kPointerSize, 4286 2 * kPointerSize,
4311 1, 4287 1,
4312 30, 4288 29,
4313 { 4289 {
4314 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // 4290 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
4315 U8(1), // 4291 U8(1), //
4316 B(PushContext), R(0), // 4292 B(PushContext), R(0), //
4317 B(LdaSmi8), U8(1), // 4293 B(LdaSmi8), U8(1), //
4318 B(StaContextSlot), R(0), U8(first_context_slot), // 4294 B(StaContextSlot), R(0), U8(first_context_slot), //
4319 B(LdaConstant), U8(0), // 4295 B(CreateClosure), U8(0), U8(0), //
4320 B(CreateClosure), U8(0), //
4321 B(LdaContextSlot), R(0), U8(first_context_slot), // 4296 B(LdaContextSlot), R(0), U8(first_context_slot), //
4322 B(Star), R(1), // 4297 B(Star), R(1), //
4323 B(LdaSmi8), U8(24), // 4298 B(LdaSmi8), U8(24), //
4324 B(BitwiseOr), R(1), // 4299 B(BitwiseOr), R(1), //
4325 B(StaContextSlot), R(0), U8(first_context_slot), // 4300 B(StaContextSlot), R(0), U8(first_context_slot), //
4326 B(LdaUndefined), // 4301 B(LdaUndefined), //
4327 B(Return), // 4302 B(Return), //
4328 }, 4303 },
4329 1, 4304 1,
4330 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 4305 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
(...skipping 1159 matching lines...) Expand 10 before | Expand all | Expand 10 after
5490 for (size_t i = 0; i < arraysize(snippets); i++) { 5465 for (size_t i = 0; i < arraysize(snippets); i++) {
5491 Handle<BytecodeArray> bytecode_array = 5466 Handle<BytecodeArray> bytecode_array =
5492 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 5467 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
5493 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 5468 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
5494 } 5469 }
5495 } 5470 }
5496 5471
5497 } // namespace interpreter 5472 } // namespace interpreter
5498 } // namespace internal 5473 } // namespace internal
5499 } // namespace v8 5474 } // namespace v8
OLDNEW
« no previous file with comments | « test/cctest/compiler/test-run-bytecode-graph-builder.cc ('k') | test/unittests/interpreter/bytecode-array-builder-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698