OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 3040 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3051 primitive.Bind(); | 3051 primitive.Bind(); |
3052 frame_->EmitPush(eax); | 3052 frame_->EmitPush(eax); |
3053 frame_->InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION, 1); | 3053 frame_->InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION, 1); |
3054 // function call returns the value in eax, which is where we want it below | 3054 // function call returns the value in eax, which is where we want it below |
3055 | 3055 |
3056 jsobject.Bind(); | 3056 jsobject.Bind(); |
3057 // Get the set of properties (as a FixedArray or Map). | 3057 // Get the set of properties (as a FixedArray or Map). |
3058 // eax: value to be iterated over | 3058 // eax: value to be iterated over |
3059 frame_->EmitPush(eax); // push the object being iterated over (slot 4) | 3059 frame_->EmitPush(eax); // push the object being iterated over (slot 4) |
3060 | 3060 |
| 3061 // Check cache validity in generated code. This is a fast case for |
| 3062 // the JSObject::IsSimpleEnum cache validity checks. If we cannot |
| 3063 // guarantee cache validity, call the runtime system to check cache |
| 3064 // validity or get the property names in a fixed array. |
| 3065 JumpTarget call_runtime; |
| 3066 JumpTarget loop(JumpTarget::BIDIRECTIONAL); |
| 3067 JumpTarget check_prototype; |
| 3068 JumpTarget use_cache; |
| 3069 __ mov(ecx, eax); |
| 3070 loop.Bind(); |
| 3071 // Check that there are no elements. |
| 3072 __ mov(edx, FieldOperand(ecx, JSObject::kElementsOffset)); |
| 3073 __ cmp(Operand(edx), Immediate(Factory::empty_fixed_array())); |
| 3074 call_runtime.Branch(not_equal); |
| 3075 // Check that instance descriptors are not empty so that we can |
| 3076 // check for an enum cache. Leave the map in ebx for the subsequent |
| 3077 // prototype load. |
| 3078 __ mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset)); |
| 3079 __ mov(edx, FieldOperand(ebx, Map::kInstanceDescriptorsOffset)); |
| 3080 __ cmp(Operand(edx), Immediate(Factory::empty_descriptor_array())); |
| 3081 call_runtime.Branch(equal); |
| 3082 // Check that there in an enum cache in the non-empty instance |
| 3083 // descriptors. This is the case if the next enumeration index |
| 3084 // field does not contain a smi. |
| 3085 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumerationIndexOffset)); |
| 3086 __ test(edx, Immediate(kSmiTagMask)); |
| 3087 call_runtime.Branch(zero); |
| 3088 // For all objects but the receiver, check that the cache is empty. |
| 3089 __ cmp(ecx, Operand(eax)); |
| 3090 check_prototype.Branch(equal); |
| 3091 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumCacheBridgeCacheOffset)); |
| 3092 __ cmp(Operand(edx), Immediate(Factory::empty_fixed_array())); |
| 3093 call_runtime.Branch(not_equal); |
| 3094 check_prototype.Bind(); |
| 3095 // Load the prototype from the map and loop if non-null. |
| 3096 __ mov(ecx, FieldOperand(ebx, Map::kPrototypeOffset)); |
| 3097 __ cmp(Operand(ecx), Immediate(Factory::null_value())); |
| 3098 loop.Branch(not_equal); |
| 3099 // The enum cache is valid. Load the map of the object being |
| 3100 // iterated over and use the cache for the iteration. |
| 3101 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); |
| 3102 use_cache.Jump(); |
| 3103 |
| 3104 call_runtime.Bind(); |
| 3105 // Call the runtime to get the property names for the object. |
3061 frame_->EmitPush(eax); // push the Object (slot 4) for the runtime call | 3106 frame_->EmitPush(eax); // push the Object (slot 4) for the runtime call |
3062 frame_->CallRuntime(Runtime::kGetPropertyNamesFast, 1); | 3107 frame_->CallRuntime(Runtime::kGetPropertyNamesFast, 1); |
3063 | 3108 |
3064 // If we got a Map, we can do a fast modification check. | 3109 // If we got a map from the runtime call, we can do a fast |
3065 // Otherwise, we got a FixedArray, and we have to do a slow check. | 3110 // modification check. Otherwise, we got a fixed array, and we have |
| 3111 // to do a slow check. |
3066 // eax: map or fixed array (result from call to | 3112 // eax: map or fixed array (result from call to |
3067 // Runtime::kGetPropertyNamesFast) | 3113 // Runtime::kGetPropertyNamesFast) |
3068 __ mov(edx, Operand(eax)); | 3114 __ mov(edx, Operand(eax)); |
3069 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); | 3115 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
3070 __ cmp(ecx, Factory::meta_map()); | 3116 __ cmp(ecx, Factory::meta_map()); |
3071 fixed_array.Branch(not_equal); | 3117 fixed_array.Branch(not_equal); |
3072 | 3118 |
| 3119 use_cache.Bind(); |
3073 // Get enum cache | 3120 // Get enum cache |
3074 // eax: map (result from call to Runtime::kGetPropertyNamesFast) | 3121 // eax: map (either the result from a call to |
| 3122 // Runtime::kGetPropertyNamesFast or has been fetched directly from |
| 3123 // the object) |
3075 __ mov(ecx, Operand(eax)); | 3124 __ mov(ecx, Operand(eax)); |
| 3125 |
3076 __ mov(ecx, FieldOperand(ecx, Map::kInstanceDescriptorsOffset)); | 3126 __ mov(ecx, FieldOperand(ecx, Map::kInstanceDescriptorsOffset)); |
3077 // Get the bridge array held in the enumeration index field. | 3127 // Get the bridge array held in the enumeration index field. |
3078 __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset)); | 3128 __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset)); |
3079 // Get the cache from the bridge array. | 3129 // Get the cache from the bridge array. |
3080 __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset)); | 3130 __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset)); |
3081 | 3131 |
3082 frame_->EmitPush(eax); // <- slot 3 | 3132 frame_->EmitPush(eax); // <- slot 3 |
3083 frame_->EmitPush(edx); // <- slot 2 | 3133 frame_->EmitPush(edx); // <- slot 2 |
3084 __ mov(eax, FieldOperand(edx, FixedArray::kLengthOffset)); | 3134 __ mov(eax, FieldOperand(edx, FixedArray::kLengthOffset)); |
3085 __ shl(eax, kSmiTagSize); | 3135 __ shl(eax, kSmiTagSize); |
(...skipping 5082 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8168 | 8218 |
8169 int CompareStub::MinorKey() { | 8219 int CompareStub::MinorKey() { |
8170 // Encode the two parameters in a unique 16 bit value. | 8220 // Encode the two parameters in a unique 16 bit value. |
8171 ASSERT(static_cast<unsigned>(cc_) < (1 << 15)); | 8221 ASSERT(static_cast<unsigned>(cc_) < (1 << 15)); |
8172 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0); | 8222 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0); |
8173 } | 8223 } |
8174 | 8224 |
8175 #undef __ | 8225 #undef __ |
8176 | 8226 |
8177 } } // namespace v8::internal | 8227 } } // namespace v8::internal |
OLD | NEW |