| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 #if V8_TARGET_ARCH_ARM64 | 5 #if V8_TARGET_ARCH_ARM64 |
| 6 | 6 |
| 7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
| 8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
| 9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
| 10 #include "src/compiler.h" | 10 #include "src/compiler.h" |
| (...skipping 3013 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3024 | 3024 |
| 3025 __ JumpIfSmi(x0, if_false); | 3025 __ JumpIfSmi(x0, if_false); |
| 3026 __ CompareObjectType(x0, x10, x11, SIMD128_VALUE_TYPE); | 3026 __ CompareObjectType(x0, x10, x11, SIMD128_VALUE_TYPE); |
| 3027 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3027 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 3028 Split(eq, if_true, if_false, fall_through); | 3028 Split(eq, if_true, if_false, fall_through); |
| 3029 | 3029 |
| 3030 context()->Plug(if_true, if_false); | 3030 context()->Plug(if_true, if_false); |
| 3031 } | 3031 } |
| 3032 | 3032 |
| 3033 | 3033 |
| 3034 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( | |
| 3035 CallRuntime* expr) { | |
| 3036 ZoneList<Expression*>* args = expr->arguments(); | |
| 3037 DCHECK(args->length() == 1); | |
| 3038 VisitForAccumulatorValue(args->at(0)); | |
| 3039 | |
| 3040 Label materialize_true, materialize_false, skip_lookup; | |
| 3041 Label* if_true = NULL; | |
| 3042 Label* if_false = NULL; | |
| 3043 Label* fall_through = NULL; | |
| 3044 context()->PrepareTest(&materialize_true, &materialize_false, | |
| 3045 &if_true, &if_false, &fall_through); | |
| 3046 | |
| 3047 Register object = x0; | |
| 3048 __ AssertNotSmi(object); | |
| 3049 | |
| 3050 Register map = x10; | |
| 3051 Register bitfield2 = x11; | |
| 3052 __ Ldr(map, FieldMemOperand(object, HeapObject::kMapOffset)); | |
| 3053 __ Ldrb(bitfield2, FieldMemOperand(map, Map::kBitField2Offset)); | |
| 3054 __ Tbnz(bitfield2, Map::kStringWrapperSafeForDefaultValueOf, &skip_lookup); | |
| 3055 | |
| 3056 // Check for fast case object. Generate false result for slow case object. | |
| 3057 Register props = x12; | |
| 3058 Register props_map = x12; | |
| 3059 Register hash_table_map = x13; | |
| 3060 __ Ldr(props, FieldMemOperand(object, JSObject::kPropertiesOffset)); | |
| 3061 __ Ldr(props_map, FieldMemOperand(props, HeapObject::kMapOffset)); | |
| 3062 __ LoadRoot(hash_table_map, Heap::kHashTableMapRootIndex); | |
| 3063 __ Cmp(props_map, hash_table_map); | |
| 3064 __ B(eq, if_false); | |
| 3065 | |
| 3066 // Look for valueOf name in the descriptor array, and indicate false if found. | |
| 3067 // Since we omit an enumeration index check, if it is added via a transition | |
| 3068 // that shares its descriptor array, this is a false positive. | |
| 3069 Label loop, done; | |
| 3070 | |
| 3071 // Skip loop if no descriptors are valid. | |
| 3072 Register descriptors = x12; | |
| 3073 Register descriptors_length = x13; | |
| 3074 __ NumberOfOwnDescriptors(descriptors_length, map); | |
| 3075 __ Cbz(descriptors_length, &done); | |
| 3076 | |
| 3077 __ LoadInstanceDescriptors(map, descriptors); | |
| 3078 | |
| 3079 // Calculate the end of the descriptor array. | |
| 3080 Register descriptors_end = x14; | |
| 3081 __ Mov(x15, DescriptorArray::kDescriptorSize); | |
| 3082 __ Mul(descriptors_length, descriptors_length, x15); | |
| 3083 // Calculate location of the first key name. | |
| 3084 __ Add(descriptors, descriptors, | |
| 3085 DescriptorArray::kFirstOffset - kHeapObjectTag); | |
| 3086 // Calculate the end of the descriptor array. | |
| 3087 __ Add(descriptors_end, descriptors, | |
| 3088 Operand(descriptors_length, LSL, kPointerSizeLog2)); | |
| 3089 | |
| 3090 // Loop through all the keys in the descriptor array. If one of these is the | |
| 3091 // string "valueOf" the result is false. | |
| 3092 Register valueof_string = x1; | |
| 3093 int descriptor_size = DescriptorArray::kDescriptorSize * kPointerSize; | |
| 3094 __ LoadRoot(valueof_string, Heap::kvalueOf_stringRootIndex); | |
| 3095 __ Bind(&loop); | |
| 3096 __ Ldr(x15, MemOperand(descriptors, descriptor_size, PostIndex)); | |
| 3097 __ Cmp(x15, valueof_string); | |
| 3098 __ B(eq, if_false); | |
| 3099 __ Cmp(descriptors, descriptors_end); | |
| 3100 __ B(ne, &loop); | |
| 3101 | |
| 3102 __ Bind(&done); | |
| 3103 | |
| 3104 // Set the bit in the map to indicate that there is no local valueOf field. | |
| 3105 __ Ldrb(x2, FieldMemOperand(map, Map::kBitField2Offset)); | |
| 3106 __ Orr(x2, x2, 1 << Map::kStringWrapperSafeForDefaultValueOf); | |
| 3107 __ Strb(x2, FieldMemOperand(map, Map::kBitField2Offset)); | |
| 3108 | |
| 3109 __ Bind(&skip_lookup); | |
| 3110 | |
| 3111 // If a valueOf property is not found on the object check that its prototype | |
| 3112 // is the unmodified String prototype. If not result is false. | |
| 3113 Register prototype = x1; | |
| 3114 Register global_idx = x2; | |
| 3115 Register native_context = x2; | |
| 3116 Register string_proto = x3; | |
| 3117 Register proto_map = x4; | |
| 3118 __ Ldr(prototype, FieldMemOperand(map, Map::kPrototypeOffset)); | |
| 3119 __ JumpIfSmi(prototype, if_false); | |
| 3120 __ Ldr(proto_map, FieldMemOperand(prototype, HeapObject::kMapOffset)); | |
| 3121 __ Ldr(global_idx, GlobalObjectMemOperand()); | |
| 3122 __ Ldr(native_context, | |
| 3123 FieldMemOperand(global_idx, GlobalObject::kNativeContextOffset)); | |
| 3124 __ Ldr(string_proto, | |
| 3125 ContextMemOperand(native_context, | |
| 3126 Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); | |
| 3127 __ Cmp(proto_map, string_proto); | |
| 3128 | |
| 3129 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | |
| 3130 Split(eq, if_true, if_false, fall_through); | |
| 3131 | |
| 3132 context()->Plug(if_true, if_false); | |
| 3133 } | |
| 3134 | |
| 3135 | |
| 3136 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) { | 3034 void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) { |
| 3137 ZoneList<Expression*>* args = expr->arguments(); | 3035 ZoneList<Expression*>* args = expr->arguments(); |
| 3138 DCHECK(args->length() == 1); | 3036 DCHECK(args->length() == 1); |
| 3139 | 3037 |
| 3140 VisitForAccumulatorValue(args->at(0)); | 3038 VisitForAccumulatorValue(args->at(0)); |
| 3141 | 3039 |
| 3142 Label materialize_true, materialize_false; | 3040 Label materialize_true, materialize_false; |
| 3143 Label* if_true = NULL; | 3041 Label* if_true = NULL; |
| 3144 Label* if_false = NULL; | 3042 Label* if_false = NULL; |
| 3145 Label* fall_through = NULL; | 3043 Label* fall_through = NULL; |
| (...skipping 2220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5366 } | 5264 } |
| 5367 | 5265 |
| 5368 return INTERRUPT; | 5266 return INTERRUPT; |
| 5369 } | 5267 } |
| 5370 | 5268 |
| 5371 | 5269 |
| 5372 } // namespace internal | 5270 } // namespace internal |
| 5373 } // namespace v8 | 5271 } // namespace v8 |
| 5374 | 5272 |
| 5375 #endif // V8_TARGET_ARCH_ARM64 | 5273 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |