V(TO_STRING_FUN_INDEX, JSFunction, to_string_fun)
-#define NATIVE_CONTEXT_JS_BUILTINS(V) \
- V(APPLY_PREPARE_BUILTIN_INDEX, JSFunction, apply_prepare_builtin) \
- V(COMPARE_BUILTIN_INDEX, JSFunction, compare_builtin) \
- V(COMPARE_STRONG_BUILTIN_INDEX, JSFunction, compare_strong_builtin) \
- V(CONCAT_ITERABLE_TO_ARRAY_BUILTIN_INDEX, JSFunction, \
- concat_iterable_to_array_builtin) \
- V(EQUALS_BUILTIN_INDEX, JSFunction, equals_builtin) \
- V(REFLECT_APPLY_PREPARE_BUILTIN_INDEX, JSFunction, \
- reflect_apply_prepare_builtin) \
- V(REFLECT_CONSTRUCT_PREPARE_BUILTIN_INDEX, JSFunction, \
- reflect_construct_prepare_builtin) \
- V(STRING_ADD_LEFT_BUILTIN_INDEX, JSFunction, string_add_left_builtin) \
- V(STRING_ADD_RIGHT_BUILTIN_INDEX, JSFunction, string_add_right_builtin)
+#define NATIVE_CONTEXT_JS_BUILTINS(V) \
+ V(APPLY_PREPARE_BUILTIN_INDEX, JSFunction, apply_prepare_builtin) \
+ V(COMPARE_BUILTIN_INDEX, JSFunction, compare_builtin) \
+ V(COMPARE_STRONG_BUILTIN_INDEX, JSFunction, compare_strong_builtin) \
+ V(CONCAT_ITERABLE_TO_ARRAY_BUILTIN_INDEX, JSFunction, \
+ concat_iterable_to_array_builtin) \
+ V(EQUALS_BUILTIN_INDEX, JSFunction, equals_builtin) \
+ V(REFLECT_APPLY_PREPARE_BUILTIN_INDEX, JSFunction, \
+ reflect_apply_prepare_builtin) \
+ V(REFLECT_CONSTRUCT_PREPARE_BUILTIN_INDEX, JSFunction, \
+ reflect_construct_prepare_builtin)
#define NATIVE_CONTEXT_IMPORTED_FIELDS(V) \
}
-void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
- CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- DCHECK(args->length() == 1);
-
- VisitForAccumulatorValue(args->at(0));
-
- Label materialize_true, materialize_false, skip_lookup;
- Label* if_true = NULL;
- Label* if_false = NULL;
- Label* fall_through = NULL;
- context()->PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
-
- __ AssertNotSmi(r0);
-
- __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
- __ ldrb(ip, FieldMemOperand(r1, Map::kBitField2Offset));
- __ tst(ip, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
- __ b(ne, &skip_lookup);
-
- // Check for fast case object. Generate false result for slow case object.
- __ ldr(r2, FieldMemOperand(r0, JSObject::kPropertiesOffset));
- __ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset));
- __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
- __ cmp(r2, ip);
- __ b(eq, if_false);
-
- // Look for valueOf name in the descriptor array, and indicate false if
- // found. Since we omit an enumeration index check, if it is added via a
- // transition that shares its descriptor array, this is a false positive.
- Label entry, loop, done;
-
- // Skip loop if no descriptors are valid.
- __ NumberOfOwnDescriptors(r3, r1);
- __ cmp(r3, Operand::Zero());
- __ b(eq, &done);
-
- __ LoadInstanceDescriptors(r1, r4);
- // r4: descriptor array.
- // r3: valid entries in the descriptor array.
- __ mov(ip, Operand(DescriptorArray::kDescriptorSize));
- __ mul(r3, r3, ip);
- // Calculate location of the first key name.
- __ add(r4, r4, Operand(DescriptorArray::kFirstOffset - kHeapObjectTag));
- // Calculate the end of the descriptor array.
- __ mov(r2, r4);
- __ add(r2, r2, Operand(r3, LSL, kPointerSizeLog2));
-
- // Loop through all the keys in the descriptor array. If one of these is the
- // string "valueOf" the result is false.
- // The use of ip to store the valueOf string assumes that it is not otherwise
- // used in the loop below.
- __ LoadRoot(ip, Heap::kvalueOf_stringRootIndex);
- __ jmp(&entry);
- __ bind(&loop);
- __ ldr(r3, MemOperand(r4, 0));
- __ cmp(r3, ip);
- __ b(eq, if_false);
- __ add(r4, r4, Operand(DescriptorArray::kDescriptorSize * kPointerSize));
- __ bind(&entry);
- __ cmp(r4, Operand(r2));
- __ b(ne, &loop);
-
- __ bind(&done);
-
- // Set the bit in the map to indicate that there is no local valueOf field.
- __ ldrb(r2, FieldMemOperand(r1, Map::kBitField2Offset));
- __ orr(r2, r2, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
- __ strb(r2, FieldMemOperand(r1, Map::kBitField2Offset));
-
- __ bind(&skip_lookup);
-
- // If a valueOf property is not found on the object check that its
- // prototype is the un-modified String prototype. If not result is false.
- __ ldr(r2, FieldMemOperand(r1, Map::kPrototypeOffset));
- __ JumpIfSmi(r2, if_false);
- __ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset));
- __ ldr(r3, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
- __ ldr(r3, FieldMemOperand(r3, GlobalObject::kNativeContextOffset));
- __ ldr(r3, ContextOperand(r3, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
- __ cmp(r2, r3);
- PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
- Split(eq, if_true, if_false, fall_through);
-
- context()->Plug(if_true, if_false);
-}
-
-
void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
}
-void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
- CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- DCHECK(args->length() == 1);
- VisitForAccumulatorValue(args->at(0));
-
- Label materialize_true, materialize_false, skip_lookup;
- Label* if_true = NULL;
- Label* if_false = NULL;
- Label* fall_through = NULL;
- context()->PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
-
- Register object = x0;
- __ AssertNotSmi(object);
-
- Register map = x10;
- Register bitfield2 = x11;
- __ Ldr(map, FieldMemOperand(object, HeapObject::kMapOffset));
- __ Ldrb(bitfield2, FieldMemOperand(map, Map::kBitField2Offset));
- __ Tbnz(bitfield2, Map::kStringWrapperSafeForDefaultValueOf, &skip_lookup);
-
- // Check for fast case object. Generate false result for slow case object.
- Register props = x12;
- Register props_map = x12;
- Register hash_table_map = x13;
- __ Ldr(props, FieldMemOperand(object, JSObject::kPropertiesOffset));
- __ Ldr(props_map, FieldMemOperand(props, HeapObject::kMapOffset));
- __ LoadRoot(hash_table_map, Heap::kHashTableMapRootIndex);
- __ Cmp(props_map, hash_table_map);
- __ B(eq, if_false);
-
- // Look for valueOf name in the descriptor array, and indicate false if found.
- // Since we omit an enumeration index check, if it is added via a transition
- // that shares its descriptor array, this is a false positive.
- Label loop, done;
-
- // Skip loop if no descriptors are valid.
- Register descriptors = x12;
- Register descriptors_length = x13;
- __ NumberOfOwnDescriptors(descriptors_length, map);
- __ Cbz(descriptors_length, &done);
-
- __ LoadInstanceDescriptors(map, descriptors);
-
- // Calculate the end of the descriptor array.
- Register descriptors_end = x14;
- __ Mov(x15, DescriptorArray::kDescriptorSize);
- __ Mul(descriptors_length, descriptors_length, x15);
- // Calculate location of the first key name.
- __ Add(descriptors, descriptors,
- DescriptorArray::kFirstOffset - kHeapObjectTag);
- // Calculate the end of the descriptor array.
- __ Add(descriptors_end, descriptors,
- Operand(descriptors_length, LSL, kPointerSizeLog2));
-
- // Loop through all the keys in the descriptor array. If one of these is the
- // string "valueOf" the result is false.
- Register valueof_string = x1;
- int descriptor_size = DescriptorArray::kDescriptorSize * kPointerSize;
- __ LoadRoot(valueof_string, Heap::kvalueOf_stringRootIndex);
- __ Bind(&loop);
- __ Ldr(x15, MemOperand(descriptors, descriptor_size, PostIndex));
- __ Cmp(x15, valueof_string);
- __ B(eq, if_false);
- __ Cmp(descriptors, descriptors_end);
- __ B(ne, &loop);
-
- __ Bind(&done);
-
- // Set the bit in the map to indicate that there is no local valueOf field.
- __ Ldrb(x2, FieldMemOperand(map, Map::kBitField2Offset));
- __ Orr(x2, x2, 1 << Map::kStringWrapperSafeForDefaultValueOf);
- __ Strb(x2, FieldMemOperand(map, Map::kBitField2Offset));
-
- __ Bind(&skip_lookup);
-
- // If a valueOf property is not found on the object check that its prototype
- // is the unmodified String prototype. If not result is false.
- Register prototype = x1;
- Register global_idx = x2;
- Register native_context = x2;
- Register string_proto = x3;
- Register proto_map = x4;
- __ Ldr(prototype, FieldMemOperand(map, Map::kPrototypeOffset));
- __ JumpIfSmi(prototype, if_false);
- __ Ldr(proto_map, FieldMemOperand(prototype, HeapObject::kMapOffset));
- __ Ldr(global_idx, GlobalObjectMemOperand());
- __ Ldr(native_context,
- FieldMemOperand(global_idx, GlobalObject::kNativeContextOffset));
- __ Ldr(string_proto,
- ContextMemOperand(native_context,
- Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
- __ Cmp(proto_map, string_proto);
-
- PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
- Split(eq, if_true, if_false, fall_through);
-
- context()->Plug(if_true, if_false);
-}
-
-
void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
F(IsFunction) \
F(IsSpecObject) \
F(IsSimdValue) \
- F(IsStringWrapperSafeForDefaultValueOf) \
F(MathPow) \
F(IsMinusZero) \
F(HasCachedArrayIndex) \
}
-void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
- CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- DCHECK(args->length() == 1);
-
- VisitForAccumulatorValue(args->at(0));
-
- Label materialize_true, materialize_false, skip_lookup;
- Label* if_true = NULL;
- Label* if_false = NULL;
- Label* fall_through = NULL;
- context()->PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
-
- __ AssertNotSmi(eax);
-
- // Check whether this map has already been checked to be safe for default
- // valueOf.
- __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
- __ test_b(FieldOperand(ebx, Map::kBitField2Offset),
- 1 << Map::kStringWrapperSafeForDefaultValueOf);
- __ j(not_zero, &skip_lookup);
-
- // Check for fast case object. Return false for slow case objects.
- __ mov(ecx, FieldOperand(eax, JSObject::kPropertiesOffset));
- __ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset));
- __ cmp(ecx, isolate()->factory()->hash_table_map());
- __ j(equal, if_false);
-
- // Look for valueOf string in the descriptor array, and indicate false if
- // found. Since we omit an enumeration index check, if it is added via a
- // transition that shares its descriptor array, this is a false positive.
- Label entry, loop, done;
-
- // Skip loop if no descriptors are valid.
- __ NumberOfOwnDescriptors(ecx, ebx);
- __ cmp(ecx, 0);
- __ j(equal, &done);
-
- __ LoadInstanceDescriptors(ebx, ebx);
- // ebx: descriptor array.
- // ecx: valid entries in the descriptor array.
- // Calculate the end of the descriptor array.
- STATIC_ASSERT(kSmiTag == 0);
- STATIC_ASSERT(kSmiTagSize == 1);
- STATIC_ASSERT(kPointerSize == 4);
- __ imul(ecx, ecx, DescriptorArray::kDescriptorSize);
- __ lea(ecx, Operand(ebx, ecx, times_4, DescriptorArray::kFirstOffset));
- // Calculate location of the first key name.
- __ add(ebx, Immediate(DescriptorArray::kFirstOffset));
- // Loop through all the keys in the descriptor array. If one of these is the
- // internalized string "valueOf" the result is false.
- __ jmp(&entry);
- __ bind(&loop);
- __ mov(edx, FieldOperand(ebx, 0));
- __ cmp(edx, isolate()->factory()->valueOf_string());
- __ j(equal, if_false);
- __ add(ebx, Immediate(DescriptorArray::kDescriptorSize * kPointerSize));
- __ bind(&entry);
- __ cmp(ebx, ecx);
- __ j(not_equal, &loop);
-
- __ bind(&done);
-
- // Reload map as register ebx was used as temporary above.
- __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
-
- // Set the bit in the map to indicate that there is no local valueOf field.
- __ or_(FieldOperand(ebx, Map::kBitField2Offset),
- Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
-
- __ bind(&skip_lookup);
-
- // If a valueOf property is not found on the object check that its
- // prototype is the un-modified String prototype. If not result is false.
- __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset));
- __ JumpIfSmi(ecx, if_false);
- __ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset));
- __ mov(edx, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
- __ mov(edx,
- FieldOperand(edx, GlobalObject::kNativeContextOffset));
- __ cmp(ecx,
- ContextOperand(edx,
- Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
- PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
- Split(equal, if_true, if_false, fall_through);
-
- context()->Plug(if_true, if_false);
-}
-
-
void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
}
-void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
- CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- DCHECK(args->length() == 1);
-
- VisitForAccumulatorValue(args->at(0));
-
- Label materialize_true, materialize_false, skip_lookup;
- Label* if_true = NULL;
- Label* if_false = NULL;
- Label* fall_through = NULL;
- context()->PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
-
- __ AssertNotSmi(v0);
-
- __ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
- __ lbu(t0, FieldMemOperand(a1, Map::kBitField2Offset));
- __ And(t0, t0, 1 << Map::kStringWrapperSafeForDefaultValueOf);
- __ Branch(&skip_lookup, ne, t0, Operand(zero_reg));
-
- // Check for fast case object. Generate false result for slow case object.
- __ lw(a2, FieldMemOperand(v0, JSObject::kPropertiesOffset));
- __ lw(a2, FieldMemOperand(a2, HeapObject::kMapOffset));
- __ LoadRoot(t0, Heap::kHashTableMapRootIndex);
- __ Branch(if_false, eq, a2, Operand(t0));
-
- // Look for valueOf name in the descriptor array, and indicate false if
- // found. Since we omit an enumeration index check, if it is added via a
- // transition that shares its descriptor array, this is a false positive.
- Label entry, loop, done;
-
- // Skip loop if no descriptors are valid.
- __ NumberOfOwnDescriptors(a3, a1);
- __ Branch(&done, eq, a3, Operand(zero_reg));
-
- __ LoadInstanceDescriptors(a1, t0);
- // t0: descriptor array.
- // a3: valid entries in the descriptor array.
- STATIC_ASSERT(kSmiTag == 0);
- STATIC_ASSERT(kSmiTagSize == 1);
- STATIC_ASSERT(kPointerSize == 4);
- __ li(at, Operand(DescriptorArray::kDescriptorSize));
- __ Mul(a3, a3, at);
- // Calculate location of the first key name.
- __ Addu(t0, t0, Operand(DescriptorArray::kFirstOffset - kHeapObjectTag));
- // Calculate the end of the descriptor array.
- __ mov(a2, t0);
- __ sll(t1, a3, kPointerSizeLog2);
- __ Addu(a2, a2, t1);
-
- // Loop through all the keys in the descriptor array. If one of these is the
- // string "valueOf" the result is false.
- // The use of t2 to store the valueOf string assumes that it is not otherwise
- // used in the loop below.
- __ LoadRoot(t2, Heap::kvalueOf_stringRootIndex);
- __ jmp(&entry);
- __ bind(&loop);
- __ lw(a3, MemOperand(t0, 0));
- __ Branch(if_false, eq, a3, Operand(t2));
- __ Addu(t0, t0, Operand(DescriptorArray::kDescriptorSize * kPointerSize));
- __ bind(&entry);
- __ Branch(&loop, ne, t0, Operand(a2));
-
- __ bind(&done);
-
- // Set the bit in the map to indicate that there is no local valueOf field.
- __ lbu(a2, FieldMemOperand(a1, Map::kBitField2Offset));
- __ Or(a2, a2, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
- __ sb(a2, FieldMemOperand(a1, Map::kBitField2Offset));
-
- __ bind(&skip_lookup);
-
- // If a valueOf property is not found on the object check that its
- // prototype is the un-modified String prototype. If not result is false.
- __ lw(a2, FieldMemOperand(a1, Map::kPrototypeOffset));
- __ JumpIfSmi(a2, if_false);
- __ lw(a2, FieldMemOperand(a2, HeapObject::kMapOffset));
- __ lw(a3, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
- __ lw(a3, FieldMemOperand(a3, GlobalObject::kNativeContextOffset));
- __ lw(a3, ContextOperand(a3, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
- PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
- Split(eq, a2, Operand(a3), if_true, if_false, fall_through);
-
- context()->Plug(if_true, if_false);
-}
-
-
void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
}
-void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
- CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- DCHECK(args->length() == 1);
-
- VisitForAccumulatorValue(args->at(0));
-
- Label materialize_true, materialize_false, skip_lookup;
- Label* if_true = NULL;
- Label* if_false = NULL;
- Label* fall_through = NULL;
- context()->PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
-
- __ AssertNotSmi(v0);
-
- __ ld(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
- __ lbu(a4, FieldMemOperand(a1, Map::kBitField2Offset));
- __ And(a4, a4, 1 << Map::kStringWrapperSafeForDefaultValueOf);
- __ Branch(&skip_lookup, ne, a4, Operand(zero_reg));
-
- // Check for fast case object. Generate false result for slow case object.
- __ ld(a2, FieldMemOperand(v0, JSObject::kPropertiesOffset));
- __ ld(a2, FieldMemOperand(a2, HeapObject::kMapOffset));
- __ LoadRoot(a4, Heap::kHashTableMapRootIndex);
- __ Branch(if_false, eq, a2, Operand(a4));
-
- // Look for valueOf name in the descriptor array, and indicate false if
- // found. Since we omit an enumeration index check, if it is added via a
- // transition that shares its descriptor array, this is a false positive.
- Label entry, loop, done;
-
- // Skip loop if no descriptors are valid.
- __ NumberOfOwnDescriptors(a3, a1);
- __ Branch(&done, eq, a3, Operand(zero_reg));
-
- __ LoadInstanceDescriptors(a1, a4);
- // a4: descriptor array.
- // a3: valid entries in the descriptor array.
- STATIC_ASSERT(kSmiTag == 0);
- STATIC_ASSERT(kSmiTagSize == 1);
-// Does not need?
-// STATIC_ASSERT(kPointerSize == 4);
- __ li(at, Operand(DescriptorArray::kDescriptorSize));
- __ Dmul(a3, a3, at);
- // Calculate location of the first key name.
- __ Daddu(a4, a4, Operand(DescriptorArray::kFirstOffset - kHeapObjectTag));
- // Calculate the end of the descriptor array.
- __ mov(a2, a4);
- __ dsll(a5, a3, kPointerSizeLog2);
- __ Daddu(a2, a2, a5);
-
- // Loop through all the keys in the descriptor array. If one of these is the
- // string "valueOf" the result is false.
- // The use of a6 to store the valueOf string assumes that it is not otherwise
- // used in the loop below.
- __ LoadRoot(a6, Heap::kvalueOf_stringRootIndex);
- __ jmp(&entry);
- __ bind(&loop);
- __ ld(a3, MemOperand(a4, 0));
- __ Branch(if_false, eq, a3, Operand(a6));
- __ Daddu(a4, a4, Operand(DescriptorArray::kDescriptorSize * kPointerSize));
- __ bind(&entry);
- __ Branch(&loop, ne, a4, Operand(a2));
-
- __ bind(&done);
-
- // Set the bit in the map to indicate that there is no local valueOf field.
- __ lbu(a2, FieldMemOperand(a1, Map::kBitField2Offset));
- __ Or(a2, a2, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
- __ sb(a2, FieldMemOperand(a1, Map::kBitField2Offset));
-
- __ bind(&skip_lookup);
-
- // If a valueOf property is not found on the object check that its
- // prototype is the un-modified String prototype. If not result is false.
- __ ld(a2, FieldMemOperand(a1, Map::kPrototypeOffset));
- __ JumpIfSmi(a2, if_false);
- __ ld(a2, FieldMemOperand(a2, HeapObject::kMapOffset));
- __ ld(a3, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
- __ ld(a3, FieldMemOperand(a3, GlobalObject::kNativeContextOffset));
- __ ld(a3, ContextOperand(a3, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
- PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
- Split(eq, a2, Operand(a3), if_true, if_false, fall_through);
-
- context()->Plug(if_true, if_false);
-}
-
-
void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
}
-void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
- CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- DCHECK(args->length() == 1);
-
- VisitForAccumulatorValue(args->at(0));
-
- Label materialize_true, materialize_false, skip_lookup;
- Label* if_true = NULL;
- Label* if_false = NULL;
- Label* fall_through = NULL;
- context()->PrepareTest(&materialize_true, &materialize_false, &if_true,
- &if_false, &fall_through);
-
- __ AssertNotSmi(r3);
-
- __ LoadP(r4, FieldMemOperand(r3, HeapObject::kMapOffset));
- __ lbz(ip, FieldMemOperand(r4, Map::kBitField2Offset));
- __ andi(r0, ip, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
- __ bne(&skip_lookup, cr0);
-
- // Check for fast case object. Generate false result for slow case object.
- __ LoadP(r5, FieldMemOperand(r3, JSObject::kPropertiesOffset));
- __ LoadP(r5, FieldMemOperand(r5, HeapObject::kMapOffset));
- __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
- __ cmp(r5, ip);
- __ beq(if_false);
-
- // Look for valueOf name in the descriptor array, and indicate false if
- // found. Since we omit an enumeration index check, if it is added via a
- // transition that shares its descriptor array, this is a false positive.
- Label entry, loop, done;
-
- // Skip loop if no descriptors are valid.
- __ NumberOfOwnDescriptors(r6, r4);
- __ cmpi(r6, Operand::Zero());
- __ beq(&done);
-
- __ LoadInstanceDescriptors(r4, r7);
- // r7: descriptor array.
- // r6: valid entries in the descriptor array.
- __ mov(ip, Operand(DescriptorArray::kDescriptorSize));
- __ Mul(r6, r6, ip);
- // Calculate location of the first key name.
- __ addi(r7, r7, Operand(DescriptorArray::kFirstOffset - kHeapObjectTag));
- // Calculate the end of the descriptor array.
- __ mr(r5, r7);
- __ ShiftLeftImm(ip, r6, Operand(kPointerSizeLog2));
- __ add(r5, r5, ip);
-
- // Loop through all the keys in the descriptor array. If one of these is the
- // string "valueOf" the result is false.
- // The use of ip to store the valueOf string assumes that it is not otherwise
- // used in the loop below.
- __ LoadRoot(ip, Heap::kvalueOf_stringRootIndex);
- __ b(&entry);
- __ bind(&loop);
- __ LoadP(r6, MemOperand(r7, 0));
- __ cmp(r6, ip);
- __ beq(if_false);
- __ addi(r7, r7, Operand(DescriptorArray::kDescriptorSize * kPointerSize));
- __ bind(&entry);
- __ cmp(r7, r5);
- __ bne(&loop);
-
- __ bind(&done);
-
- // Set the bit in the map to indicate that there is no local valueOf field.
- __ lbz(r5, FieldMemOperand(r4, Map::kBitField2Offset));
- __ ori(r5, r5, Operand(1 << Map::kStringWrapperSafeForDefaultValueOf));
- __ stb(r5, FieldMemOperand(r4, Map::kBitField2Offset));
-
- __ bind(&skip_lookup);
-
- // If a valueOf property is not found on the object check that its
- // prototype is the un-modified String prototype. If not result is false.
- __ LoadP(r5, FieldMemOperand(r4, Map::kPrototypeOffset));
- __ JumpIfSmi(r5, if_false);
- __ LoadP(r5, FieldMemOperand(r5, HeapObject::kMapOffset));
- __ LoadP(r6, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
- __ LoadP(r6, FieldMemOperand(r6, GlobalObject::kNativeContextOffset));
- __ LoadP(r6,
- ContextOperand(r6, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
- __ cmp(r5, r6);
- PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
- Split(eq, if_true, if_false, fall_through);
-
- context()->Plug(if_true, if_false);
-}
-
-
void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
}
-void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
- CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- DCHECK(args->length() == 1);
-
- VisitForAccumulatorValue(args->at(0));
-
- Label materialize_true, materialize_false, skip_lookup;
- Label* if_true = NULL;
- Label* if_false = NULL;
- Label* fall_through = NULL;
- context()->PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
-
- __ AssertNotSmi(rax);
-
- // Check whether this map has already been checked to be safe for default
- // valueOf.
- __ movp(rbx, FieldOperand(rax, HeapObject::kMapOffset));
- __ testb(FieldOperand(rbx, Map::kBitField2Offset),
- Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
- __ j(not_zero, &skip_lookup);
-
- // Check for fast case object. Generate false result for slow case object.
- __ movp(rcx, FieldOperand(rax, JSObject::kPropertiesOffset));
- __ movp(rcx, FieldOperand(rcx, HeapObject::kMapOffset));
- __ CompareRoot(rcx, Heap::kHashTableMapRootIndex);
- __ j(equal, if_false);
-
- // Look for valueOf string in the descriptor array, and indicate false if
- // found. Since we omit an enumeration index check, if it is added via a
- // transition that shares its descriptor array, this is a false positive.
- Label entry, loop, done;
-
- // Skip loop if no descriptors are valid.
- __ NumberOfOwnDescriptors(rcx, rbx);
- __ cmpp(rcx, Immediate(0));
- __ j(equal, &done);
-
- __ LoadInstanceDescriptors(rbx, r8);
- // rbx: descriptor array.
- // rcx: valid entries in the descriptor array.
- // Calculate the end of the descriptor array.
- __ imulp(rcx, rcx, Immediate(DescriptorArray::kDescriptorSize));
- __ leap(rcx,
- Operand(r8, rcx, times_pointer_size, DescriptorArray::kFirstOffset));
- // Calculate location of the first key name.
- __ addp(r8, Immediate(DescriptorArray::kFirstOffset));
- // Loop through all the keys in the descriptor array. If one of these is the
- // internalized string "valueOf" the result is false.
- __ jmp(&entry);
- __ bind(&loop);
- __ movp(rdx, FieldOperand(r8, 0));
- __ CompareRoot(rdx, Heap::kvalueOf_stringRootIndex);
- __ j(equal, if_false);
- __ addp(r8, Immediate(DescriptorArray::kDescriptorSize * kPointerSize));
- __ bind(&entry);
- __ cmpp(r8, rcx);
- __ j(not_equal, &loop);
-
- __ bind(&done);
-
- // Set the bit in the map to indicate that there is no local valueOf field.
- __ orp(FieldOperand(rbx, Map::kBitField2Offset),
- Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
-
- __ bind(&skip_lookup);
-
- // If a valueOf property is not found on the object check that its
- // prototype is the un-modified String prototype. If not result is false.
- __ movp(rcx, FieldOperand(rbx, Map::kPrototypeOffset));
- __ testp(rcx, Immediate(kSmiTagMask));
- __ j(zero, if_false);
- __ movp(rcx, FieldOperand(rcx, HeapObject::kMapOffset));
- __ movp(rdx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
- __ movp(rdx, FieldOperand(rdx, GlobalObject::kNativeContextOffset));
- __ cmpp(rcx,
- ContextOperand(rdx, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
- PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
- Split(equal, if_true, if_false, fall_through);
-
- context()->Plug(if_true, if_false);
-}
-
-
void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
}
-void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
- CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- DCHECK(args->length() == 1);
-
- VisitForAccumulatorValue(args->at(0));
-
- Label materialize_true, materialize_false, skip_lookup;
- Label* if_true = NULL;
- Label* if_false = NULL;
- Label* fall_through = NULL;
- context()->PrepareTest(&materialize_true, &materialize_false,
- &if_true, &if_false, &fall_through);
-
- __ AssertNotSmi(eax);
-
- // Check whether this map has already been checked to be safe for default
- // valueOf.
- __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
- __ test_b(FieldOperand(ebx, Map::kBitField2Offset),
- 1 << Map::kStringWrapperSafeForDefaultValueOf);
- __ j(not_zero, &skip_lookup);
-
- // Check for fast case object. Return false for slow case objects.
- __ mov(ecx, FieldOperand(eax, JSObject::kPropertiesOffset));
- __ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset));
- __ cmp(ecx, isolate()->factory()->hash_table_map());
- __ j(equal, if_false);
-
- // Look for valueOf string in the descriptor array, and indicate false if
- // found. Since we omit an enumeration index check, if it is added via a
- // transition that shares its descriptor array, this is a false positive.
- Label entry, loop, done;
-
- // Skip loop if no descriptors are valid.
- __ NumberOfOwnDescriptors(ecx, ebx);
- __ cmp(ecx, 0);
- __ j(equal, &done);
-
- __ LoadInstanceDescriptors(ebx, ebx);
- // ebx: descriptor array.
- // ecx: valid entries in the descriptor array.
- // Calculate the end of the descriptor array.
- STATIC_ASSERT(kSmiTag == 0);
- STATIC_ASSERT(kSmiTagSize == 1);
- STATIC_ASSERT(kPointerSize == 4);
- __ imul(ecx, ecx, DescriptorArray::kDescriptorSize);
- __ lea(ecx, Operand(ebx, ecx, times_4, DescriptorArray::kFirstOffset));
- // Calculate location of the first key name.
- __ add(ebx, Immediate(DescriptorArray::kFirstOffset));
- // Loop through all the keys in the descriptor array. If one of these is the
- // internalized string "valueOf" the result is false.
- __ jmp(&entry);
- __ bind(&loop);
- __ mov(edx, FieldOperand(ebx, 0));
- __ cmp(edx, isolate()->factory()->valueOf_string());
- __ j(equal, if_false);
- __ add(ebx, Immediate(DescriptorArray::kDescriptorSize * kPointerSize));
- __ bind(&entry);
- __ cmp(ebx, ecx);
- __ j(not_equal, &loop);
-
- __ bind(&done);
-
- // Reload map as register ebx was used as temporary above.
- __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
-
- // Set the bit in the map to indicate that there is no local valueOf field.
- __ or_(FieldOperand(ebx, Map::kBitField2Offset),
- Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf));
-
- __ bind(&skip_lookup);
-
- // If a valueOf property is not found on the object check that its
- // prototype is the un-modified String prototype. If not result is false.
- __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset));
- __ JumpIfSmi(ecx, if_false);
- __ mov(ecx, FieldOperand(ecx, HeapObject::kMapOffset));
- __ mov(edx, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
- __ mov(edx,
- FieldOperand(edx, GlobalObject::kNativeContextOffset));
- __ cmp(ecx,
- ContextOperand(edx,
- Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX));
- PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
- Split(equal, if_true, if_false, fall_through);
-
- context()->Plug(if_true, if_false);
-}
-
-
void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
left = BuildNumberToString(left, left_type);
} else if (!left_type->Is(Type::String())) {
DCHECK(right_type->Is(Type::String()));
- HValue* function =
- AddLoadJSBuiltin(Context::STRING_ADD_RIGHT_BUILTIN_INDEX);
+ // TODO(bmeurer): We might want to optimize this, because we already
+ // know that the right hand side is a string.
Add<HPushArguments>(left, right);
- return AddUncasted<HInvokeFunction>(function, 2);
+ return AddUncasted<HCallRuntime>(Runtime::FunctionForId(Runtime::kAdd),
+ 2);
}
// Convert right argument as necessary.
right = BuildNumberToString(right, right_type);
} else if (!right_type->Is(Type::String())) {
DCHECK(left_type->Is(Type::String()));
- HValue* function =
- AddLoadJSBuiltin(Context::STRING_ADD_LEFT_BUILTIN_INDEX);
+ // TODO(bmeurer): We might want to optimize this, because we already
+ // know that the left hand side is a string.
Add<HPushArguments>(left, right);
- return AddUncasted<HInvokeFunction>(function, 2);
+ return AddUncasted<HCallRuntime>(Runtime::FunctionForId(Runtime::kAdd),
+ 2);
}
}
// Bit positions for bit field 2
static const int kIsExtensible = 0;
- static const int kStringWrapperSafeForDefaultValueOf = 1;
+ // Bit 1 is free.
class IsPrototypeMapBits : public BitField<bool, 2, 1> {};
class ElementsKindBits: public BitField<ElementsKind, 3, 5> {};
}
-
-/* -----------------------------------
- - - - A r i t h m e t i c - - -
- -----------------------------------
-*/
-
-// Left operand (this) is already a string.
-function STRING_ADD_LEFT(y) {
- if (!IS_STRING(y)) {
- if (IS_STRING_WRAPPER(y) && %_IsStringWrapperSafeForDefaultValueOf(y)) {
- y = %_ValueOf(y);
- } else {
- y = IS_NUMBER(y)
- ? %_NumberToString(y)
- : %to_string_fun(%to_primitive(y, NO_HINT));
- }
- }
- return %_StringAdd(this, y);
-}
-
-
-// Right operand (y) is already a string.
-function STRING_ADD_RIGHT(y) {
- var x = this;
- if (!IS_STRING(x)) {
- if (IS_STRING_WRAPPER(x) && %_IsStringWrapperSafeForDefaultValueOf(x)) {
- x = %_ValueOf(x);
- } else {
- x = IS_NUMBER(x)
- ? %_NumberToString(x)
- : %to_string_fun(%to_primitive(x, NO_HINT));
- }
- }
- return %_StringAdd(x, y);
-}
-
-
/* -----------------------------
- - - H e l p e r s - - -
-----------------------------
"equals_builtin", EQUALS,
"reflect_apply_prepare_builtin", REFLECT_APPLY_PREPARE,
"reflect_construct_prepare_builtin", REFLECT_CONSTRUCT_PREPARE,
- "string_add_left_builtin", STRING_ADD_LEFT,
- "string_add_right_builtin", STRING_ADD_RIGHT,
]);
%InstallToContext([
}
-RUNTIME_FUNCTION(Runtime_IsStringWrapperSafeForDefaultValueOf) {
- UNIMPLEMENTED();
- return NULL;
-}
-
-
RUNTIME_FUNCTION(Runtime_StringGetLength) {
HandleScope scope(isolate);
DCHECK(args.length() == 1);
F(TwoByteSeqStringGetChar, 2, 1) \
F(TwoByteSeqStringSetChar, 3, 1) \
F(StringCharCodeAt, 2, 1) \
- F(IsStringWrapperSafeForDefaultValueOf, 1, 1) \
F(StringGetLength, 1, 1)