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 5054 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5065 Handle<Object> result; | 5065 Handle<Object> result; |
5066 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 5066 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
5067 isolate, result, | 5067 isolate, result, |
5068 Runtime::GetObjectProperty(isolate, object, key)); | 5068 Runtime::GetObjectProperty(isolate, object, key)); |
5069 return *result; | 5069 return *result; |
5070 } | 5070 } |
5071 | 5071 |
5072 | 5072 |
5073 // KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric. | 5073 // KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric. |
5074 RUNTIME_FUNCTION(Runtime_KeyedGetProperty) { | 5074 RUNTIME_FUNCTION(Runtime_KeyedGetProperty) { |
5075 SealHandleScope shs(isolate); | 5075 HandleScope scope(isolate); |
5076 ASSERT(args.length() == 2); | 5076 ASSERT(args.length() == 2); |
5077 | 5077 |
| 5078 CONVERT_ARG_HANDLE_CHECKED(Object, receiver_obj, 0); |
| 5079 CONVERT_ARG_HANDLE_CHECKED(Object, key_obj, 1); |
| 5080 |
5078 // Fast cases for getting named properties of the receiver JSObject | 5081 // Fast cases for getting named properties of the receiver JSObject |
5079 // itself. | 5082 // itself. |
5080 // | 5083 // |
5081 // The global proxy objects has to be excluded since LocalLookup on | 5084 // The global proxy objects has to be excluded since LocalLookup on |
5082 // the global proxy object can return a valid result even though the | 5085 // the global proxy object can return a valid result even though the |
5083 // global proxy object never has properties. This is the case | 5086 // global proxy object never has properties. This is the case |
5084 // because the global proxy object forwards everything to its hidden | 5087 // because the global proxy object forwards everything to its hidden |
5085 // prototype including local lookups. | 5088 // prototype including local lookups. |
5086 // | 5089 // |
5087 // Additionally, we need to make sure that we do not cache results | 5090 // Additionally, we need to make sure that we do not cache results |
5088 // for objects that require access checks. | 5091 // for objects that require access checks. |
5089 if (args[0]->IsJSObject()) { | 5092 if (receiver_obj->IsJSObject()) { |
5090 if (!args[0]->IsJSGlobalProxy() && | 5093 if (!receiver_obj->IsJSGlobalProxy() && |
5091 !args[0]->IsAccessCheckNeeded() && | 5094 !receiver_obj->IsAccessCheckNeeded() && |
5092 args[1]->IsName()) { | 5095 key_obj->IsName()) { |
5093 JSObject* receiver = JSObject::cast(args[0]); | 5096 DisallowHeapAllocation no_allocation; |
5094 Name* key = Name::cast(args[1]); | 5097 Handle<JSObject> receiver = Handle<JSObject>::cast(receiver_obj); |
| 5098 Handle<Name> key = Handle<Name>::cast(key_obj); |
5095 if (receiver->HasFastProperties()) { | 5099 if (receiver->HasFastProperties()) { |
5096 // Attempt to use lookup cache. | 5100 // Attempt to use lookup cache. |
5097 Map* receiver_map = receiver->map(); | 5101 Map* receiver_map = receiver->map(); |
5098 KeyedLookupCache* keyed_lookup_cache = isolate->keyed_lookup_cache(); | 5102 KeyedLookupCache* keyed_lookup_cache = isolate->keyed_lookup_cache(); |
5099 int offset = keyed_lookup_cache->Lookup(receiver_map, key); | 5103 int offset = keyed_lookup_cache->Lookup(receiver_map, *key); |
5100 if (offset != -1) { | 5104 if (offset != -1) { |
5101 // Doubles are not cached, so raw read the value. | 5105 // Doubles are not cached, so raw read the value. |
5102 Object* value = receiver->RawFastPropertyAt(offset); | 5106 Object* value = receiver->RawFastPropertyAt(offset); |
5103 return value->IsTheHole() | 5107 return value->IsTheHole() |
5104 ? isolate->heap()->undefined_value() | 5108 ? isolate->heap()->undefined_value() |
5105 : value; | 5109 : value; |
5106 } | 5110 } |
5107 // Lookup cache miss. Perform lookup and update the cache if | 5111 // Lookup cache miss. Perform lookup and update the cache if |
5108 // appropriate. | 5112 // appropriate. |
5109 LookupResult result(isolate); | 5113 LookupResult result(isolate); |
5110 receiver->LocalLookup(key, &result); | 5114 receiver->LocalLookup(*key, &result); |
5111 if (result.IsField()) { | 5115 if (result.IsField()) { |
5112 int offset = result.GetFieldIndex().field_index(); | 5116 int offset = result.GetFieldIndex().field_index(); |
5113 // Do not track double fields in the keyed lookup cache. Reading | 5117 // Do not track double fields in the keyed lookup cache. Reading |
5114 // double values requires boxing. | 5118 // double values requires boxing. |
5115 if (!result.representation().IsDouble()) { | 5119 if (!result.representation().IsDouble()) { |
5116 keyed_lookup_cache->Update(receiver_map, key, offset); | 5120 keyed_lookup_cache->Update(receiver_map, *key, offset); |
5117 } | 5121 } |
5118 HandleScope scope(isolate); | 5122 AllowHeapAllocation allow_allocation; |
5119 return *JSObject::FastPropertyAt( | 5123 return *JSObject::FastPropertyAt( |
5120 handle(receiver, isolate), result.representation(), offset); | 5124 receiver, result.representation(), offset); |
5121 } | 5125 } |
5122 } else { | 5126 } else { |
5123 // Attempt dictionary lookup. | 5127 // Attempt dictionary lookup. |
5124 NameDictionary* dictionary = receiver->property_dictionary(); | 5128 NameDictionary* dictionary = receiver->property_dictionary(); |
5125 int entry = dictionary->FindEntry(key); | 5129 int entry = dictionary->FindEntry(key); |
5126 if ((entry != NameDictionary::kNotFound) && | 5130 if ((entry != NameDictionary::kNotFound) && |
5127 (dictionary->DetailsAt(entry).type() == NORMAL)) { | 5131 (dictionary->DetailsAt(entry).type() == NORMAL)) { |
5128 Object* value = dictionary->ValueAt(entry); | 5132 Object* value = dictionary->ValueAt(entry); |
5129 if (!receiver->IsGlobalObject()) return value; | 5133 if (!receiver->IsGlobalObject()) return value; |
5130 value = PropertyCell::cast(value)->value(); | 5134 value = PropertyCell::cast(value)->value(); |
5131 if (!value->IsTheHole()) return value; | 5135 if (!value->IsTheHole()) return value; |
5132 // If value is the hole do the general lookup. | 5136 // If value is the hole do the general lookup. |
5133 } | 5137 } |
5134 } | 5138 } |
5135 } else if (FLAG_smi_only_arrays && args.at<Object>(1)->IsSmi()) { | 5139 } else if (FLAG_smi_only_arrays && key_obj->IsSmi()) { |
5136 // JSObject without a name key. If the key is a Smi, check for a | 5140 // JSObject without a name key. If the key is a Smi, check for a |
5137 // definite out-of-bounds access to elements, which is a strong indicator | 5141 // definite out-of-bounds access to elements, which is a strong indicator |
5138 // that subsequent accesses will also call the runtime. Proactively | 5142 // that subsequent accesses will also call the runtime. Proactively |
5139 // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of | 5143 // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of |
5140 // doubles for those future calls in the case that the elements would | 5144 // doubles for those future calls in the case that the elements would |
5141 // become FAST_DOUBLE_ELEMENTS. | 5145 // become FAST_DOUBLE_ELEMENTS. |
5142 Handle<JSObject> js_object(args.at<JSObject>(0)); | 5146 Handle<JSObject> js_object = Handle<JSObject>::cast(receiver_obj); |
5143 ElementsKind elements_kind = js_object->GetElementsKind(); | 5147 ElementsKind elements_kind = js_object->GetElementsKind(); |
5144 if (IsFastDoubleElementsKind(elements_kind)) { | 5148 if (IsFastDoubleElementsKind(elements_kind)) { |
5145 if (args.at<Smi>(1)->value() >= js_object->elements()->length()) { | 5149 Handle<Smi> key = Handle<Smi>::cast(key_obj); |
| 5150 if (key->value() >= js_object->elements()->length()) { |
5146 if (IsFastHoleyElementsKind(elements_kind)) { | 5151 if (IsFastHoleyElementsKind(elements_kind)) { |
5147 elements_kind = FAST_HOLEY_ELEMENTS; | 5152 elements_kind = FAST_HOLEY_ELEMENTS; |
5148 } else { | 5153 } else { |
5149 elements_kind = FAST_ELEMENTS; | 5154 elements_kind = FAST_ELEMENTS; |
5150 } | 5155 } |
5151 RETURN_FAILURE_ON_EXCEPTION( | 5156 RETURN_FAILURE_ON_EXCEPTION( |
5152 isolate, TransitionElements(js_object, elements_kind, isolate)); | 5157 isolate, TransitionElements(js_object, elements_kind, isolate)); |
5153 } | 5158 } |
5154 } else { | 5159 } else { |
5155 ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) || | 5160 ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) || |
5156 !IsFastElementsKind(elements_kind)); | 5161 !IsFastElementsKind(elements_kind)); |
5157 } | 5162 } |
5158 } | 5163 } |
5159 } else if (args[0]->IsString() && args[1]->IsSmi()) { | 5164 } else if (receiver_obj->IsString() && key_obj->IsSmi()) { |
5160 // Fast case for string indexing using [] with a smi index. | 5165 // Fast case for string indexing using [] with a smi index. |
5161 HandleScope scope(isolate); | 5166 Handle<String> str = Handle<String>::cast(receiver_obj); |
5162 Handle<String> str = args.at<String>(0); | |
5163 int index = args.smi_at(1); | 5167 int index = args.smi_at(1); |
5164 if (index >= 0 && index < str->length()) { | 5168 if (index >= 0 && index < str->length()) { |
5165 return *GetCharAt(str, index); | 5169 return *GetCharAt(str, index); |
5166 } | 5170 } |
5167 } | 5171 } |
5168 | 5172 |
5169 // Fall back to GetObjectProperty. | 5173 // Fall back to GetObjectProperty. |
5170 HandleScope scope(isolate); | |
5171 Handle<Object> result; | 5174 Handle<Object> result; |
5172 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 5175 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
5173 isolate, result, | 5176 isolate, result, |
5174 Runtime::GetObjectProperty( | 5177 Runtime::GetObjectProperty(isolate, receiver_obj, key_obj)); |
5175 isolate, args.at<Object>(0), args.at<Object>(1))); | |
5176 return *result; | 5178 return *result; |
5177 } | 5179 } |
5178 | 5180 |
5179 | 5181 |
5180 static bool IsValidAccessor(Handle<Object> obj) { | 5182 static bool IsValidAccessor(Handle<Object> obj) { |
5181 return obj->IsUndefined() || obj->IsSpecFunction() || obj->IsNull(); | 5183 return obj->IsUndefined() || obj->IsSpecFunction() || obj->IsNull(); |
5182 } | 5184 } |
5183 | 5185 |
5184 | 5186 |
5185 // Implements part of 8.12.9 DefineOwnProperty. | 5187 // Implements part of 8.12.9 DefineOwnProperty. |
(...skipping 9970 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15156 } | 15158 } |
15157 return NULL; | 15159 return NULL; |
15158 } | 15160 } |
15159 | 15161 |
15160 | 15162 |
15161 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) { | 15163 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) { |
15162 return &(kIntrinsicFunctions[static_cast<int>(id)]); | 15164 return &(kIntrinsicFunctions[static_cast<int>(id)]); |
15163 } | 15165 } |
15164 | 15166 |
15165 } } // namespace v8::internal | 15167 } } // namespace v8::internal |
OLD | NEW |