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 2940 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2951 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, | 2951 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, |
2952 }; | 2952 }; |
2953 | 2953 |
2954 for (size_t i = 0; i < arraysize(snippets); i++) { | 2954 for (size_t i = 0; i < arraysize(snippets); i++) { |
2955 Handle<BytecodeArray> bytecode_array = | 2955 Handle<BytecodeArray> bytecode_array = |
2956 helper.MakeBytecodeForFunction(snippets[i].code_snippet); | 2956 helper.MakeBytecodeForFunction(snippets[i].code_snippet); |
2957 CheckBytecodeArrayEqual(snippets[i], bytecode_array); | 2957 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
2958 } | 2958 } |
2959 } | 2959 } |
2960 | 2960 |
| 2961 |
| 2962 TEST(CountOperators) { |
| 2963 InitializedHandleScope handle_scope; |
| 2964 BytecodeGeneratorHelper helper; |
| 2965 Zone zone; |
| 2966 |
| 2967 FeedbackVectorSpec feedback_spec(&zone); |
| 2968 FeedbackVectorSlot slot1 = feedback_spec.AddLoadICSlot(); |
| 2969 FeedbackVectorSlot slot2 = feedback_spec.AddStoreICSlot(); |
| 2970 |
| 2971 Handle<i::TypeFeedbackVector> vector = |
| 2972 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); |
| 2973 |
| 2974 int closure = Register::function_closure().index(); |
| 2975 int first_context_slot = Context::MIN_CONTEXT_SLOTS; |
| 2976 |
| 2977 int object_literal_flags = |
| 2978 ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos; |
| 2979 |
| 2980 ExpectedSnippet<InstanceType> snippets[] = { |
| 2981 {"var a = 1; return ++a;", |
| 2982 1 * kPointerSize, |
| 2983 1, |
| 2984 11, |
| 2985 { |
| 2986 B(LdaSmi8), U8(1), // |
| 2987 B(Star), R(0), // |
| 2988 B(Ldar), R(0), // |
| 2989 B(ToNumber), // |
| 2990 B(Inc), // |
| 2991 B(Star), R(0), // |
| 2992 B(Return), // |
| 2993 }}, |
| 2994 {"var a = 1; return a++;", |
| 2995 2 * kPointerSize, |
| 2996 1, |
| 2997 15, |
| 2998 { |
| 2999 B(LdaSmi8), U8(1), // |
| 3000 B(Star), R(0), // |
| 3001 B(Ldar), R(0), // |
| 3002 B(ToNumber), // |
| 3003 B(Star), R(1), // |
| 3004 B(Inc), // |
| 3005 B(Star), R(0), // |
| 3006 B(Ldar), R(1), // |
| 3007 B(Return), // |
| 3008 }}, |
| 3009 {"var a = 1; return --a;", |
| 3010 1 * kPointerSize, |
| 3011 1, |
| 3012 11, |
| 3013 { |
| 3014 B(LdaSmi8), U8(1), // |
| 3015 B(Star), R(0), // |
| 3016 B(Ldar), R(0), // |
| 3017 B(ToNumber), // |
| 3018 B(Dec), // |
| 3019 B(Star), R(0), // |
| 3020 B(Return), // |
| 3021 }}, |
| 3022 {"var a = 1; return a--;", |
| 3023 2 * kPointerSize, |
| 3024 1, |
| 3025 15, |
| 3026 { |
| 3027 B(LdaSmi8), U8(1), // |
| 3028 B(Star), R(0), // |
| 3029 B(Ldar), R(0), // |
| 3030 B(ToNumber), // |
| 3031 B(Star), R(1), // |
| 3032 B(Dec), // |
| 3033 B(Star), R(0), // |
| 3034 B(Ldar), R(1), // |
| 3035 B(Return), // |
| 3036 }}, |
| 3037 {"var a = { val: 1 }; return a.val++;", |
| 3038 4 * kPointerSize, |
| 3039 1, |
| 3040 29, |
| 3041 { |
| 3042 B(LdaConstant), U8(0), // |
| 3043 B(CreateObjectLiteral), U8(0), U8(object_literal_flags), // |
| 3044 B(Star), R(0), // |
| 3045 B(Ldar), R(0), // |
| 3046 B(Star), R(1), // |
| 3047 B(LdaConstant), U8(1), // |
| 3048 B(Star), R(2), // |
| 3049 B(LoadICSloppy), R(1), U8(vector->GetIndex(slot1)), // |
| 3050 B(ToNumber), // |
| 3051 B(Star), R(3), // |
| 3052 B(Inc), // |
| 3053 B(StoreICSloppy), R(1), R(2), U8(vector->GetIndex(slot2)), // |
| 3054 B(Ldar), R(3), // |
| 3055 B(Return), // |
| 3056 }, |
| 3057 2, |
| 3058 {InstanceType::FIXED_ARRAY_TYPE, |
| 3059 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, |
| 3060 {"var a = { val: 1 }; return --a.val;", |
| 3061 3 * kPointerSize, |
| 3062 1, |
| 3063 25, |
| 3064 { |
| 3065 B(LdaConstant), U8(0), // |
| 3066 B(CreateObjectLiteral), U8(0), U8(object_literal_flags), // |
| 3067 B(Star), R(0), // |
| 3068 B(Ldar), R(0), // |
| 3069 B(Star), R(1), // |
| 3070 B(LdaConstant), U8(1), // |
| 3071 B(Star), R(2), // |
| 3072 B(LoadICSloppy), R(1), U8(vector->GetIndex(slot1)), // |
| 3073 B(ToNumber), // |
| 3074 B(Dec), // |
| 3075 B(StoreICSloppy), R(1), R(2), U8(vector->GetIndex(slot2)), // |
| 3076 B(Return), // |
| 3077 }, |
| 3078 2, |
| 3079 {InstanceType::FIXED_ARRAY_TYPE, |
| 3080 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, |
| 3081 {"var name = 'var'; var a = { val: 1 }; return a[name]--;", |
| 3082 5 * kPointerSize, |
| 3083 1, |
| 3084 33, |
| 3085 { |
| 3086 B(LdaConstant), U8(0), // |
| 3087 B(Star), R(0), // |
| 3088 B(LdaConstant), U8(1), // |
| 3089 B(CreateObjectLiteral), U8(0), U8(object_literal_flags), // |
| 3090 B(Star), R(1), // |
| 3091 B(Ldar), R(1), // |
| 3092 B(Star), R(2), // |
| 3093 B(Ldar), R(0), // |
| 3094 B(Star), R(3), // |
| 3095 B(KeyedLoadICSloppy), R(2), U8(3), // |
| 3096 B(ToNumber), // |
| 3097 B(Star), R(4), // |
| 3098 B(Dec), // |
| 3099 B(KeyedStoreICSloppy), R(2), R(3), U8(5), // |
| 3100 B(Ldar), R(4), // |
| 3101 B(Return), // |
| 3102 }, |
| 3103 2, |
| 3104 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, |
| 3105 InstanceType::FIXED_ARRAY_TYPE}}, |
| 3106 {"var name = 'var'; var a = { val: 1 }; return ++a[name];", |
| 3107 4 * kPointerSize, |
| 3108 1, |
| 3109 29, |
| 3110 { |
| 3111 B(LdaConstant), U8(0), // |
| 3112 B(Star), R(0), // |
| 3113 B(LdaConstant), U8(1), // |
| 3114 B(CreateObjectLiteral), U8(0), U8(object_literal_flags), // |
| 3115 B(Star), R(1), // |
| 3116 B(Ldar), R(1), // |
| 3117 B(Star), R(2), // |
| 3118 B(Ldar), R(0), // |
| 3119 B(Star), R(3), // |
| 3120 B(KeyedLoadICSloppy), R(2), U8(3), // |
| 3121 B(ToNumber), // |
| 3122 B(Inc), // |
| 3123 B(KeyedStoreICSloppy), R(2), R(3), U8(5), // |
| 3124 B(Return), // |
| 3125 }, |
| 3126 2, |
| 3127 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, |
| 3128 InstanceType::FIXED_ARRAY_TYPE}}, |
| 3129 {"var a = 1; var b = function() { return a }; return ++a;", |
| 3130 2 * kPointerSize, |
| 3131 1, |
| 3132 27, |
| 3133 { |
| 3134 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // |
| 3135 U8(1), // |
| 3136 B(PushContext), R(1), // |
| 3137 B(LdaSmi8), U8(1), // |
| 3138 B(StaContextSlot), R(1), U8(first_context_slot), // |
| 3139 B(LdaConstant), U8(0), // |
| 3140 B(CreateClosure), U8(0), // |
| 3141 B(Star), R(0), // |
| 3142 B(LdaContextSlot), R(1), U8(first_context_slot), // |
| 3143 B(ToNumber), // |
| 3144 B(Inc), // |
| 3145 B(StaContextSlot), R(1), U8(first_context_slot), // |
| 3146 B(Return), // |
| 3147 }, |
| 3148 1, |
| 3149 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, |
| 3150 {"var a = 1; var b = function() { return a }; return a--;", |
| 3151 3 * kPointerSize, |
| 3152 1, |
| 3153 31, |
| 3154 { |
| 3155 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // |
| 3156 U8(1), // |
| 3157 B(PushContext), R(1), // |
| 3158 B(LdaSmi8), U8(1), // |
| 3159 B(StaContextSlot), R(1), U8(first_context_slot), // |
| 3160 B(LdaConstant), U8(0), // |
| 3161 B(CreateClosure), U8(0), // |
| 3162 B(Star), R(0), // |
| 3163 B(LdaContextSlot), R(1), U8(first_context_slot), // |
| 3164 B(ToNumber), // |
| 3165 B(Star), R(2), // |
| 3166 B(Dec), // |
| 3167 B(StaContextSlot), R(1), U8(first_context_slot), // |
| 3168 B(Ldar), R(2), // |
| 3169 B(Return), // |
| 3170 }, |
| 3171 1, |
| 3172 {InstanceType::SHARED_FUNCTION_INFO_TYPE}}, |
| 3173 }; |
| 3174 |
| 3175 for (size_t i = 0; i < arraysize(snippets); i++) { |
| 3176 Handle<BytecodeArray> bytecode_array = |
| 3177 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); |
| 3178 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
| 3179 } |
| 3180 } |
| 3181 |
| 3182 |
| 3183 TEST(GlobalCountOperators) { |
| 3184 InitializedHandleScope handle_scope; |
| 3185 BytecodeGeneratorHelper helper; |
| 3186 Zone zone; |
| 3187 |
| 3188 int context = Register::function_context().index(); |
| 3189 |
| 3190 FeedbackVectorSpec feedback_spec(&zone); |
| 3191 FeedbackVectorSlot slot1 = feedback_spec.AddLoadICSlot(); |
| 3192 FeedbackVectorSlot slot2 = feedback_spec.AddStoreICSlot(); |
| 3193 |
| 3194 Handle<i::TypeFeedbackVector> vector = |
| 3195 i::NewTypeFeedbackVector(helper.isolate(), &feedback_spec); |
| 3196 |
| 3197 ExpectedSnippet<InstanceType> snippets[] = { |
| 3198 {"var global = 1;\nfunction f() { return ++global; }\nf()", |
| 3199 0, |
| 3200 1, |
| 3201 7, |
| 3202 { |
| 3203 B(LdaGlobal), _, // |
| 3204 B(ToNumber), // |
| 3205 B(Inc), // |
| 3206 B(StaGlobalSloppy), _, // |
| 3207 B(Return), // |
| 3208 }}, |
| 3209 {"var global = 1;\nfunction f() { return global--; }\nf()", |
| 3210 1 * kPointerSize, |
| 3211 1, |
| 3212 11, |
| 3213 { |
| 3214 B(LdaGlobal), U8(4), // |
| 3215 B(ToNumber), // |
| 3216 B(Star), R(0), // |
| 3217 B(Dec), // |
| 3218 B(StaGlobalSloppy), _, // |
| 3219 B(Ldar), R(0), // |
| 3220 B(Return), // |
| 3221 }}, |
| 3222 {"unallocated = 1;\nfunction f() { return --unallocated; }\nf()", |
| 3223 3 * kPointerSize, |
| 3224 1, |
| 3225 30, |
| 3226 { |
| 3227 // TODO(rmcilroy): We could probably be more clever here and maintain |
| 3228 // the value looked up on the global object and use it for the store |
| 3229 // rather than having to reload it. |
| 3230 B(LdaContextSlot), R(context), U8(Context::GLOBAL_OBJECT_INDEX), // |
| 3231 B(Star), R(0), // |
| 3232 B(LdaConstant), U8(0), // |
| 3233 B(LoadICSloppy), R(0), U8(vector->GetIndex(slot1)), // |
| 3234 B(ToNumber), // |
| 3235 B(Dec), // |
| 3236 B(Star), R(0), // |
| 3237 B(LdaContextSlot), R(context), U8(Context::GLOBAL_OBJECT_INDEX), // |
| 3238 B(Star), R(1), // |
| 3239 B(LdaConstant), U8(0), // |
| 3240 B(Star), R(2), // |
| 3241 B(Ldar), R(0), // |
| 3242 B(StoreICSloppy), R(1), R(2), U8(vector->GetIndex(slot2)), // |
| 3243 B(Return), // |
| 3244 }, |
| 3245 1, |
| 3246 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, |
| 3247 {"unallocated = 1;\nfunction f() { return unallocated++; }\nf()", |
| 3248 4 * kPointerSize, |
| 3249 1, |
| 3250 34, |
| 3251 { |
| 3252 // TODO(rmcilroy): We could probably be more clever here and maintain |
| 3253 // the value looked up on the global object and use it for the store |
| 3254 // rather than having to reload it. |
| 3255 B(LdaContextSlot), R(context), U8(Context::GLOBAL_OBJECT_INDEX), // |
| 3256 B(Star), R(0), // |
| 3257 B(LdaConstant), U8(0), // |
| 3258 B(LoadICSloppy), R(0), U8(vector->GetIndex(slot1)), // |
| 3259 B(ToNumber), // |
| 3260 B(Star), R(0), // |
| 3261 B(Inc), // |
| 3262 B(Star), R(1), // |
| 3263 B(LdaContextSlot), R(context), U8(Context::GLOBAL_OBJECT_INDEX), // |
| 3264 B(Star), R(2), // |
| 3265 B(LdaConstant), U8(0), // |
| 3266 B(Star), R(3), // |
| 3267 B(Ldar), R(1), // |
| 3268 B(StoreICSloppy), R(2), R(3), U8(vector->GetIndex(slot2)), // |
| 3269 B(Ldar), R(0), // |
| 3270 B(Return), // |
| 3271 }, |
| 3272 1, |
| 3273 {InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, |
| 3274 }; |
| 3275 |
| 3276 for (size_t i = 0; i < arraysize(snippets); i++) { |
| 3277 Handle<BytecodeArray> bytecode_array = |
| 3278 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
| 3279 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); |
| 3280 } |
| 3281 } |
| 3282 |
2961 } // namespace interpreter | 3283 } // namespace interpreter |
2962 } // namespace internal | 3284 } // namespace internal |
2963 } // namespace v8 | 3285 } // namespace v8 |
OLD | NEW |