Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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/code-stub-assembler.h" | 5 #include "src/code-stub-assembler.h" |
| 6 #include "src/code-factory.h" | 6 #include "src/code-factory.h" |
| 7 #include "src/frames-inl.h" | 7 #include "src/frames-inl.h" |
| 8 #include "src/frames.h" | 8 #include "src/frames.h" |
| 9 #include "src/ic/stub-cache.h" | 9 #include "src/ic/stub-cache.h" |
| 10 | 10 |
| (...skipping 2398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2409 }; | 2409 }; |
| 2410 // clang-format on | 2410 // clang-format on |
| 2411 STATIC_ASSERT(arraysize(values) == arraysize(labels)); | 2411 STATIC_ASSERT(arraysize(values) == arraysize(labels)); |
| 2412 Switch(elements_kind, if_bailout, values, labels, arraysize(values)); | 2412 Switch(elements_kind, if_bailout, values, labels, arraysize(values)); |
| 2413 | 2413 |
| 2414 Bind(&if_isobjectorsmi); | 2414 Bind(&if_isobjectorsmi); |
| 2415 { | 2415 { |
| 2416 Node* elements = LoadElements(object); | 2416 Node* elements = LoadElements(object); |
| 2417 Node* length = LoadFixedArrayBaseLength(elements); | 2417 Node* length = LoadFixedArrayBaseLength(elements); |
| 2418 | 2418 |
| 2419 GotoIf(Int32GreaterThanOrEqual(index, SmiToWord32(length)), if_not_found); | 2419 GotoUnless(Uint32LessThan(index, SmiToWord32(length)), if_not_found); |
|
Jakob Kummerow
2016/07/26 14:43:28
Drive-by fix: bounds checks should use unsigned co
Igor Sheludko
2016/07/26 16:25:11
Acknowledged.
| |
| 2420 | 2420 |
| 2421 Node* element = LoadFixedArrayElement(elements, index); | 2421 Node* element = LoadFixedArrayElement(elements, index); |
| 2422 Node* the_hole = TheHoleConstant(); | 2422 Node* the_hole = TheHoleConstant(); |
| 2423 Branch(WordEqual(element, the_hole), if_not_found, if_found); | 2423 Branch(WordEqual(element, the_hole), if_not_found, if_found); |
| 2424 } | 2424 } |
| 2425 Bind(&if_isdouble); | 2425 Bind(&if_isdouble); |
| 2426 { | 2426 { |
| 2427 Node* elements = LoadElements(object); | 2427 Node* elements = LoadElements(object); |
| 2428 Node* length = LoadFixedArrayBaseLength(elements); | 2428 Node* length = LoadFixedArrayBaseLength(elements); |
| 2429 | 2429 |
| 2430 GotoIf(Int32GreaterThanOrEqual(index, SmiToWord32(length)), if_not_found); | 2430 GotoUnless(Uint32LessThan(index, SmiToWord32(length)), if_not_found); |
| 2431 | 2431 |
| 2432 if (kPointerSize == kDoubleSize) { | 2432 if (kPointerSize == kDoubleSize) { |
| 2433 Node* element = | 2433 Node* element = |
| 2434 LoadFixedDoubleArrayElement(elements, index, MachineType::Uint64()); | 2434 LoadFixedDoubleArrayElement(elements, index, MachineType::Uint64()); |
| 2435 Node* the_hole = Int64Constant(kHoleNanInt64); | 2435 Node* the_hole = Int64Constant(kHoleNanInt64); |
| 2436 Branch(Word64Equal(element, the_hole), if_not_found, if_found); | 2436 Branch(Word64Equal(element, the_hole), if_not_found, if_found); |
| 2437 } else { | 2437 } else { |
| 2438 Node* element_upper = | 2438 Node* element_upper = |
| 2439 LoadFixedDoubleArrayElement(elements, index, MachineType::Uint32(), | 2439 LoadFixedDoubleArrayElement(elements, index, MachineType::Uint32(), |
| 2440 kIeeeDoubleExponentWordOffset); | 2440 kIeeeDoubleExponentWordOffset); |
| 2441 Branch(Word32Equal(element_upper, Int32Constant(kHoleNanUpper32)), | 2441 Branch(Word32Equal(element_upper, Int32Constant(kHoleNanUpper32)), |
| 2442 if_not_found, if_found); | 2442 if_not_found, if_found); |
| 2443 } | 2443 } |
| 2444 } | 2444 } |
| 2445 Bind(&if_isdictionary); | 2445 Bind(&if_isdictionary); |
| 2446 { | 2446 { |
| 2447 Variable var_entry(this, MachineRepresentation::kWord32); | 2447 Variable var_entry(this, MachineRepresentation::kWord32); |
| 2448 Node* elements = LoadElements(object); | 2448 Node* elements = LoadElements(object); |
| 2449 NumberDictionaryLookup<SeededNumberDictionary>(elements, index, if_found, | 2449 NumberDictionaryLookup<SeededNumberDictionary>(elements, index, if_found, |
| 2450 &var_entry, if_not_found); | 2450 &var_entry, if_not_found); |
| 2451 } | 2451 } |
| 2452 Bind(&if_isfaststringwrapper); | 2452 Bind(&if_isfaststringwrapper); |
| 2453 { | 2453 { |
| 2454 AssertInstanceType(object, JS_VALUE_TYPE); | 2454 AssertInstanceType(object, JS_VALUE_TYPE); |
| 2455 Node* string = LoadJSValueValue(object); | 2455 Node* string = LoadJSValueValue(object); |
| 2456 Assert(Int32LessThan(LoadInstanceType(string), | 2456 Assert(Int32LessThan(LoadInstanceType(string), |
| 2457 Int32Constant(FIRST_NONSTRING_TYPE))); | 2457 Int32Constant(FIRST_NONSTRING_TYPE))); |
| 2458 Node* length = LoadStringLength(string); | 2458 Node* length = LoadStringLength(string); |
| 2459 GotoIf(Int32LessThan(index, SmiToWord32(length)), if_found); | 2459 GotoIf(Uint32LessThan(index, SmiToWord32(length)), if_found); |
| 2460 Goto(&if_isobjectorsmi); | 2460 Goto(&if_isobjectorsmi); |
| 2461 } | 2461 } |
| 2462 Bind(&if_isslowstringwrapper); | 2462 Bind(&if_isslowstringwrapper); |
| 2463 { | 2463 { |
| 2464 AssertInstanceType(object, JS_VALUE_TYPE); | 2464 AssertInstanceType(object, JS_VALUE_TYPE); |
| 2465 Node* string = LoadJSValueValue(object); | 2465 Node* string = LoadJSValueValue(object); |
| 2466 Assert(Int32LessThan(LoadInstanceType(string), | 2466 Assert(Int32LessThan(LoadInstanceType(string), |
| 2467 Int32Constant(FIRST_NONSTRING_TYPE))); | 2467 Int32Constant(FIRST_NONSTRING_TYPE))); |
| 2468 Node* length = LoadStringLength(string); | 2468 Node* length = LoadStringLength(string); |
| 2469 GotoIf(Int32LessThan(index, SmiToWord32(length)), if_found); | 2469 GotoIf(Uint32LessThan(index, SmiToWord32(length)), if_found); |
| 2470 Goto(&if_isdictionary); | 2470 Goto(&if_isdictionary); |
| 2471 } | 2471 } |
| 2472 } | 2472 } |
| 2473 | 2473 |
| 2474 // Instantiate template methods to workaround GCC compilation issue. | 2474 // Instantiate template methods to workaround GCC compilation issue. |
| 2475 template void CodeStubAssembler::NumberDictionaryLookup<SeededNumberDictionary>( | 2475 template void CodeStubAssembler::NumberDictionaryLookup<SeededNumberDictionary>( |
| 2476 Node*, Node*, Label*, Variable*, Label*); | 2476 Node*, Node*, Label*, Variable*, Label*); |
| 2477 template void CodeStubAssembler::NumberDictionaryLookup< | 2477 template void CodeStubAssembler::NumberDictionaryLookup< |
| 2478 UnseededNumberDictionary>(Node*, Node*, Label*, Variable*, Label*); | 2478 UnseededNumberDictionary>(Node*, Node*, Label*, Variable*, Label*); |
| 2479 | 2479 |
| (...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2970 receiver_map, if_handler, var_handler, &miss); | 2970 receiver_map, if_handler, var_handler, &miss); |
| 2971 } | 2971 } |
| 2972 | 2972 |
| 2973 Bind(&miss); | 2973 Bind(&miss); |
| 2974 { | 2974 { |
| 2975 IncrementCounter(counters->megamorphic_stub_cache_misses(), 1); | 2975 IncrementCounter(counters->megamorphic_stub_cache_misses(), 1); |
| 2976 Goto(if_miss); | 2976 Goto(if_miss); |
| 2977 } | 2977 } |
| 2978 } | 2978 } |
| 2979 | 2979 |
| 2980 void CodeStubAssembler::HaveLoadICHandler(const LoadICParameters* p, | |
| 2981 Node* handler, Label* miss) { | |
| 2982 Comment("have_handler"); | |
| 2983 Label call_handler(this); | |
| 2984 GotoUnless(WordIsSmi(handler), &call_handler); | |
| 2985 | |
| 2986 // |handler| is a Smi. It encodes a field index as obtained by | |
| 2987 // FieldIndex.GetLoadByFieldOffset(). | |
| 2988 // TODO(jkummerow): For KeyedLoadICs, extend this scheme to encode | |
| 2989 // fast *element* loads. | |
| 2990 { | |
| 2991 Variable var_double_value(this, MachineRepresentation::kFloat64); | |
| 2992 Label rebox_double(this, &var_double_value); | |
| 2993 | |
| 2994 Node* handler_word = SmiUntag(handler); | |
| 2995 // |handler_word| is a field index as obtained by | |
| 2996 // FieldIndex.GetLoadByFieldOffset(): | |
| 2997 // (offset << 3) | (is_double << 2) | (is_inobject << 1) | 1. | |
| 2998 Label inobject_double(this), out_of_object(this), | |
| 2999 out_of_object_double(this); | |
| 3000 Node* inobject_bit = WordAnd(handler_word, IntPtrConstant(1 << 1)); | |
| 3001 Node* double_bit = WordAnd(handler_word, IntPtrConstant(1 << 2)); | |
| 3002 Node* offset = WordSar(handler_word, IntPtrConstant(3)); | |
| 3003 | |
| 3004 GotoIf(WordEqual(inobject_bit, IntPtrConstant(0)), &out_of_object); | |
| 3005 | |
| 3006 GotoUnless(WordEqual(double_bit, IntPtrConstant(0)), &inobject_double); | |
| 3007 Return(LoadObjectField(p->receiver, offset)); | |
| 3008 | |
| 3009 Bind(&inobject_double); | |
| 3010 if (FLAG_unbox_double_fields) { | |
| 3011 var_double_value.Bind( | |
| 3012 LoadObjectField(p->receiver, offset, MachineType::Float64())); | |
| 3013 } else { | |
| 3014 Node* mutable_heap_number = LoadObjectField(p->receiver, offset); | |
| 3015 var_double_value.Bind(LoadHeapNumberValue(mutable_heap_number)); | |
| 3016 } | |
| 3017 Goto(&rebox_double); | |
| 3018 | |
| 3019 Bind(&out_of_object); | |
| 3020 Node* properties = LoadProperties(p->receiver); | |
| 3021 Node* value = LoadObjectField(properties, offset); | |
| 3022 GotoUnless(WordEqual(double_bit, IntPtrConstant(0)), &out_of_object_double); | |
| 3023 Return(value); | |
| 3024 | |
| 3025 Bind(&out_of_object_double); | |
| 3026 var_double_value.Bind(LoadHeapNumberValue(value)); | |
| 3027 Goto(&rebox_double); | |
| 3028 | |
| 3029 Bind(&rebox_double); | |
| 3030 Return(AllocateHeapNumberWithValue(var_double_value.value())); | |
| 3031 } | |
| 3032 | |
| 3033 // |handler| is a heap object. Must be code, call it. | |
| 3034 Bind(&call_handler); | |
| 3035 LoadWithVectorDescriptor descriptor(isolate()); | |
| 3036 TailCallStub(descriptor, handler, p->context, p->receiver, p->name, p->slot, | |
| 3037 p->vector); | |
| 3038 } | |
| 3039 | |
| 2980 void CodeStubAssembler::LoadIC(const LoadICParameters* p) { | 3040 void CodeStubAssembler::LoadIC(const LoadICParameters* p) { |
| 2981 Variable var_handler(this, MachineRepresentation::kTagged); | 3041 Variable var_handler(this, MachineRepresentation::kTagged); |
| 2982 // TODO(ishell): defer blocks when it works. | 3042 // TODO(ishell): defer blocks when it works. |
| 2983 Label if_handler(this, &var_handler), try_polymorphic(this), | 3043 Label if_handler(this, &var_handler), try_polymorphic(this), |
| 2984 try_megamorphic(this /*, Label::kDeferred*/), | 3044 try_megamorphic(this /*, Label::kDeferred*/), |
| 2985 miss(this /*, Label::kDeferred*/); | 3045 miss(this /*, Label::kDeferred*/); |
| 2986 | 3046 |
| 2987 Node* receiver_map = LoadReceiverMap(p->receiver); | 3047 Node* receiver_map = LoadReceiverMap(p->receiver); |
| 2988 | 3048 |
| 2989 // Check monomorphic case. | 3049 // Check monomorphic case. |
| 2990 Node* feedback = TryMonomorphicCase(p, receiver_map, &if_handler, | 3050 Node* feedback = TryMonomorphicCase(p, receiver_map, &if_handler, |
| 2991 &var_handler, &try_polymorphic); | 3051 &var_handler, &try_polymorphic); |
| 2992 Bind(&if_handler); | 3052 Bind(&if_handler); |
| 2993 { | 3053 { |
| 2994 Comment("LoadIC_if_handler"); | 3054 HaveLoadICHandler(p, var_handler.value(), &miss); |
| 2995 Label call_handler(this); | |
| 2996 Node* handler = var_handler.value(); | |
| 2997 GotoUnless(WordIsSmi(handler), &call_handler); | |
| 2998 | |
| 2999 // |handler| is a Smi. It encodes a field index as obtained by | |
| 3000 // FieldIndex.GetLoadByFieldOffset(). | |
| 3001 { | |
| 3002 Label inobject_double(this), out_of_object(this), | |
| 3003 out_of_object_double(this); | |
| 3004 Variable var_double_value(this, MachineRepresentation::kFloat64); | |
| 3005 Label rebox_double(this, &var_double_value); | |
| 3006 | |
| 3007 Node* handler_word = SmiToWord32(handler); | |
| 3008 // handler == (offset << 1) | is_double. | |
| 3009 Node* double_bit = Word32And(handler_word, Int32Constant(1)); | |
| 3010 Node* offset = Word32Sar(handler_word, Int32Constant(1)); | |
| 3011 | |
| 3012 // Negative index -> out of object. | |
| 3013 GotoIf(Int32LessThan(offset, Int32Constant(0)), &out_of_object); | |
| 3014 | |
| 3015 Node* offset_ptr = ChangeInt32ToIntPtr(offset); | |
| 3016 GotoUnless(Word32Equal(double_bit, Int32Constant(0)), &inobject_double); | |
| 3017 Return(LoadObjectField(p->receiver, offset_ptr)); | |
| 3018 | |
| 3019 Bind(&inobject_double); | |
| 3020 if (FLAG_unbox_double_fields) { | |
| 3021 var_double_value.Bind( | |
| 3022 LoadObjectField(p->receiver, offset_ptr, MachineType::Float64())); | |
| 3023 } else { | |
| 3024 Node* mutable_heap_number = LoadObjectField(p->receiver, offset_ptr); | |
| 3025 var_double_value.Bind(LoadHeapNumberValue(mutable_heap_number)); | |
| 3026 } | |
| 3027 Goto(&rebox_double); | |
| 3028 | |
| 3029 Bind(&out_of_object); | |
| 3030 // |offset| == -actual_offset | |
| 3031 offset_ptr = ChangeInt32ToIntPtr(Int32Sub(Int32Constant(0), offset)); | |
| 3032 Node* properties = LoadProperties(p->receiver); | |
| 3033 Node* value = LoadObjectField(properties, offset_ptr); | |
| 3034 GotoUnless(Word32Equal(double_bit, Int32Constant(0)), | |
| 3035 &out_of_object_double); | |
| 3036 Return(value); | |
| 3037 | |
| 3038 Bind(&out_of_object_double); | |
| 3039 var_double_value.Bind(LoadHeapNumberValue(value)); | |
| 3040 Goto(&rebox_double); | |
| 3041 | |
| 3042 Bind(&rebox_double); | |
| 3043 Return(AllocateHeapNumberWithValue(var_double_value.value())); | |
| 3044 } | |
| 3045 | |
| 3046 // |handler| is a heap object. Must be code, call it. | |
| 3047 Bind(&call_handler); | |
| 3048 LoadWithVectorDescriptor descriptor(isolate()); | |
| 3049 TailCallStub(descriptor, handler, p->context, p->receiver, p->name, p->slot, | |
| 3050 p->vector); | |
| 3051 } | 3055 } |
| 3052 | 3056 |
| 3053 Bind(&try_polymorphic); | 3057 Bind(&try_polymorphic); |
| 3054 { | 3058 { |
| 3055 // Check polymorphic case. | 3059 // Check polymorphic case. |
| 3056 Comment("LoadIC_try_polymorphic"); | 3060 Comment("LoadIC_try_polymorphic"); |
| 3057 GotoUnless( | 3061 GotoUnless( |
| 3058 WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), | 3062 WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), |
| 3059 &try_megamorphic); | 3063 &try_megamorphic); |
| 3060 HandlePolymorphicCase(p, receiver_map, feedback, &if_handler, &var_handler, | 3064 HandlePolymorphicCase(p, receiver_map, feedback, &if_handler, &var_handler, |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 3071 TryProbeStubCache(isolate()->load_stub_cache(), p->receiver, p->name, | 3075 TryProbeStubCache(isolate()->load_stub_cache(), p->receiver, p->name, |
| 3072 &if_handler, &var_handler, &miss); | 3076 &if_handler, &var_handler, &miss); |
| 3073 } | 3077 } |
| 3074 Bind(&miss); | 3078 Bind(&miss); |
| 3075 { | 3079 { |
| 3076 TailCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver, p->name, | 3080 TailCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver, p->name, |
| 3077 p->slot, p->vector); | 3081 p->slot, p->vector); |
| 3078 } | 3082 } |
| 3079 } | 3083 } |
| 3080 | 3084 |
| 3085 void CodeStubAssembler::KeyedLoadIC(const LoadICParameters* p) { | |
| 3086 Variable var_handler(this, MachineRepresentation::kTagged); | |
| 3087 // TODO(ishell): defer blocks when it works. | |
| 3088 Label if_handler(this, &var_handler), try_polymorphic(this), | |
| 3089 try_megamorphic(this /*, Label::kDeferred*/), | |
| 3090 try_polymorphic_name(this /*, Label::kDeferred*/), | |
| 3091 miss(this /*, Label::kDeferred*/); | |
| 3092 | |
| 3093 Node* receiver_map = LoadReceiverMap(p->receiver); | |
| 3094 | |
| 3095 // Check monomorphic case. | |
| 3096 Node* feedback = TryMonomorphicCase(p, receiver_map, &if_handler, | |
| 3097 &var_handler, &try_polymorphic); | |
| 3098 Bind(&if_handler); | |
| 3099 { | |
| 3100 HaveLoadICHandler(p, var_handler.value(), &miss); | |
| 3101 } | |
| 3102 | |
| 3103 Bind(&try_polymorphic); | |
| 3104 { | |
| 3105 // Check polymorphic case. | |
| 3106 Comment("KeyedLoadIC_try_polymorphic"); | |
| 3107 GotoUnless( | |
| 3108 WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), | |
| 3109 &try_megamorphic); | |
| 3110 HandlePolymorphicCase(p, receiver_map, feedback, &if_handler, &var_handler, | |
| 3111 &miss, 2); | |
| 3112 } | |
| 3113 | |
| 3114 Bind(&try_megamorphic); | |
| 3115 { | |
| 3116 // Check megamorphic case. | |
| 3117 Comment("KeyedLoadIC_try_megamorphic"); | |
| 3118 GotoUnless( | |
| 3119 WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)), | |
| 3120 &try_polymorphic_name); | |
| 3121 // TODO(jkummerow): Inline this? Or some of it? | |
| 3122 TailCallStub(CodeFactory::KeyedLoadIC_Megamorphic(isolate()), p->context, | |
| 3123 p->receiver, p->name, p->slot, p->vector); | |
| 3124 } | |
| 3125 Bind(&try_polymorphic_name); | |
| 3126 { | |
| 3127 // We might have a name in feedback, and a fixed array in the next slot. | |
| 3128 Comment("KeyedLoadIC_try_polymorphic_name"); | |
| 3129 GotoUnless(WordEqual(feedback, p->name), &miss); | |
| 3130 // If the name comparison succeeded, we know we have a fixed array with | |
| 3131 // at least one map/handler pair. | |
| 3132 Node* offset = ElementOffsetFromIndex( | |
| 3133 p->slot, FAST_HOLEY_ELEMENTS, SMI_PARAMETERS, | |
| 3134 FixedArray::kHeaderSize + kPointerSize - kHeapObjectTag); | |
| 3135 Node* array = Load(MachineType::AnyTagged(), p->vector, offset); | |
| 3136 HandlePolymorphicCase(p, receiver_map, array, &if_handler, &var_handler, | |
| 3137 &miss, 1); | |
| 3138 } | |
| 3139 Bind(&miss); | |
| 3140 { | |
| 3141 Comment("KeyedLoadIC_miss"); | |
| 3142 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver, | |
| 3143 p->name, p->slot, p->vector); | |
| 3144 } | |
| 3145 } | |
| 3146 | |
| 3081 void CodeStubAssembler::LoadGlobalIC(const LoadICParameters* p) { | 3147 void CodeStubAssembler::LoadGlobalIC(const LoadICParameters* p) { |
| 3082 Label try_handler(this), miss(this); | 3148 Label try_handler(this), miss(this); |
| 3083 Node* weak_cell = | 3149 Node* weak_cell = |
| 3084 LoadFixedArrayElement(p->vector, p->slot, 0, SMI_PARAMETERS); | 3150 LoadFixedArrayElement(p->vector, p->slot, 0, SMI_PARAMETERS); |
| 3085 AssertInstanceType(weak_cell, WEAK_CELL_TYPE); | 3151 AssertInstanceType(weak_cell, WEAK_CELL_TYPE); |
| 3086 | 3152 |
| 3087 // Load value or try handler case if the {weak_cell} is cleared. | 3153 // Load value or try handler case if the {weak_cell} is cleared. |
| 3088 Node* property_cell = LoadWeakCellValue(weak_cell, &try_handler); | 3154 Node* property_cell = LoadWeakCellValue(weak_cell, &try_handler); |
| 3089 AssertInstanceType(property_cell, PROPERTY_CELL_TYPE); | 3155 AssertInstanceType(property_cell, PROPERTY_CELL_TYPE); |
| 3090 | 3156 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3178 // For all objects but the receiver, check that the cache is empty. | 3244 // For all objects but the receiver, check that the cache is empty. |
| 3179 current_map.Bind(LoadMap(current_js_object.value())); | 3245 current_map.Bind(LoadMap(current_js_object.value())); |
| 3180 Node* enum_length = EnumLength(current_map.value()); | 3246 Node* enum_length = EnumLength(current_map.value()); |
| 3181 Node* zero_constant = SmiConstant(Smi::FromInt(0)); | 3247 Node* zero_constant = SmiConstant(Smi::FromInt(0)); |
| 3182 BranchIf(WordEqual(enum_length, zero_constant), &loop, use_runtime); | 3248 BranchIf(WordEqual(enum_length, zero_constant), &loop, use_runtime); |
| 3183 } | 3249 } |
| 3184 } | 3250 } |
| 3185 | 3251 |
| 3186 } // namespace internal | 3252 } // namespace internal |
| 3187 } // namespace v8 | 3253 } // namespace v8 |
| OLD | NEW |