OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1593 __ push(rax); // Save result on the stack | 1593 __ push(rax); // Save result on the stack |
1594 result_saved = true; | 1594 result_saved = true; |
1595 } | 1595 } |
1596 switch (property->kind()) { | 1596 switch (property->kind()) { |
1597 case ObjectLiteral::Property::CONSTANT: | 1597 case ObjectLiteral::Property::CONSTANT: |
1598 UNREACHABLE(); | 1598 UNREACHABLE(); |
1599 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 1599 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
1600 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); | 1600 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); |
1601 // Fall through. | 1601 // Fall through. |
1602 case ObjectLiteral::Property::COMPUTED: | 1602 case ObjectLiteral::Property::COMPUTED: |
1603 if (key->handle()->IsSymbol()) { | 1603 if (key->handle()->IsInternalizedString()) { |
1604 if (property->emit_store()) { | 1604 if (property->emit_store()) { |
1605 VisitForAccumulatorValue(value); | 1605 VisitForAccumulatorValue(value); |
1606 __ Move(rcx, key->handle()); | 1606 __ Move(rcx, key->handle()); |
1607 __ movq(rdx, Operand(rsp, 0)); | 1607 __ movq(rdx, Operand(rsp, 0)); |
1608 Handle<Code> ic = is_classic_mode() | 1608 Handle<Code> ic = is_classic_mode() |
1609 ? isolate()->builtins()->StoreIC_Initialize() | 1609 ? isolate()->builtins()->StoreIC_Initialize() |
1610 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 1610 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
1611 CallIC(ic, RelocInfo::CODE_TARGET, key->LiteralFeedbackId()); | 1611 CallIC(ic, RelocInfo::CODE_TARGET, key->LiteralFeedbackId()); |
1612 PrepareForBailoutForId(key->id(), NO_REGISTERS); | 1612 PrepareForBailoutForId(key->id(), NO_REGISTERS); |
1613 } else { | 1613 } else { |
(...skipping 980 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2594 __ testb(FieldOperand(rbx, Map::kBitField2Offset), | 2594 __ testb(FieldOperand(rbx, Map::kBitField2Offset), |
2595 Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf)); | 2595 Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf)); |
2596 __ j(not_zero, if_true); | 2596 __ j(not_zero, if_true); |
2597 | 2597 |
2598 // Check for fast case object. Generate false result for slow case object. | 2598 // Check for fast case object. Generate false result for slow case object. |
2599 __ movq(rcx, FieldOperand(rax, JSObject::kPropertiesOffset)); | 2599 __ movq(rcx, FieldOperand(rax, JSObject::kPropertiesOffset)); |
2600 __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset)); | 2600 __ movq(rcx, FieldOperand(rcx, HeapObject::kMapOffset)); |
2601 __ CompareRoot(rcx, Heap::kHashTableMapRootIndex); | 2601 __ CompareRoot(rcx, Heap::kHashTableMapRootIndex); |
2602 __ j(equal, if_false); | 2602 __ j(equal, if_false); |
2603 | 2603 |
2604 // Look for valueOf symbol in the descriptor array, and indicate false if | 2604 // Look for valueOf string in the descriptor array, and indicate false if |
2605 // found. Since we omit an enumeration index check, if it is added via a | 2605 // found. Since we omit an enumeration index check, if it is added via a |
2606 // transition that shares its descriptor array, this is a false positive. | 2606 // transition that shares its descriptor array, this is a false positive. |
2607 Label entry, loop, done; | 2607 Label entry, loop, done; |
2608 | 2608 |
2609 // Skip loop if no descriptors are valid. | 2609 // Skip loop if no descriptors are valid. |
2610 __ NumberOfOwnDescriptors(rcx, rbx); | 2610 __ NumberOfOwnDescriptors(rcx, rbx); |
2611 __ cmpq(rcx, Immediate(0)); | 2611 __ cmpq(rcx, Immediate(0)); |
2612 __ j(equal, &done); | 2612 __ j(equal, &done); |
2613 | 2613 |
2614 __ LoadInstanceDescriptors(rbx, rbx); | 2614 __ LoadInstanceDescriptors(rbx, rbx); |
2615 // rbx: descriptor array. | 2615 // rbx: descriptor array. |
2616 // rcx: valid entries in the descriptor array. | 2616 // rcx: valid entries in the descriptor array. |
2617 // Calculate the end of the descriptor array. | 2617 // Calculate the end of the descriptor array. |
2618 __ imul(rcx, rcx, Immediate(DescriptorArray::kDescriptorSize)); | 2618 __ imul(rcx, rcx, Immediate(DescriptorArray::kDescriptorSize)); |
2619 SmiIndex index = masm_->SmiToIndex(rdx, rcx, kPointerSizeLog2); | 2619 SmiIndex index = masm_->SmiToIndex(rdx, rcx, kPointerSizeLog2); |
2620 __ lea(rcx, | 2620 __ lea(rcx, |
2621 Operand( | 2621 Operand( |
2622 rbx, index.reg, index.scale, DescriptorArray::kFirstOffset)); | 2622 rbx, index.reg, index.scale, DescriptorArray::kFirstOffset)); |
2623 // Calculate location of the first key name. | 2623 // Calculate location of the first key name. |
2624 __ addq(rbx, Immediate(DescriptorArray::kFirstOffset)); | 2624 __ addq(rbx, Immediate(DescriptorArray::kFirstOffset)); |
2625 // Loop through all the keys in the descriptor array. If one of these is the | 2625 // Loop through all the keys in the descriptor array. If one of these is the |
2626 // symbol valueOf the result is false. | 2626 // internalized string "valueOf" the result is false. |
2627 __ jmp(&entry); | 2627 __ jmp(&entry); |
2628 __ bind(&loop); | 2628 __ bind(&loop); |
2629 __ movq(rdx, FieldOperand(rbx, 0)); | 2629 __ movq(rdx, FieldOperand(rbx, 0)); |
2630 __ Cmp(rdx, FACTORY->value_of_symbol()); | 2630 __ Cmp(rdx, FACTORY->value_of_string()); |
2631 __ j(equal, if_false); | 2631 __ j(equal, if_false); |
2632 __ addq(rbx, Immediate(DescriptorArray::kDescriptorSize * kPointerSize)); | 2632 __ addq(rbx, Immediate(DescriptorArray::kDescriptorSize * kPointerSize)); |
2633 __ bind(&entry); | 2633 __ bind(&entry); |
2634 __ cmpq(rbx, rcx); | 2634 __ cmpq(rbx, rcx); |
2635 __ j(not_equal, &loop); | 2635 __ j(not_equal, &loop); |
2636 | 2636 |
2637 __ bind(&done); | 2637 __ bind(&done); |
2638 // Reload map as register rbx was used as temporary above. | 2638 // Reload map as register rbx was used as temporary above. |
2639 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | 2639 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); |
2640 | 2640 |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2855 __ j(not_equal, &non_function_constructor); | 2855 __ j(not_equal, &non_function_constructor); |
2856 | 2856 |
2857 // rax now contains the constructor function. Grab the | 2857 // rax now contains the constructor function. Grab the |
2858 // instance class name from there. | 2858 // instance class name from there. |
2859 __ movq(rax, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset)); | 2859 __ movq(rax, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset)); |
2860 __ movq(rax, FieldOperand(rax, SharedFunctionInfo::kInstanceClassNameOffset)); | 2860 __ movq(rax, FieldOperand(rax, SharedFunctionInfo::kInstanceClassNameOffset)); |
2861 __ jmp(&done); | 2861 __ jmp(&done); |
2862 | 2862 |
2863 // Functions have class 'Function'. | 2863 // Functions have class 'Function'. |
2864 __ bind(&function); | 2864 __ bind(&function); |
2865 __ Move(rax, isolate()->factory()->function_class_symbol()); | 2865 __ Move(rax, isolate()->factory()->function_class_string()); |
2866 __ jmp(&done); | 2866 __ jmp(&done); |
2867 | 2867 |
2868 // Objects with a non-function constructor have class 'Object'. | 2868 // Objects with a non-function constructor have class 'Object'. |
2869 __ bind(&non_function_constructor); | 2869 __ bind(&non_function_constructor); |
2870 __ Move(rax, isolate()->factory()->Object_symbol()); | 2870 __ Move(rax, isolate()->factory()->Object_string()); |
2871 __ jmp(&done); | 2871 __ jmp(&done); |
2872 | 2872 |
2873 // Non-JS objects have class null. | 2873 // Non-JS objects have class null. |
2874 __ bind(&null); | 2874 __ bind(&null); |
2875 __ LoadRoot(rax, Heap::kNullValueRootIndex); | 2875 __ LoadRoot(rax, Heap::kNullValueRootIndex); |
2876 | 2876 |
2877 // All done. | 2877 // All done. |
2878 __ bind(&done); | 2878 __ bind(&done); |
2879 | 2879 |
2880 context()->Plug(rax); | 2880 context()->Plug(rax); |
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3220 &need_conversion, | 3220 &need_conversion, |
3221 &need_conversion, | 3221 &need_conversion, |
3222 &index_out_of_range, | 3222 &index_out_of_range, |
3223 STRING_INDEX_IS_NUMBER); | 3223 STRING_INDEX_IS_NUMBER); |
3224 generator.GenerateFast(masm_); | 3224 generator.GenerateFast(masm_); |
3225 __ jmp(&done); | 3225 __ jmp(&done); |
3226 | 3226 |
3227 __ bind(&index_out_of_range); | 3227 __ bind(&index_out_of_range); |
3228 // When the index is out of range, the spec requires us to return | 3228 // When the index is out of range, the spec requires us to return |
3229 // the empty string. | 3229 // the empty string. |
3230 __ LoadRoot(result, Heap::kEmptyStringRootIndex); | 3230 __ LoadRoot(result, Heap::kempty_stringRootIndex); |
3231 __ jmp(&done); | 3231 __ jmp(&done); |
3232 | 3232 |
3233 __ bind(&need_conversion); | 3233 __ bind(&need_conversion); |
3234 // Move smi zero into the result register, which will trigger | 3234 // Move smi zero into the result register, which will trigger |
3235 // conversion. | 3235 // conversion. |
3236 __ Move(result, Smi::FromInt(0)); | 3236 __ Move(result, Smi::FromInt(0)); |
3237 __ jmp(&done); | 3237 __ jmp(&done); |
3238 | 3238 |
3239 NopRuntimeCallHelper call_helper; | 3239 NopRuntimeCallHelper call_helper; |
3240 generator.GenerateSlow(masm_, call_helper); | 3240 generator.GenerateSlow(masm_, call_helper); |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3546 __ j(not_equal, &bailout); | 3546 __ j(not_equal, &bailout); |
3547 | 3547 |
3548 // Check that the array has fast elements. | 3548 // Check that the array has fast elements. |
3549 __ CheckFastElements(scratch, &bailout); | 3549 __ CheckFastElements(scratch, &bailout); |
3550 | 3550 |
3551 // Array has fast elements, so its length must be a smi. | 3551 // Array has fast elements, so its length must be a smi. |
3552 // If the array has length zero, return the empty string. | 3552 // If the array has length zero, return the empty string. |
3553 __ movq(array_length, FieldOperand(array, JSArray::kLengthOffset)); | 3553 __ movq(array_length, FieldOperand(array, JSArray::kLengthOffset)); |
3554 __ SmiCompare(array_length, Smi::FromInt(0)); | 3554 __ SmiCompare(array_length, Smi::FromInt(0)); |
3555 __ j(not_zero, &non_trivial_array); | 3555 __ j(not_zero, &non_trivial_array); |
3556 __ LoadRoot(rax, Heap::kEmptyStringRootIndex); | 3556 __ LoadRoot(rax, Heap::kempty_stringRootIndex); |
3557 __ jmp(&return_result); | 3557 __ jmp(&return_result); |
3558 | 3558 |
3559 // Save the array length on the stack. | 3559 // Save the array length on the stack. |
3560 __ bind(&non_trivial_array); | 3560 __ bind(&non_trivial_array); |
3561 __ SmiToInteger32(array_length, array_length); | 3561 __ SmiToInteger32(array_length, array_length); |
3562 __ movl(array_length_operand, array_length); | 3562 __ movl(array_length_operand, array_length); |
3563 | 3563 |
3564 // Save the FixedArray containing array's elements. | 3564 // Save the FixedArray containing array's elements. |
3565 // End of array's live range. | 3565 // End of array's live range. |
3566 elements = array; | 3566 elements = array; |
(...skipping 641 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4208 Label* if_false = NULL; | 4208 Label* if_false = NULL; |
4209 Label* fall_through = NULL; | 4209 Label* fall_through = NULL; |
4210 context()->PrepareTest(&materialize_true, &materialize_false, | 4210 context()->PrepareTest(&materialize_true, &materialize_false, |
4211 &if_true, &if_false, &fall_through); | 4211 &if_true, &if_false, &fall_through); |
4212 | 4212 |
4213 { AccumulatorValueContext context(this); | 4213 { AccumulatorValueContext context(this); |
4214 VisitForTypeofValue(sub_expr); | 4214 VisitForTypeofValue(sub_expr); |
4215 } | 4215 } |
4216 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 4216 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
4217 | 4217 |
4218 if (check->Equals(isolate()->heap()->number_symbol())) { | 4218 if (check->Equals(isolate()->heap()->number_string())) { |
4219 __ JumpIfSmi(rax, if_true); | 4219 __ JumpIfSmi(rax, if_true); |
4220 __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset)); | 4220 __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset)); |
4221 __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex); | 4221 __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex); |
4222 Split(equal, if_true, if_false, fall_through); | 4222 Split(equal, if_true, if_false, fall_through); |
4223 } else if (check->Equals(isolate()->heap()->string_symbol())) { | 4223 } else if (check->Equals(isolate()->heap()->string_string())) { |
4224 __ JumpIfSmi(rax, if_false); | 4224 __ JumpIfSmi(rax, if_false); |
4225 // Check for undetectable objects => false. | 4225 // Check for undetectable objects => false. |
4226 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx); | 4226 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx); |
4227 __ j(above_equal, if_false); | 4227 __ j(above_equal, if_false); |
4228 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), | 4228 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), |
4229 Immediate(1 << Map::kIsUndetectable)); | 4229 Immediate(1 << Map::kIsUndetectable)); |
4230 Split(zero, if_true, if_false, fall_through); | 4230 Split(zero, if_true, if_false, fall_through); |
4231 } else if (check->Equals(isolate()->heap()->boolean_symbol())) { | 4231 } else if (check->Equals(isolate()->heap()->boolean_string())) { |
4232 __ CompareRoot(rax, Heap::kTrueValueRootIndex); | 4232 __ CompareRoot(rax, Heap::kTrueValueRootIndex); |
4233 __ j(equal, if_true); | 4233 __ j(equal, if_true); |
4234 __ CompareRoot(rax, Heap::kFalseValueRootIndex); | 4234 __ CompareRoot(rax, Heap::kFalseValueRootIndex); |
4235 Split(equal, if_true, if_false, fall_through); | 4235 Split(equal, if_true, if_false, fall_through); |
4236 } else if (FLAG_harmony_typeof && | 4236 } else if (FLAG_harmony_typeof && |
4237 check->Equals(isolate()->heap()->null_symbol())) { | 4237 check->Equals(isolate()->heap()->null_string())) { |
4238 __ CompareRoot(rax, Heap::kNullValueRootIndex); | 4238 __ CompareRoot(rax, Heap::kNullValueRootIndex); |
4239 Split(equal, if_true, if_false, fall_through); | 4239 Split(equal, if_true, if_false, fall_through); |
4240 } else if (check->Equals(isolate()->heap()->undefined_symbol())) { | 4240 } else if (check->Equals(isolate()->heap()->undefined_string())) { |
4241 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); | 4241 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); |
4242 __ j(equal, if_true); | 4242 __ j(equal, if_true); |
4243 __ JumpIfSmi(rax, if_false); | 4243 __ JumpIfSmi(rax, if_false); |
4244 // Check for undetectable objects => true. | 4244 // Check for undetectable objects => true. |
4245 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); | 4245 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); |
4246 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), | 4246 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), |
4247 Immediate(1 << Map::kIsUndetectable)); | 4247 Immediate(1 << Map::kIsUndetectable)); |
4248 Split(not_zero, if_true, if_false, fall_through); | 4248 Split(not_zero, if_true, if_false, fall_through); |
4249 } else if (check->Equals(isolate()->heap()->function_symbol())) { | 4249 } else if (check->Equals(isolate()->heap()->function_string())) { |
4250 __ JumpIfSmi(rax, if_false); | 4250 __ JumpIfSmi(rax, if_false); |
4251 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); | 4251 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); |
4252 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rdx); | 4252 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rdx); |
4253 __ j(equal, if_true); | 4253 __ j(equal, if_true); |
4254 __ CmpInstanceType(rdx, JS_FUNCTION_PROXY_TYPE); | 4254 __ CmpInstanceType(rdx, JS_FUNCTION_PROXY_TYPE); |
4255 Split(equal, if_true, if_false, fall_through); | 4255 Split(equal, if_true, if_false, fall_through); |
4256 } else if (check->Equals(isolate()->heap()->object_symbol())) { | 4256 } else if (check->Equals(isolate()->heap()->object_string())) { |
4257 __ JumpIfSmi(rax, if_false); | 4257 __ JumpIfSmi(rax, if_false); |
4258 if (!FLAG_harmony_typeof) { | 4258 if (!FLAG_harmony_typeof) { |
4259 __ CompareRoot(rax, Heap::kNullValueRootIndex); | 4259 __ CompareRoot(rax, Heap::kNullValueRootIndex); |
4260 __ j(equal, if_true); | 4260 __ j(equal, if_true); |
4261 } | 4261 } |
4262 __ CmpObjectType(rax, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, rdx); | 4262 __ CmpObjectType(rax, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, rdx); |
4263 __ j(below, if_false); | 4263 __ j(below, if_false); |
4264 __ CmpInstanceType(rdx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); | 4264 __ CmpInstanceType(rdx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); |
4265 __ j(above, if_false); | 4265 __ j(above, if_false); |
4266 // Check for undetectable objects => false. | 4266 // Check for undetectable objects => false. |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4526 *context_length = 0; | 4526 *context_length = 0; |
4527 return previous_; | 4527 return previous_; |
4528 } | 4528 } |
4529 | 4529 |
4530 | 4530 |
4531 #undef __ | 4531 #undef __ |
4532 | 4532 |
4533 } } // namespace v8::internal | 4533 } } // namespace v8::internal |
4534 | 4534 |
4535 #endif // V8_TARGET_ARCH_X64 | 4535 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |