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

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

Issue 1475793003: 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 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
3097 B(StoreICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), // 3093 B(StoreICSloppy), R(1), U8(1), U8(vector->GetIndex(slot1)), //
3098 B(Ldar), R(1), // 3094 B(Ldar), R(1), //
3099 B(Return), // 3095 B(Return), //
3100 }, 3096 },
3101 2, 3097 2,
3102 {InstanceType::FIXED_ARRAY_TYPE, 3098 {InstanceType::FIXED_ARRAY_TYPE,
3103 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, 3099 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}},
3104 {"return { func: function() { } };", 3100 {"return { func: function() { } };",
3105 1 * kPointerSize, 3101 1 * kPointerSize,
3106 1, 3102 1,
3107 18, 3103 17,
3108 { 3104 {
3109 B(LdaConstant), U8(0), // 3105 B(LdaConstant), U8(0), //
3110 B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), // 3106 B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), //
3111 B(Star), R(0), // 3107 B(Star), R(0), //
3112 B(LdaConstant), U8(2), // 3108 B(CreateClosure), U8(2), U8(0), //
3113 B(CreateClosure), U8(0), //
3114 B(StoreICSloppy), R(0), U8(1), U8(vector->GetIndex(slot1)), // 3109 B(StoreICSloppy), R(0), U8(1), U8(vector->GetIndex(slot1)), //
3115 B(Ldar), R(0), // 3110 B(Ldar), R(0), //
3116 B(Return), // 3111 B(Return), //
3117 }, 3112 },
3118 3, 3113 3,
3119 {InstanceType::FIXED_ARRAY_TYPE, 3114 {InstanceType::FIXED_ARRAY_TYPE,
3120 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 3115 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
3121 InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3116 InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3122 {"return { func(a) { return a; } };", 3117 {"return { func(a) { return a; } };",
3123 1 * kPointerSize, 3118 1 * kPointerSize,
3124 1, 3119 1,
3125 18, 3120 17,
3126 { 3121 {
3127 B(LdaConstant), U8(0), // 3122 B(LdaConstant), U8(0), //
3128 B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), // 3123 B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), //
3129 B(Star), R(0), // 3124 B(Star), R(0), //
3130 B(LdaConstant), U8(2), // 3125 B(CreateClosure), U8(2), U8(0), //
3131 B(CreateClosure), U8(0), //
3132 B(StoreICSloppy), R(0), U8(1), U8(vector->GetIndex(slot1)), // 3126 B(StoreICSloppy), R(0), U8(1), U8(vector->GetIndex(slot1)), //
3133 B(Ldar), R(0), // 3127 B(Ldar), R(0), //
3134 B(Return), // 3128 B(Return), //
3135 }, 3129 },
3136 3, 3130 3,
3137 {InstanceType::FIXED_ARRAY_TYPE, 3131 {InstanceType::FIXED_ARRAY_TYPE,
3138 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 3132 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
3139 InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3133 InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3140 {"return { get a() { return 2; } };", 3134 {"return { get a() { return 2; } };",
3141 5 * kPointerSize, 3135 5 * kPointerSize,
3142 1, 3136 1,
3143 31, 3137 30,
3144 { 3138 {
3145 B(LdaConstant), U8(0), // 3139 B(LdaConstant), U8(0), //
3146 B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), // 3140 B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), //
3147 B(Star), R(0), // 3141 B(Star), R(0), //
3148 B(LdaConstant), U8(1), // 3142 B(LdaConstant), U8(1), //
3149 B(Star), R(1), // 3143 B(Star), R(1), //
3150 B(LdaConstant), U8(2), // 3144 B(CreateClosure), U8(2), U8(0), //
3151 B(CreateClosure), U8(0), //
3152 B(Star), R(2), // 3145 B(Star), R(2), //
3153 B(LdaNull), // 3146 B(LdaNull), //
3154 B(Star), R(3), // 3147 B(Star), R(3), //
3155 B(LdaZero), // 3148 B(LdaZero), //
3156 B(Star), R(4), // 3149 B(Star), R(4), //
3157 B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), // 3150 B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), //
3158 R(0), U8(5), // 3151 R(0), U8(5), //
3159 B(Ldar), R(0), // 3152 B(Ldar), R(0), //
3160 B(Return), // 3153 B(Return), //
3161 }, 3154 },
3162 3, 3155 3,
3163 {InstanceType::FIXED_ARRAY_TYPE, 3156 {InstanceType::FIXED_ARRAY_TYPE,
3164 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 3157 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
3165 InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3158 InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3166 {"return { get a() { return this.x; }, set a(val) { this.x = val } };", 3159 {"return { get a() { return this.x; }, set a(val) { this.x = val } };",
3167 5 * kPointerSize, 3160 5 * kPointerSize,
3168 1, 3161 1,
3169 34, 3162 32,
3170 { 3163 {
3171 B(LdaConstant), U8(0), // 3164 B(LdaConstant), U8(0), //
3172 B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), // 3165 B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), //
3173 B(Star), R(0), // 3166 B(Star), R(0), //
3174 B(LdaConstant), U8(1), // 3167 B(LdaConstant), U8(1), //
3175 B(Star), R(1), // 3168 B(Star), R(1), //
3176 B(LdaConstant), U8(2), // 3169 B(CreateClosure), U8(2), U8(0), //
3177 B(CreateClosure), U8(0), //
3178 B(Star), R(2), // 3170 B(Star), R(2), //
3179 B(LdaConstant), U8(3), // 3171 B(CreateClosure), U8(3), U8(0), //
3180 B(CreateClosure), U8(0), //
3181 B(Star), R(3), // 3172 B(Star), R(3), //
3182 B(LdaZero), // 3173 B(LdaZero), //
3183 B(Star), R(4), // 3174 B(Star), R(4), //
3184 B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), // 3175 B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), //
3185 R(0), U8(5), // 3176 R(0), U8(5), //
3186 B(Ldar), R(0), // 3177 B(Ldar), R(0), //
3187 B(Return), // 3178 B(Return), //
3188 }, 3179 },
3189 4, 3180 4,
3190 {InstanceType::FIXED_ARRAY_TYPE, 3181 {InstanceType::FIXED_ARRAY_TYPE,
3191 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 3182 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
3192 InstanceType::SHARED_FUNCTION_INFO_TYPE, 3183 InstanceType::SHARED_FUNCTION_INFO_TYPE,
3193 InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3184 InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3194 {"return { set b(val) { this.y = val } };", 3185 {"return { set b(val) { this.y = val } };",
3195 5 * kPointerSize, 3186 5 * kPointerSize,
3196 1, 3187 1,
3197 31, 3188 30,
3198 { 3189 {
3199 B(LdaConstant), U8(0), // 3190 B(LdaConstant), U8(0), //
3200 B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), // 3191 B(CreateObjectLiteral), U8(0), U8(deep_elements_flags), //
3201 B(Star), R(0), // 3192 B(Star), R(0), //
3202 B(LdaConstant), U8(1), // 3193 B(LdaConstant), U8(1), //
3203 B(Star), R(1), // 3194 B(Star), R(1), //
3204 B(LdaNull), // 3195 B(LdaNull), //
3205 B(Star), R(2), // 3196 B(Star), R(2), //
3206 B(LdaConstant), U8(2), // 3197 B(CreateClosure), U8(2), U8(0), //
3207 B(CreateClosure), U8(0), //
3208 B(Star), R(3), // 3198 B(Star), R(3), //
3209 B(LdaZero), // 3199 B(LdaZero), //
3210 B(Star), R(4), // 3200 B(Star), R(4), //
3211 B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), // 3201 B(CallRuntime), U16(Runtime::kDefineAccessorPropertyUnchecked), //
3212 R(0), U8(5), // 3202 R(0), U8(5), //
3213 B(Ldar), R(0), // 3203 B(Ldar), R(0), //
3214 B(Return), // 3204 B(Return), //
3215 }, 3205 },
3216 3, 3206 3,
3217 {InstanceType::FIXED_ARRAY_TYPE, 3207 {InstanceType::FIXED_ARRAY_TYPE,
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
3332 B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(1), U8(2), // 3322 B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(1), U8(2), //
3333 B(Ldar), R(1), // 3323 B(Ldar), R(1), //
3334 B(Return), // 3324 B(Return), //
3335 }, 3325 },
3336 2, 3326 2,
3337 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 3327 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
3338 InstanceType::FIXED_ARRAY_TYPE}}, 3328 InstanceType::FIXED_ARRAY_TYPE}},
3339 {"var n = 'name'; return { [n]: 'val', get a() { }, set a(b) {} };", 3329 {"var n = 'name'; return { [n]: 'val', get a() { }, set a(b) {} };",
3340 5 * kPointerSize, 3330 5 * kPointerSize,
3341 1, 3331 1,
3342 69, 3332 67,
3343 { 3333 {
3344 B(LdaConstant), U8(0), // 3334 B(LdaConstant), U8(0), //
3345 B(Star), R(0), // 3335 B(Star), R(0), //
3346 B(LdaConstant), U8(1), // 3336 B(LdaConstant), U8(1), //
3347 B(CreateObjectLiteral), U8(0), U8(simple_flags), // 3337 B(CreateObjectLiteral), U8(0), U8(simple_flags), //
3348 B(Star), R(1), // 3338 B(Star), R(1), //
3349 B(Ldar), R(0), // 3339 B(Ldar), R(0), //
3350 B(ToName), // 3340 B(ToName), //
3351 B(Star), R(2), // 3341 B(Star), R(2), //
3352 B(LdaConstant), U8(2), // 3342 B(LdaConstant), U8(2), //
3353 B(Star), R(3), // 3343 B(Star), R(3), //
3354 B(LdaZero), // 3344 B(LdaZero), //
3355 B(Star), R(4), // 3345 B(Star), R(4), //
3356 B(CallRuntime), U16(Runtime::kDefineDataPropertyUnchecked), R(1), // 3346 B(CallRuntime), U16(Runtime::kDefineDataPropertyUnchecked), R(1), //
3357 U8(4), // 3347 U8(4), //
3358 B(LdaConstant), U8(3), // 3348 B(LdaConstant), U8(3), //
3359 B(ToName), // 3349 B(ToName), //
3360 B(Star), R(2), // 3350 B(Star), R(2), //
3361 B(LdaConstant), U8(4), // 3351 B(CreateClosure), U8(4), U8(0), //
3362 B(CreateClosure), U8(0), //
3363 B(Star), R(3), // 3352 B(Star), R(3), //
3364 B(LdaZero), // 3353 B(LdaZero), //
3365 B(Star), R(4), // 3354 B(Star), R(4), //
3366 B(CallRuntime), U16(Runtime::kDefineGetterPropertyUnchecked), // 3355 B(CallRuntime), U16(Runtime::kDefineGetterPropertyUnchecked), //
3367 R(1), U8(4), // 3356 R(1), U8(4), //
3368 B(LdaConstant), U8(3), // 3357 B(LdaConstant), U8(3), //
3369 B(ToName), // 3358 B(ToName), //
3370 B(Star), R(2), // 3359 B(Star), R(2), //
3371 B(LdaConstant), U8(5), // 3360 B(CreateClosure), U8(5), U8(0), //
3372 B(CreateClosure), U8(0), //
3373 B(Star), R(3), // 3361 B(Star), R(3), //
3374 B(LdaZero), // 3362 B(LdaZero), //
3375 B(Star), R(4), // 3363 B(Star), R(4), //
3376 B(CallRuntime), U16(Runtime::kDefineSetterPropertyUnchecked), // 3364 B(CallRuntime), U16(Runtime::kDefineSetterPropertyUnchecked), //
3377 R(1), U8(4), // 3365 R(1), U8(4), //
3378 B(Ldar), R(1), // 3366 B(Ldar), R(1), //
3379 B(Return), // 3367 B(Return), //
3380 }, 3368 },
3381 6, 3369 6,
3382 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 3370 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
(...skipping 16 matching lines...) Expand all
3399 InitializedHandleScope handle_scope; 3387 InitializedHandleScope handle_scope;
3400 BytecodeGeneratorHelper helper; 3388 BytecodeGeneratorHelper helper;
3401 3389
3402 int has_function_flags = ObjectLiteral::kFastElements | 3390 int has_function_flags = ObjectLiteral::kFastElements |
3403 ObjectLiteral::kHasFunction | 3391 ObjectLiteral::kHasFunction |
3404 ObjectLiteral::kDisableMementos; 3392 ObjectLiteral::kDisableMementos;
3405 ExpectedSnippet<InstanceType> snippets[] = { 3393 ExpectedSnippet<InstanceType> snippets[] = {
3406 {"var a = { func: function() { } };", 3394 {"var a = { func: function() { } };",
3407 5 * kPointerSize, 3395 5 * kPointerSize,
3408 1, 3396 1,
3409 50, 3397 49,
3410 { 3398 {
3411 B(LdaConstant), U8(0), // 3399 B(LdaConstant), U8(0), //
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(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2), // 3403 B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2), //
3416 B(LdaConstant), U8(1), // 3404 B(LdaConstant), U8(1), //
3417 B(Star), R(1), // 3405 B(Star), R(1), //
3418 B(LdaZero), // 3406 B(LdaZero), //
3419 B(Star), R(2), // 3407 B(Star), R(2), //
3420 B(LdaConstant), U8(2), // 3408 B(LdaConstant), U8(2), //
3421 B(CreateObjectLiteral), U8(0), U8(has_function_flags), // 3409 B(CreateObjectLiteral), U8(0), U8(has_function_flags), //
3422 B(Star), R(4), // 3410 B(Star), R(4), //
3423 B(LdaConstant), U8(4), // 3411 B(CreateClosure), U8(4), U8(1), //
3424 B(CreateClosure), U8(1), //
3425 B(StoreICSloppy), R(4), U8(3), U8(5), // 3412 B(StoreICSloppy), R(4), U8(3), U8(5), //
3426 B(CallRuntime), U16(Runtime::kToFastProperties), R(4), U8(1), // 3413 B(CallRuntime), U16(Runtime::kToFastProperties), R(4), U8(1), //
3427 B(Ldar), R(4), // 3414 B(Ldar), R(4), //
3428 B(Star), R(3), // 3415 B(Star), R(3), //
3429 B(CallRuntime), U16(Runtime::kInitializeVarGlobal), R(1), U8(3), // 3416 B(CallRuntime), U16(Runtime::kInitializeVarGlobal), R(1), U8(3), //
3430 B(LdaUndefined), // 3417 B(LdaUndefined), //
3431 B(Return), // 3418 B(Return), //
3432 }, 3419 },
3433 5, 3420 5,
3434 {InstanceType::FIXED_ARRAY_TYPE, 3421 {InstanceType::FIXED_ARRAY_TYPE,
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
3656 3643
3657 Handle<i::TypeFeedbackVector> vector = 3644 Handle<i::TypeFeedbackVector> vector =
3658 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); 3645 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec);
3659 3646
3660 int closure = Register::function_closure().index(); 3647 int closure = Register::function_closure().index();
3661 int first_context_slot = Context::MIN_CONTEXT_SLOTS; 3648 int first_context_slot = Context::MIN_CONTEXT_SLOTS;
3662 ExpectedSnippet<InstanceType> snippets[] = { 3649 ExpectedSnippet<InstanceType> snippets[] = {
3663 {"var a; return function() { a = 1; };", 3650 {"var a; return function() { a = 1; };",
3664 1 * kPointerSize, 3651 1 * kPointerSize,
3665 1, 3652 1,
3666 12, 3653 11,
3667 { 3654 {
3668 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 3655 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
3669 R(closure), U8(1), // 3656 R(closure), U8(1), //
3670 B(PushContext), R(0), // 3657 B(PushContext), R(0), //
3671 B(LdaConstant), U8(0), // 3658 B(CreateClosure), U8(0), U8(0), //
3672 B(CreateClosure), U8(0), //
3673 B(Return), // 3659 B(Return), //
3674 }, 3660 },
3675 1, 3661 1,
3676 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3662 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3677 {"var a = 1; return function() { a = 2; };", 3663 {"var a = 1; return function() { a = 2; };",
3678 1 * kPointerSize, 3664 1 * kPointerSize,
3679 1, 3665 1,
3680 17, 3666 16,
3681 { 3667 {
3682 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 3668 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
3683 R(closure), U8(1), // 3669 R(closure), U8(1), //
3684 B(PushContext), R(0), // 3670 B(PushContext), R(0), //
3685 B(LdaSmi8), U8(1), // 3671 B(LdaSmi8), U8(1), //
3686 B(StaContextSlot), R(0), U8(first_context_slot), // 3672 B(StaContextSlot), R(0), U8(first_context_slot), //
3687 B(LdaConstant), U8(0), // 3673 B(CreateClosure), U8(0), U8(0), //
3688 B(CreateClosure), U8(0), //
3689 B(Return), // 3674 B(Return), //
3690 }, 3675 },
3691 1, 3676 1,
3692 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3677 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3693 {"var a = 1; var b = 2; return function() { a = 2; b = 3 };", 3678 {"var a = 1; var b = 2; return function() { a = 2; b = 3 };",
3694 1 * kPointerSize, 3679 1 * kPointerSize,
3695 1, 3680 1,
3696 22, 3681 21,
3697 { 3682 {
3698 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 3683 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
3699 R(closure), U8(1), // 3684 R(closure), U8(1), //
3700 B(PushContext), R(0), // 3685 B(PushContext), R(0), //
3701 B(LdaSmi8), U8(1), // 3686 B(LdaSmi8), U8(1), //
3702 B(StaContextSlot), R(0), U8(first_context_slot), // 3687 B(StaContextSlot), R(0), U8(first_context_slot), //
3703 B(LdaSmi8), U8(2), // 3688 B(LdaSmi8), U8(2), //
3704 B(StaContextSlot), R(0), U8(first_context_slot + 1), // 3689 B(StaContextSlot), R(0), U8(first_context_slot + 1), //
3705 B(LdaConstant), U8(0), // 3690 B(CreateClosure), U8(0), U8(0), //
3706 B(CreateClosure), U8(0), //
3707 B(Return), // 3691 B(Return), //
3708 }, 3692 },
3709 1, 3693 1,
3710 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3694 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3711 {"var a; (function() { a = 2; })(); return a;", 3695 {"var a; (function() { a = 2; })(); return a;",
3712 3 * kPointerSize, 3696 3 * kPointerSize,
3713 1, 3697 1,
3714 25, 3698 24,
3715 { 3699 {
3716 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 3700 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
3717 R(closure), U8(1), // 3701 R(closure), U8(1), //
3718 B(PushContext), R(0), // 3702 B(PushContext), R(0), //
3719 B(LdaUndefined), // 3703 B(LdaUndefined), //
3720 B(Star), R(2), // 3704 B(Star), R(2), //
3721 B(LdaConstant), U8(0), // 3705 B(CreateClosure), U8(0), U8(0), //
3722 B(CreateClosure), U8(0), //
3723 B(Star), R(1), // 3706 B(Star), R(1), //
3724 B(Call), R(1), R(2), U8(0), U8(vector->GetIndex(slot)), // 3707 B(Call), R(1), R(2), U8(0), U8(vector->GetIndex(slot)), //
3725 B(LdaContextSlot), R(0), U8(first_context_slot), // 3708 B(LdaContextSlot), R(0), U8(first_context_slot), //
3726 B(Return), // 3709 B(Return), //
3727 }, 3710 },
3728 1, 3711 1,
3729 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3712 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3730 {"'use strict'; let a = 1; { let b = 2; return function() { a + b; }; }", 3713 {"'use strict'; let a = 1; { let b = 2; return function() { a + b; }; }",
3731 4 * kPointerSize, 3714 4 * kPointerSize,
3732 1, 3715 1,
3733 45, 3716 44,
3734 { 3717 {
3735 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 3718 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
3736 R(closure), U8(1), // 3719 R(closure), U8(1), //
3737 B(PushContext), R(0), // 3720 B(PushContext), R(0), //
3738 B(LdaTheHole), // 3721 B(LdaTheHole), //
3739 B(StaContextSlot), R(0), U8(first_context_slot), // 3722 B(StaContextSlot), R(0), U8(first_context_slot), //
3740 B(LdaSmi8), U8(1), // 3723 B(LdaSmi8), U8(1), //
3741 B(StaContextSlot), R(0), U8(first_context_slot), // 3724 B(StaContextSlot), R(0), U8(first_context_slot), //
3742 B(LdaConstant), U8(0), // 3725 B(LdaConstant), U8(0), //
3743 B(Star), R(2), // 3726 B(Star), R(2), //
3744 B(Ldar), R(closure), // 3727 B(Ldar), R(closure), //
3745 B(Star), R(3), // 3728 B(Star), R(3), //
3746 B(CallRuntime), U16(Runtime::kPushBlockContext), R(2), U8(2), // 3729 B(CallRuntime), U16(Runtime::kPushBlockContext), R(2), U8(2), //
3747 B(PushContext), R(1), // 3730 B(PushContext), R(1), //
3748 B(LdaTheHole), // 3731 B(LdaTheHole), //
3749 B(StaContextSlot), R(1), U8(first_context_slot), // 3732 B(StaContextSlot), R(1), U8(first_context_slot), //
3750 B(LdaSmi8), U8(2), // 3733 B(LdaSmi8), U8(2), //
3751 B(StaContextSlot), R(1), U8(first_context_slot), // 3734 B(StaContextSlot), R(1), U8(first_context_slot), //
3752 B(LdaConstant), U8(1), // 3735 B(CreateClosure), U8(1), U8(0), //
3753 B(CreateClosure), U8(0), //
3754 B(Return), // 3736 B(Return), //
3755 }, 3737 },
3756 2, 3738 2,
3757 {InstanceType::FIXED_ARRAY_TYPE, 3739 {InstanceType::FIXED_ARRAY_TYPE,
3758 InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3740 InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3759 }; 3741 };
3760 3742
3761 for (size_t i = 0; i < arraysize(snippets); i++) { 3743 for (size_t i = 0; i < arraysize(snippets); i++) {
3762 Handle<BytecodeArray> bytecode_array = 3744 Handle<BytecodeArray> bytecode_array =
3763 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 3745 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
3764 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 3746 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
3765 } 3747 }
3766 } 3748 }
3767 3749
3768 3750
3769 TEST(ContextParameters) { 3751 TEST(ContextParameters) {
3770 InitializedHandleScope handle_scope; 3752 InitializedHandleScope handle_scope;
3771 BytecodeGeneratorHelper helper; 3753 BytecodeGeneratorHelper helper;
3772 3754
3773 int closure = Register::function_closure().index(); 3755 int closure = Register::function_closure().index();
3774 int first_context_slot = Context::MIN_CONTEXT_SLOTS; 3756 int first_context_slot = Context::MIN_CONTEXT_SLOTS;
3775 3757
3776 ExpectedSnippet<InstanceType> snippets[] = { 3758 ExpectedSnippet<InstanceType> snippets[] = {
3777 {"function f(arg1) { return function() { arg1 = 2; }; }", 3759 {"function f(arg1) { return function() { arg1 = 2; }; }",
3778 1 * kPointerSize, 3760 1 * kPointerSize,
3779 2, 3761 2,
3780 17, 3762 16,
3781 { 3763 {
3782 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 3764 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
3783 R(closure), U8(1), // 3765 R(closure), U8(1), //
3784 B(PushContext), R(0), // 3766 B(PushContext), R(0), //
3785 B(Ldar), R(helper.kLastParamIndex), // 3767 B(Ldar), R(helper.kLastParamIndex), //
3786 B(StaContextSlot), R(0), U8(first_context_slot), // 3768 B(StaContextSlot), R(0), U8(first_context_slot), //
3787 B(LdaConstant), U8(0), // 3769 B(CreateClosure), U8(0), U8(0), //
3788 B(CreateClosure), U8(0), //
3789 B(Return), // 3770 B(Return), //
3790 }, 3771 },
3791 1, 3772 1,
3792 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3773 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3793 {"function f(arg1) { var a = function() { arg1 = 2; }; return arg1; }", 3774 {"function f(arg1) { var a = function() { arg1 = 2; }; return arg1; }",
3794 2 * kPointerSize, 3775 2 * kPointerSize,
3795 2, 3776 2,
3796 22, 3777 21,
3797 { 3778 {
3798 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 3779 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
3799 R(closure), U8(1), // 3780 R(closure), U8(1), //
3800 B(PushContext), R(1), // 3781 B(PushContext), R(1), //
3801 B(Ldar), R(helper.kLastParamIndex), // 3782 B(Ldar), R(helper.kLastParamIndex), //
3802 B(StaContextSlot), R(1), U8(first_context_slot), // 3783 B(StaContextSlot), R(1), U8(first_context_slot), //
3803 B(LdaConstant), U8(0), // 3784 B(CreateClosure), U8(0), U8(0), //
3804 B(CreateClosure), U8(0), //
3805 B(Star), R(0), // 3785 B(Star), R(0), //
3806 B(LdaContextSlot), R(1), U8(first_context_slot), // 3786 B(LdaContextSlot), R(1), U8(first_context_slot), //
3807 B(Return), // 3787 B(Return), //
3808 }, 3788 },
3809 1, 3789 1,
3810 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3790 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3811 {"function f(a1, a2, a3, a4) { return function() { a1 = a3; }; }", 3791 {"function f(a1, a2, a3, a4) { return function() { a1 = a3; }; }",
3812 1 * kPointerSize, 3792 1 * kPointerSize,
3813 5, 3793 5,
3814 22, 3794 21,
3815 { 3795 {
3816 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 3796 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
3817 R(closure), U8(1), // 3797 R(closure), U8(1), //
3818 B(PushContext), R(0), // 3798 B(PushContext), R(0), //
3819 B(Ldar), R(helper.kLastParamIndex - 3), // 3799 B(Ldar), R(helper.kLastParamIndex - 3), //
3820 B(StaContextSlot), R(0), U8(first_context_slot + 1), // 3800 B(StaContextSlot), R(0), U8(first_context_slot + 1), //
3821 B(Ldar), R(helper.kLastParamIndex -1), // 3801 B(Ldar), R(helper.kLastParamIndex -1), //
3822 B(StaContextSlot), R(0), U8(first_context_slot), // 3802 B(StaContextSlot), R(0), U8(first_context_slot), //
3823 B(LdaConstant), U8(0), // 3803 B(CreateClosure), U8(0), U8(0), //
3824 B(CreateClosure), U8(0), //
3825 B(Return), // 3804 B(Return), //
3826 }, 3805 },
3827 1, 3806 1,
3828 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3807 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3829 {"function f() { var self = this; return function() { self = 2; }; }", 3808 {"function f() { var self = this; return function() { self = 2; }; }",
3830 1 * kPointerSize, 3809 1 * kPointerSize,
3831 1, 3810 1,
3832 17, 3811 16,
3833 { 3812 {
3834 B(CallRuntime), U16(Runtime::kNewFunctionContext), // 3813 B(CallRuntime), U16(Runtime::kNewFunctionContext), //
3835 R(closure), U8(1), // 3814 R(closure), U8(1), //
3836 B(PushContext), R(0), // 3815 B(PushContext), R(0), //
3837 B(Ldar), R(helper.kLastParamIndex), // 3816 B(Ldar), R(helper.kLastParamIndex), //
3838 B(StaContextSlot), R(0), U8(first_context_slot), // 3817 B(StaContextSlot), R(0), U8(first_context_slot), //
3839 B(LdaConstant), U8(0), // 3818 B(CreateClosure), U8(0), U8(0), //
3840 B(CreateClosure), U8(0), //
3841 B(Return), // 3819 B(Return), //
3842 }, 3820 },
3843 1, 3821 1,
3844 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 3822 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
3845 }; 3823 };
3846 3824
3847 for (size_t i = 0; i < arraysize(snippets); i++) { 3825 for (size_t i = 0; i < arraysize(snippets); i++) {
3848 Handle<BytecodeArray> bytecode_array = 3826 Handle<BytecodeArray> bytecode_array =
3849 helper.MakeBytecodeForFunction(snippets[i].code_snippet); 3827 helper.MakeBytecodeForFunction(snippets[i].code_snippet);
3850 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 3828 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
4068 B(Inc), // 4046 B(Inc), //
4069 B(KeyedStoreICSloppy), R(1), R(2), U8(vector->GetIndex(slot2)), // 4047 B(KeyedStoreICSloppy), R(1), R(2), U8(vector->GetIndex(slot2)), //
4070 B(Return), // 4048 B(Return), //
4071 }, 4049 },
4072 2, 4050 2,
4073 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, 4051 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
4074 InstanceType::FIXED_ARRAY_TYPE}}, 4052 InstanceType::FIXED_ARRAY_TYPE}},
4075 {"var a = 1; var b = function() { return a }; return ++a;", 4053 {"var a = 1; var b = function() { return a }; return ++a;",
4076 2 * kPointerSize, 4054 2 * kPointerSize,
4077 1, 4055 1,
4078 27, 4056 26,
4079 { 4057 {
4080 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // 4058 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
4081 U8(1), // 4059 U8(1), //
4082 B(PushContext), R(1), // 4060 B(PushContext), R(1), //
4083 B(LdaSmi8), U8(1), // 4061 B(LdaSmi8), U8(1), //
4084 B(StaContextSlot), R(1), U8(first_context_slot), // 4062 B(StaContextSlot), R(1), U8(first_context_slot), //
4085 B(LdaConstant), U8(0), // 4063 B(CreateClosure), U8(0), U8(0), //
4086 B(CreateClosure), U8(0), //
4087 B(Star), R(0), // 4064 B(Star), R(0), //
4088 B(LdaContextSlot), R(1), U8(first_context_slot), // 4065 B(LdaContextSlot), R(1), U8(first_context_slot), //
4089 B(ToNumber), // 4066 B(ToNumber), //
4090 B(Inc), // 4067 B(Inc), //
4091 B(StaContextSlot), R(1), U8(first_context_slot), // 4068 B(StaContextSlot), R(1), U8(first_context_slot), //
4092 B(Return), // 4069 B(Return), //
4093 }, 4070 },
4094 1, 4071 1,
4095 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 4072 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
4096 {"var a = 1; var b = function() { return a }; return a--;", 4073 {"var a = 1; var b = function() { return a }; return a--;",
4097 3 * kPointerSize, 4074 3 * kPointerSize,
4098 1, 4075 1,
4099 31, 4076 30,
4100 { 4077 {
4101 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // 4078 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
4102 U8(1), // 4079 U8(1), //
4103 B(PushContext), R(1), // 4080 B(PushContext), R(1), //
4104 B(LdaSmi8), U8(1), // 4081 B(LdaSmi8), U8(1), //
4105 B(StaContextSlot), R(1), U8(first_context_slot), // 4082 B(StaContextSlot), R(1), U8(first_context_slot), //
4106 B(LdaConstant), U8(0), // 4083 B(CreateClosure), U8(0), U8(0), //
4107 B(CreateClosure), U8(0), //
4108 B(Star), R(0), // 4084 B(Star), R(0), //
4109 B(LdaContextSlot), R(1), U8(first_context_slot), // 4085 B(LdaContextSlot), R(1), U8(first_context_slot), //
4110 B(ToNumber), // 4086 B(ToNumber), //
4111 B(Star), R(2), // 4087 B(Star), R(2), //
4112 B(Dec), // 4088 B(Dec), //
4113 B(StaContextSlot), R(1), U8(first_context_slot), // 4089 B(StaContextSlot), R(1), U8(first_context_slot), //
4114 B(Ldar), R(2), // 4090 B(Ldar), R(2), //
4115 B(Return), // 4091 B(Return), //
4116 }, 4092 },
4117 1, 4093 1,
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
4307 B(BitwiseXor), R(2), // 4283 B(BitwiseXor), R(2), //
4308 B(KeyedStoreICSloppy), R(0), R(1), U8(vector->GetIndex(slot2)), // 4284 B(KeyedStoreICSloppy), R(0), R(1), U8(vector->GetIndex(slot2)), //
4309 B(LdaUndefined), // 4285 B(LdaUndefined), //
4310 B(Return), // 4286 B(Return), //
4311 }, 4287 },
4312 1, 4288 1,
4313 {InstanceType::FIXED_ARRAY_TYPE}}, 4289 {InstanceType::FIXED_ARRAY_TYPE}},
4314 {"var a = 1; (function f() { return a; }); a |= 24;", 4290 {"var a = 1; (function f() { return a; }); a |= 24;",
4315 2 * kPointerSize, 4291 2 * kPointerSize,
4316 1, 4292 1,
4317 30, 4293 29,
4318 { 4294 {
4319 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // 4295 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
4320 U8(1), // 4296 U8(1), //
4321 B(PushContext), R(0), // 4297 B(PushContext), R(0), //
4322 B(LdaSmi8), U8(1), // 4298 B(LdaSmi8), U8(1), //
4323 B(StaContextSlot), R(0), U8(first_context_slot), // 4299 B(StaContextSlot), R(0), U8(first_context_slot), //
4324 B(LdaConstant), U8(0), // 4300 B(CreateClosure), U8(0), U8(0), //
4325 B(CreateClosure), U8(0), //
4326 B(LdaContextSlot), R(0), U8(first_context_slot), // 4301 B(LdaContextSlot), R(0), U8(first_context_slot), //
4327 B(Star), R(1), // 4302 B(Star), R(1), //
4328 B(LdaSmi8), U8(24), // 4303 B(LdaSmi8), U8(24), //
4329 B(BitwiseOr), R(1), // 4304 B(BitwiseOr), R(1), //
4330 B(StaContextSlot), R(0), U8(first_context_slot), // 4305 B(StaContextSlot), R(0), U8(first_context_slot), //
4331 B(LdaUndefined), // 4306 B(LdaUndefined), //
4332 B(Return), // 4307 B(Return), //
4333 }, 4308 },
4334 1, 4309 1,
4335 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, 4310 {InstanceType::SHARED_FUNCTION_INFO_TYPE}},
(...skipping 1147 matching lines...) Expand 10 before | Expand all | Expand 10 after
5483 for (size_t i = 0; i < arraysize(snippets); i++) { 5458 for (size_t i = 0; i < arraysize(snippets); i++) {
5484 Handle<BytecodeArray> bytecode_array = 5459 Handle<BytecodeArray> bytecode_array =
5485 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); 5460 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet);
5486 CheckBytecodeArrayEqual(snippets[i], bytecode_array); 5461 CheckBytecodeArrayEqual(snippets[i], bytecode_array);
5487 } 5462 }
5488 } 5463 }
5489 5464
5490 } // namespace interpreter 5465 } // namespace interpreter
5491 } // namespace internal 5466 } // namespace internal
5492 } // namespace v8 5467 } // namespace v8
OLDNEW
« no previous file with comments | « test/cctest/compiler/test-run-bytecode-graph-builder.cc ('k') | test/unittests/compiler/bytecode-graph-builder-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698