| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 #include "scopeinfo.h" | 44 #include "scopeinfo.h" |
| 45 #include "string-stream.h" | 45 #include "string-stream.h" |
| 46 #include "utils.h" | 46 #include "utils.h" |
| 47 #include "vm-state-inl.h" | 47 #include "vm-state-inl.h" |
| 48 | 48 |
| 49 #ifdef ENABLE_DISASSEMBLER | 49 #ifdef ENABLE_DISASSEMBLER |
| 50 #include "disasm.h" | 50 #include "disasm.h" |
| 51 #include "disassembler.h" | 51 #include "disassembler.h" |
| 52 #endif | 52 #endif |
| 53 | 53 |
| 54 | |
| 55 namespace v8 { | 54 namespace v8 { |
| 56 namespace internal { | 55 namespace internal { |
| 57 | 56 |
| 58 // Getters and setters are stored in a fixed array property. These are | 57 // Getters and setters are stored in a fixed array property. These are |
| 59 // constants for their indices. | 58 // constants for their indices. |
| 60 const int kGetterIndex = 0; | 59 const int kGetterIndex = 0; |
| 61 const int kSetterIndex = 1; | 60 const int kSetterIndex = 1; |
| 62 | 61 |
| 63 | 62 |
| 64 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor, | 63 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor, |
| 65 Object* value) { | 64 Object* value) { |
| 66 Object* result; | 65 Object* result; |
| 67 { MaybeObject* maybe_result = Heap::AllocateJSObject(constructor); | 66 { MaybeObject* maybe_result = |
| 67 constructor->GetHeap()->AllocateJSObject(constructor); |
| 68 if (!maybe_result->ToObject(&result)) return maybe_result; | 68 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 69 } | 69 } |
| 70 JSValue::cast(result)->set_value(value); | 70 JSValue::cast(result)->set_value(value); |
| 71 return result; | 71 return result; |
| 72 } | 72 } |
| 73 | 73 |
| 74 | 74 |
| 75 MaybeObject* Object::ToObject(Context* global_context) { | 75 MaybeObject* Object::ToObject(Context* global_context) { |
| 76 if (IsNumber()) { | 76 if (IsNumber()) { |
| 77 return CreateJSValue(global_context->number_function(), this); | 77 return CreateJSValue(global_context->number_function(), this); |
| 78 } else if (IsBoolean()) { | 78 } else if (IsBoolean()) { |
| 79 return CreateJSValue(global_context->boolean_function(), this); | 79 return CreateJSValue(global_context->boolean_function(), this); |
| 80 } else if (IsString()) { | 80 } else if (IsString()) { |
| 81 return CreateJSValue(global_context->string_function(), this); | 81 return CreateJSValue(global_context->string_function(), this); |
| 82 } | 82 } |
| 83 ASSERT(IsJSObject()); | 83 ASSERT(IsJSObject()); |
| 84 return this; | 84 return this; |
| 85 } | 85 } |
| 86 | 86 |
| 87 | 87 |
| 88 MaybeObject* Object::ToObject() { | 88 MaybeObject* Object::ToObject() { |
| 89 Context* global_context = Top::context()->global_context(); | |
| 90 if (IsJSObject()) { | 89 if (IsJSObject()) { |
| 91 return this; | 90 return this; |
| 92 } else if (IsNumber()) { | 91 } else if (IsNumber()) { |
| 92 Isolate* isolate = Isolate::Current(); |
| 93 Context* global_context = isolate->context()->global_context(); |
| 93 return CreateJSValue(global_context->number_function(), this); | 94 return CreateJSValue(global_context->number_function(), this); |
| 94 } else if (IsBoolean()) { | 95 } else if (IsBoolean()) { |
| 96 Isolate* isolate = HeapObject::cast(this)->GetIsolate(); |
| 97 Context* global_context = isolate->context()->global_context(); |
| 95 return CreateJSValue(global_context->boolean_function(), this); | 98 return CreateJSValue(global_context->boolean_function(), this); |
| 96 } else if (IsString()) { | 99 } else if (IsString()) { |
| 100 Isolate* isolate = HeapObject::cast(this)->GetIsolate(); |
| 101 Context* global_context = isolate->context()->global_context(); |
| 97 return CreateJSValue(global_context->string_function(), this); | 102 return CreateJSValue(global_context->string_function(), this); |
| 98 } | 103 } |
| 99 | 104 |
| 100 // Throw a type error. | 105 // Throw a type error. |
| 101 return Failure::InternalError(); | 106 return Failure::InternalError(); |
| 102 } | 107 } |
| 103 | 108 |
| 104 | 109 |
| 105 Object* Object::ToBoolean() { | 110 Object* Object::ToBoolean() { |
| 106 if (IsTrue()) return Heap::true_value(); | 111 if (IsTrue()) return this; |
| 107 if (IsFalse()) return Heap::false_value(); | 112 if (IsFalse()) return this; |
| 108 if (IsSmi()) { | 113 if (IsSmi()) { |
| 109 return Heap::ToBoolean(Smi::cast(this)->value() != 0); | 114 return Isolate::Current()->heap()->ToBoolean(Smi::cast(this)->value() != 0); |
| 110 } | 115 } |
| 111 if (IsUndefined() || IsNull()) return Heap::false_value(); | 116 if (IsUndefined() || IsNull()) { |
| 117 return HeapObject::cast(this)->GetHeap()->false_value(); |
| 118 } |
| 112 // Undetectable object is false | 119 // Undetectable object is false |
| 113 if (IsUndetectableObject()) { | 120 if (IsUndetectableObject()) { |
| 114 return Heap::false_value(); | 121 return HeapObject::cast(this)->GetHeap()->false_value(); |
| 115 } | 122 } |
| 116 if (IsString()) { | 123 if (IsString()) { |
| 117 return Heap::ToBoolean(String::cast(this)->length() != 0); | 124 return HeapObject::cast(this)->GetHeap()->ToBoolean( |
| 125 String::cast(this)->length() != 0); |
| 118 } | 126 } |
| 119 if (IsHeapNumber()) { | 127 if (IsHeapNumber()) { |
| 120 return HeapNumber::cast(this)->HeapNumberToBoolean(); | 128 return HeapNumber::cast(this)->HeapNumberToBoolean(); |
| 121 } | 129 } |
| 122 return Heap::true_value(); | 130 return Isolate::Current()->heap()->true_value(); |
| 123 } | 131 } |
| 124 | 132 |
| 125 | 133 |
| 126 void Object::Lookup(String* name, LookupResult* result) { | 134 void Object::Lookup(String* name, LookupResult* result) { |
| 127 if (IsJSObject()) return JSObject::cast(this)->Lookup(name, result); | 135 if (IsJSObject()) return JSObject::cast(this)->Lookup(name, result); |
| 128 Object* holder = NULL; | 136 Object* holder = NULL; |
| 129 Context* global_context = Top::context()->global_context(); | |
| 130 if (IsString()) { | 137 if (IsString()) { |
| 138 Heap* heap = HeapObject::cast(this)->GetHeap(); |
| 139 Context* global_context = heap->isolate()->context()->global_context(); |
| 131 holder = global_context->string_function()->instance_prototype(); | 140 holder = global_context->string_function()->instance_prototype(); |
| 132 } else if (IsNumber()) { | 141 } else if (IsNumber()) { |
| 142 Heap* heap = Isolate::Current()->heap(); |
| 143 Context* global_context = heap->isolate()->context()->global_context(); |
| 133 holder = global_context->number_function()->instance_prototype(); | 144 holder = global_context->number_function()->instance_prototype(); |
| 134 } else if (IsBoolean()) { | 145 } else if (IsBoolean()) { |
| 146 Heap* heap = HeapObject::cast(this)->GetHeap(); |
| 147 Context* global_context = heap->isolate()->context()->global_context(); |
| 135 holder = global_context->boolean_function()->instance_prototype(); | 148 holder = global_context->boolean_function()->instance_prototype(); |
| 136 } | 149 } |
| 137 ASSERT(holder != NULL); // Cannot handle null or undefined. | 150 ASSERT(holder != NULL); // Cannot handle null or undefined. |
| 138 JSObject::cast(holder)->Lookup(name, result); | 151 JSObject::cast(holder)->Lookup(name, result); |
| 139 } | 152 } |
| 140 | 153 |
| 141 | 154 |
| 142 MaybeObject* Object::GetPropertyWithReceiver(Object* receiver, | 155 MaybeObject* Object::GetPropertyWithReceiver(Object* receiver, |
| 143 String* name, | 156 String* name, |
| 144 PropertyAttributes* attributes) { | 157 PropertyAttributes* attributes) { |
| 145 LookupResult result; | 158 LookupResult result; |
| 146 Lookup(name, &result); | 159 Lookup(name, &result); |
| 147 MaybeObject* value = GetProperty(receiver, &result, name, attributes); | 160 MaybeObject* value = GetProperty(receiver, &result, name, attributes); |
| 148 ASSERT(*attributes <= ABSENT); | 161 ASSERT(*attributes <= ABSENT); |
| 149 return value; | 162 return value; |
| 150 } | 163 } |
| 151 | 164 |
| 152 | 165 |
| 153 MaybeObject* Object::GetPropertyWithCallback(Object* receiver, | 166 MaybeObject* Object::GetPropertyWithCallback(Object* receiver, |
| 154 Object* structure, | 167 Object* structure, |
| 155 String* name, | 168 String* name, |
| 156 Object* holder) { | 169 Object* holder) { |
| 170 Isolate* isolate = name->GetIsolate(); |
| 157 // To accommodate both the old and the new api we switch on the | 171 // To accommodate both the old and the new api we switch on the |
| 158 // data structure used to store the callbacks. Eventually proxy | 172 // data structure used to store the callbacks. Eventually proxy |
| 159 // callbacks should be phased out. | 173 // callbacks should be phased out. |
| 160 if (structure->IsProxy()) { | 174 if (structure->IsProxy()) { |
| 161 AccessorDescriptor* callback = | 175 AccessorDescriptor* callback = |
| 162 reinterpret_cast<AccessorDescriptor*>(Proxy::cast(structure)->proxy()); | 176 reinterpret_cast<AccessorDescriptor*>(Proxy::cast(structure)->proxy()); |
| 163 MaybeObject* value = (callback->getter)(receiver, callback->data); | 177 MaybeObject* value = (callback->getter)(receiver, callback->data); |
| 164 RETURN_IF_SCHEDULED_EXCEPTION(); | 178 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 165 return value; | 179 return value; |
| 166 } | 180 } |
| 167 | 181 |
| 168 // api style callbacks. | 182 // api style callbacks. |
| 169 if (structure->IsAccessorInfo()) { | 183 if (structure->IsAccessorInfo()) { |
| 170 AccessorInfo* data = AccessorInfo::cast(structure); | 184 AccessorInfo* data = AccessorInfo::cast(structure); |
| 171 Object* fun_obj = data->getter(); | 185 Object* fun_obj = data->getter(); |
| 172 v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj); | 186 v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj); |
| 173 HandleScope scope; | 187 HandleScope scope; |
| 174 JSObject* self = JSObject::cast(receiver); | 188 JSObject* self = JSObject::cast(receiver); |
| 175 JSObject* holder_handle = JSObject::cast(holder); | 189 JSObject* holder_handle = JSObject::cast(holder); |
| 176 Handle<String> key(name); | 190 Handle<String> key(name); |
| 177 LOG(ApiNamedPropertyAccess("load", self, name)); | 191 LOG(isolate, ApiNamedPropertyAccess("load", self, name)); |
| 178 CustomArguments args(data->data(), self, holder_handle); | 192 CustomArguments args(isolate, data->data(), self, holder_handle); |
| 179 v8::AccessorInfo info(args.end()); | 193 v8::AccessorInfo info(args.end()); |
| 180 v8::Handle<v8::Value> result; | 194 v8::Handle<v8::Value> result; |
| 181 { | 195 { |
| 182 // Leaving JavaScript. | 196 // Leaving JavaScript. |
| 183 VMState state(EXTERNAL); | 197 VMState state(isolate, EXTERNAL); |
| 184 result = call_fun(v8::Utils::ToLocal(key), info); | 198 result = call_fun(v8::Utils::ToLocal(key), info); |
| 185 } | 199 } |
| 186 RETURN_IF_SCHEDULED_EXCEPTION(); | 200 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 187 if (result.IsEmpty()) return Heap::undefined_value(); | 201 if (result.IsEmpty()) { |
| 202 return isolate->heap()->undefined_value(); |
| 203 } |
| 188 return *v8::Utils::OpenHandle(*result); | 204 return *v8::Utils::OpenHandle(*result); |
| 189 } | 205 } |
| 190 | 206 |
| 191 // __defineGetter__ callback | 207 // __defineGetter__ callback |
| 192 if (structure->IsFixedArray()) { | 208 if (structure->IsFixedArray()) { |
| 193 Object* getter = FixedArray::cast(structure)->get(kGetterIndex); | 209 Object* getter = FixedArray::cast(structure)->get(kGetterIndex); |
| 194 if (getter->IsJSFunction()) { | 210 if (getter->IsJSFunction()) { |
| 195 return Object::GetPropertyWithDefinedGetter(receiver, | 211 return Object::GetPropertyWithDefinedGetter(receiver, |
| 196 JSFunction::cast(getter)); | 212 JSFunction::cast(getter)); |
| 197 } | 213 } |
| 198 // Getter is not a function. | 214 // Getter is not a function. |
| 199 return Heap::undefined_value(); | 215 return isolate->heap()->undefined_value(); |
| 200 } | 216 } |
| 201 | 217 |
| 202 UNREACHABLE(); | 218 UNREACHABLE(); |
| 203 return NULL; | 219 return NULL; |
| 204 } | 220 } |
| 205 | 221 |
| 206 | 222 |
| 207 MaybeObject* Object::GetPropertyWithDefinedGetter(Object* receiver, | 223 MaybeObject* Object::GetPropertyWithDefinedGetter(Object* receiver, |
| 208 JSFunction* getter) { | 224 JSFunction* getter) { |
| 209 HandleScope scope; | 225 HandleScope scope; |
| 210 Handle<JSFunction> fun(JSFunction::cast(getter)); | 226 Handle<JSFunction> fun(JSFunction::cast(getter)); |
| 211 Handle<Object> self(receiver); | 227 Handle<Object> self(receiver); |
| 212 #ifdef ENABLE_DEBUGGER_SUPPORT | 228 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 229 Debug* debug = fun->GetHeap()->isolate()->debug(); |
| 213 // Handle stepping into a getter if step into is active. | 230 // Handle stepping into a getter if step into is active. |
| 214 if (Debug::StepInActive()) { | 231 if (debug->StepInActive()) { |
| 215 Debug::HandleStepIn(fun, Handle<Object>::null(), 0, false); | 232 debug->HandleStepIn(fun, Handle<Object>::null(), 0, false); |
| 216 } | 233 } |
| 217 #endif | 234 #endif |
| 218 bool has_pending_exception; | 235 bool has_pending_exception; |
| 219 Handle<Object> result = | 236 Handle<Object> result = |
| 220 Execution::Call(fun, self, 0, NULL, &has_pending_exception); | 237 Execution::Call(fun, self, 0, NULL, &has_pending_exception); |
| 221 // Check for pending exception and return the result. | 238 // Check for pending exception and return the result. |
| 222 if (has_pending_exception) return Failure::Exception(); | 239 if (has_pending_exception) return Failure::Exception(); |
| 223 return *result; | 240 return *result; |
| 224 } | 241 } |
| 225 | 242 |
| 226 | 243 |
| 227 // Only deal with CALLBACKS and INTERCEPTOR | 244 // Only deal with CALLBACKS and INTERCEPTOR |
| 228 MaybeObject* JSObject::GetPropertyWithFailedAccessCheck( | 245 MaybeObject* JSObject::GetPropertyWithFailedAccessCheck( |
| 229 Object* receiver, | 246 Object* receiver, |
| 230 LookupResult* result, | 247 LookupResult* result, |
| 231 String* name, | 248 String* name, |
| 232 PropertyAttributes* attributes) { | 249 PropertyAttributes* attributes) { |
| 250 Heap* heap = name->GetHeap(); |
| 233 if (result->IsProperty()) { | 251 if (result->IsProperty()) { |
| 234 switch (result->type()) { | 252 switch (result->type()) { |
| 235 case CALLBACKS: { | 253 case CALLBACKS: { |
| 236 // Only allow API accessors. | 254 // Only allow API accessors. |
| 237 Object* obj = result->GetCallbackObject(); | 255 Object* obj = result->GetCallbackObject(); |
| 238 if (obj->IsAccessorInfo()) { | 256 if (obj->IsAccessorInfo()) { |
| 239 AccessorInfo* info = AccessorInfo::cast(obj); | 257 AccessorInfo* info = AccessorInfo::cast(obj); |
| 240 if (info->all_can_read()) { | 258 if (info->all_can_read()) { |
| 241 *attributes = result->GetAttributes(); | 259 *attributes = result->GetAttributes(); |
| 242 return GetPropertyWithCallback(receiver, | 260 return GetPropertyWithCallback(receiver, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 } | 292 } |
| 275 break; | 293 break; |
| 276 } | 294 } |
| 277 default: | 295 default: |
| 278 UNREACHABLE(); | 296 UNREACHABLE(); |
| 279 } | 297 } |
| 280 } | 298 } |
| 281 | 299 |
| 282 // No accessible property found. | 300 // No accessible property found. |
| 283 *attributes = ABSENT; | 301 *attributes = ABSENT; |
| 284 Top::ReportFailedAccessCheck(this, v8::ACCESS_GET); | 302 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_GET); |
| 285 return Heap::undefined_value(); | 303 return heap->undefined_value(); |
| 286 } | 304 } |
| 287 | 305 |
| 288 | 306 |
| 289 PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck( | 307 PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck( |
| 290 Object* receiver, | 308 Object* receiver, |
| 291 LookupResult* result, | 309 LookupResult* result, |
| 292 String* name, | 310 String* name, |
| 293 bool continue_search) { | 311 bool continue_search) { |
| 312 Heap* heap = name->GetHeap(); |
| 294 if (result->IsProperty()) { | 313 if (result->IsProperty()) { |
| 295 switch (result->type()) { | 314 switch (result->type()) { |
| 296 case CALLBACKS: { | 315 case CALLBACKS: { |
| 297 // Only allow API accessors. | 316 // Only allow API accessors. |
| 298 Object* obj = result->GetCallbackObject(); | 317 Object* obj = result->GetCallbackObject(); |
| 299 if (obj->IsAccessorInfo()) { | 318 if (obj->IsAccessorInfo()) { |
| 300 AccessorInfo* info = AccessorInfo::cast(obj); | 319 AccessorInfo* info = AccessorInfo::cast(obj); |
| 301 if (info->all_can_read()) { | 320 if (info->all_can_read()) { |
| 302 return result->GetAttributes(); | 321 return result->GetAttributes(); |
| 303 } | 322 } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 337 continue_search); | 356 continue_search); |
| 338 } | 357 } |
| 339 break; | 358 break; |
| 340 } | 359 } |
| 341 | 360 |
| 342 default: | 361 default: |
| 343 UNREACHABLE(); | 362 UNREACHABLE(); |
| 344 } | 363 } |
| 345 } | 364 } |
| 346 | 365 |
| 347 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 366 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 348 return ABSENT; | 367 return ABSENT; |
| 349 } | 368 } |
| 350 | 369 |
| 351 | 370 |
| 352 Object* JSObject::GetNormalizedProperty(LookupResult* result) { | 371 Object* JSObject::GetNormalizedProperty(LookupResult* result) { |
| 353 ASSERT(!HasFastProperties()); | 372 ASSERT(!HasFastProperties()); |
| 354 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); | 373 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); |
| 355 if (IsGlobalObject()) { | 374 if (IsGlobalObject()) { |
| 356 value = JSGlobalPropertyCell::cast(value)->value(); | 375 value = JSGlobalPropertyCell::cast(value)->value(); |
| 357 } | 376 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 371 property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value); | 390 property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value); |
| 372 } | 391 } |
| 373 return value; | 392 return value; |
| 374 } | 393 } |
| 375 | 394 |
| 376 | 395 |
| 377 MaybeObject* JSObject::SetNormalizedProperty(String* name, | 396 MaybeObject* JSObject::SetNormalizedProperty(String* name, |
| 378 Object* value, | 397 Object* value, |
| 379 PropertyDetails details) { | 398 PropertyDetails details) { |
| 380 ASSERT(!HasFastProperties()); | 399 ASSERT(!HasFastProperties()); |
| 400 Heap* heap = name->GetHeap(); |
| 381 int entry = property_dictionary()->FindEntry(name); | 401 int entry = property_dictionary()->FindEntry(name); |
| 382 if (entry == StringDictionary::kNotFound) { | 402 if (entry == StringDictionary::kNotFound) { |
| 383 Object* store_value = value; | 403 Object* store_value = value; |
| 384 if (IsGlobalObject()) { | 404 if (IsGlobalObject()) { |
| 385 { MaybeObject* maybe_store_value = | 405 MaybeObject* maybe_store_value = |
| 386 Heap::AllocateJSGlobalPropertyCell(value); | 406 heap->AllocateJSGlobalPropertyCell(value); |
| 387 if (!maybe_store_value->ToObject(&store_value)) { | 407 if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value; |
| 388 return maybe_store_value; | |
| 389 } | |
| 390 } | |
| 391 } | 408 } |
| 392 Object* dict; | 409 Object* dict; |
| 393 { MaybeObject* maybe_dict = | 410 { MaybeObject* maybe_dict = |
| 394 property_dictionary()->Add(name, store_value, details); | 411 property_dictionary()->Add(name, store_value, details); |
| 395 if (!maybe_dict->ToObject(&dict)) return maybe_dict; | 412 if (!maybe_dict->ToObject(&dict)) return maybe_dict; |
| 396 } | 413 } |
| 397 set_properties(StringDictionary::cast(dict)); | 414 set_properties(StringDictionary::cast(dict)); |
| 398 return value; | 415 return value; |
| 399 } | 416 } |
| 400 // Preserve enumeration index. | 417 // Preserve enumeration index. |
| 401 details = PropertyDetails(details.attributes(), | 418 details = PropertyDetails(details.attributes(), |
| 402 details.type(), | 419 details.type(), |
| 403 property_dictionary()->DetailsAt(entry).index()); | 420 property_dictionary()->DetailsAt(entry).index()); |
| 404 if (IsGlobalObject()) { | 421 if (IsGlobalObject()) { |
| 405 JSGlobalPropertyCell* cell = | 422 JSGlobalPropertyCell* cell = |
| 406 JSGlobalPropertyCell::cast(property_dictionary()->ValueAt(entry)); | 423 JSGlobalPropertyCell::cast(property_dictionary()->ValueAt(entry)); |
| 407 cell->set_value(value); | 424 cell->set_value(value); |
| 408 // Please note we have to update the property details. | 425 // Please note we have to update the property details. |
| 409 property_dictionary()->DetailsAtPut(entry, details); | 426 property_dictionary()->DetailsAtPut(entry, details); |
| 410 } else { | 427 } else { |
| 411 property_dictionary()->SetEntry(entry, name, value, details); | 428 property_dictionary()->SetEntry(entry, name, value, details); |
| 412 } | 429 } |
| 413 return value; | 430 return value; |
| 414 } | 431 } |
| 415 | 432 |
| 416 | 433 |
| 417 MaybeObject* JSObject::DeleteNormalizedProperty(String* name, DeleteMode mode) { | 434 MaybeObject* JSObject::DeleteNormalizedProperty(String* name, DeleteMode mode) { |
| 418 ASSERT(!HasFastProperties()); | 435 ASSERT(!HasFastProperties()); |
| 436 Heap* heap = GetHeap(); |
| 419 StringDictionary* dictionary = property_dictionary(); | 437 StringDictionary* dictionary = property_dictionary(); |
| 420 int entry = dictionary->FindEntry(name); | 438 int entry = dictionary->FindEntry(name); |
| 421 if (entry != StringDictionary::kNotFound) { | 439 if (entry != StringDictionary::kNotFound) { |
| 422 // If we have a global object set the cell to the hole. | 440 // If we have a global object set the cell to the hole. |
| 423 if (IsGlobalObject()) { | 441 if (IsGlobalObject()) { |
| 424 PropertyDetails details = dictionary->DetailsAt(entry); | 442 PropertyDetails details = dictionary->DetailsAt(entry); |
| 425 if (details.IsDontDelete()) { | 443 if (details.IsDontDelete()) { |
| 426 if (mode != FORCE_DELETION) return Heap::false_value(); | 444 if (mode != FORCE_DELETION) return heap->false_value(); |
| 427 // When forced to delete global properties, we have to make a | 445 // When forced to delete global properties, we have to make a |
| 428 // map change to invalidate any ICs that think they can load | 446 // map change to invalidate any ICs that think they can load |
| 429 // from the DontDelete cell without checking if it contains | 447 // from the DontDelete cell without checking if it contains |
| 430 // the hole value. | 448 // the hole value. |
| 431 Object* new_map; | 449 Object* new_map; |
| 432 { MaybeObject* maybe_new_map = map()->CopyDropDescriptors(); | 450 { MaybeObject* maybe_new_map = map()->CopyDropDescriptors(); |
| 433 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; | 451 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; |
| 434 } | 452 } |
| 435 set_map(Map::cast(new_map)); | 453 set_map(Map::cast(new_map)); |
| 436 } | 454 } |
| 437 JSGlobalPropertyCell* cell = | 455 JSGlobalPropertyCell* cell = |
| 438 JSGlobalPropertyCell::cast(dictionary->ValueAt(entry)); | 456 JSGlobalPropertyCell::cast(dictionary->ValueAt(entry)); |
| 439 cell->set_value(Heap::the_hole_value()); | 457 cell->set_value(heap->the_hole_value()); |
| 440 dictionary->DetailsAtPut(entry, details.AsDeleted()); | 458 dictionary->DetailsAtPut(entry, details.AsDeleted()); |
| 441 } else { | 459 } else { |
| 442 return dictionary->DeleteProperty(entry, mode); | 460 return dictionary->DeleteProperty(entry, mode); |
| 443 } | 461 } |
| 444 } | 462 } |
| 445 return Heap::true_value(); | 463 return heap->true_value(); |
| 446 } | 464 } |
| 447 | 465 |
| 448 | 466 |
| 449 bool JSObject::IsDirty() { | 467 bool JSObject::IsDirty() { |
| 450 Object* cons_obj = map()->constructor(); | 468 Object* cons_obj = map()->constructor(); |
| 451 if (!cons_obj->IsJSFunction()) | 469 if (!cons_obj->IsJSFunction()) |
| 452 return true; | 470 return true; |
| 453 JSFunction* fun = JSFunction::cast(cons_obj); | 471 JSFunction* fun = JSFunction::cast(cons_obj); |
| 454 if (!fun->shared()->IsApiFunction()) | 472 if (!fun->shared()->IsApiFunction()) |
| 455 return true; | 473 return true; |
| 456 // If the object is fully fast case and has the same map it was | 474 // If the object is fully fast case and has the same map it was |
| 457 // created with then no changes can have been made to it. | 475 // created with then no changes can have been made to it. |
| 458 return map() != fun->initial_map() | 476 return map() != fun->initial_map() |
| 459 || !HasFastElements() | 477 || !HasFastElements() |
| 460 || !HasFastProperties(); | 478 || !HasFastProperties(); |
| 461 } | 479 } |
| 462 | 480 |
| 463 | 481 |
| 464 MaybeObject* Object::GetProperty(Object* receiver, | 482 MaybeObject* Object::GetProperty(Object* receiver, |
| 465 LookupResult* result, | 483 LookupResult* result, |
| 466 String* name, | 484 String* name, |
| 467 PropertyAttributes* attributes) { | 485 PropertyAttributes* attributes) { |
| 468 // Make sure that the top context does not change when doing | 486 // Make sure that the top context does not change when doing |
| 469 // callbacks or interceptor calls. | 487 // callbacks or interceptor calls. |
| 470 AssertNoContextChange ncc; | 488 AssertNoContextChange ncc; |
| 489 Heap* heap = name->GetHeap(); |
| 471 | 490 |
| 472 // Traverse the prototype chain from the current object (this) to | 491 // Traverse the prototype chain from the current object (this) to |
| 473 // the holder and check for access rights. This avoid traversing the | 492 // the holder and check for access rights. This avoid traversing the |
| 474 // objects more than once in case of interceptors, because the | 493 // objects more than once in case of interceptors, because the |
| 475 // holder will always be the interceptor holder and the search may | 494 // holder will always be the interceptor holder and the search may |
| 476 // only continue with a current object just after the interceptor | 495 // only continue with a current object just after the interceptor |
| 477 // holder in the prototype chain. | 496 // holder in the prototype chain. |
| 478 Object* last = result->IsProperty() ? result->holder() : Heap::null_value(); | 497 Object* last = result->IsProperty() ? result->holder() : heap->null_value(); |
| 479 for (Object* current = this; true; current = current->GetPrototype()) { | 498 for (Object* current = this; true; current = current->GetPrototype()) { |
| 480 if (current->IsAccessCheckNeeded()) { | 499 if (current->IsAccessCheckNeeded()) { |
| 481 // Check if we're allowed to read from the current object. Note | 500 // Check if we're allowed to read from the current object. Note |
| 482 // that even though we may not actually end up loading the named | 501 // that even though we may not actually end up loading the named |
| 483 // property from the current object, we still check that we have | 502 // property from the current object, we still check that we have |
| 484 // access to it. | 503 // access to it. |
| 485 JSObject* checked = JSObject::cast(current); | 504 JSObject* checked = JSObject::cast(current); |
| 486 if (!Top::MayNamedAccess(checked, name, v8::ACCESS_GET)) { | 505 if (!heap->isolate()->MayNamedAccess(checked, name, v8::ACCESS_GET)) { |
| 487 return checked->GetPropertyWithFailedAccessCheck(receiver, | 506 return checked->GetPropertyWithFailedAccessCheck(receiver, |
| 488 result, | 507 result, |
| 489 name, | 508 name, |
| 490 attributes); | 509 attributes); |
| 491 } | 510 } |
| 492 } | 511 } |
| 493 // Stop traversing the chain once we reach the last object in the | 512 // Stop traversing the chain once we reach the last object in the |
| 494 // chain; either the holder of the result or null in case of an | 513 // chain; either the holder of the result or null in case of an |
| 495 // absent property. | 514 // absent property. |
| 496 if (current == last) break; | 515 if (current == last) break; |
| 497 } | 516 } |
| 498 | 517 |
| 499 if (!result->IsProperty()) { | 518 if (!result->IsProperty()) { |
| 500 *attributes = ABSENT; | 519 *attributes = ABSENT; |
| 501 return Heap::undefined_value(); | 520 return heap->undefined_value(); |
| 502 } | 521 } |
| 503 *attributes = result->GetAttributes(); | 522 *attributes = result->GetAttributes(); |
| 504 Object* value; | 523 Object* value; |
| 505 JSObject* holder = result->holder(); | 524 JSObject* holder = result->holder(); |
| 506 switch (result->type()) { | 525 switch (result->type()) { |
| 507 case NORMAL: | 526 case NORMAL: |
| 508 value = holder->GetNormalizedProperty(result); | 527 value = holder->GetNormalizedProperty(result); |
| 509 ASSERT(!value->IsTheHole() || result->IsReadOnly()); | 528 ASSERT(!value->IsTheHole() || result->IsReadOnly()); |
| 510 return value->IsTheHole() ? Heap::undefined_value() : value; | 529 return value->IsTheHole() ? heap->undefined_value() : value; |
| 511 case FIELD: | 530 case FIELD: |
| 512 value = holder->FastPropertyAt(result->GetFieldIndex()); | 531 value = holder->FastPropertyAt(result->GetFieldIndex()); |
| 513 ASSERT(!value->IsTheHole() || result->IsReadOnly()); | 532 ASSERT(!value->IsTheHole() || result->IsReadOnly()); |
| 514 return value->IsTheHole() ? Heap::undefined_value() : value; | 533 return value->IsTheHole() ? heap->undefined_value() : value; |
| 515 case CONSTANT_FUNCTION: | 534 case CONSTANT_FUNCTION: |
| 516 return result->GetConstantFunction(); | 535 return result->GetConstantFunction(); |
| 517 case CALLBACKS: | 536 case CALLBACKS: |
| 518 return GetPropertyWithCallback(receiver, | 537 return GetPropertyWithCallback(receiver, |
| 519 result->GetCallbackObject(), | 538 result->GetCallbackObject(), |
| 520 name, | 539 name, |
| 521 holder); | 540 holder); |
| 522 case INTERCEPTOR: { | 541 case INTERCEPTOR: { |
| 523 JSObject* recvr = JSObject::cast(receiver); | 542 JSObject* recvr = JSObject::cast(receiver); |
| 524 return holder->GetPropertyWithInterceptor(recvr, name, attributes); | 543 return holder->GetPropertyWithInterceptor(recvr, name, attributes); |
| 525 } | 544 } |
| 526 default: | 545 default: |
| 527 UNREACHABLE(); | 546 UNREACHABLE(); |
| 528 return NULL; | 547 return NULL; |
| 529 } | 548 } |
| 530 } | 549 } |
| 531 | 550 |
| 532 | 551 |
| 533 MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) { | 552 MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) { |
| 534 if (IsJSObject()) { | 553 if (IsJSObject()) { |
| 535 return JSObject::cast(this)->GetElementWithReceiver(receiver, index); | 554 return JSObject::cast(this)->GetElementWithReceiver(receiver, index); |
| 536 } | 555 } |
| 537 | 556 |
| 538 Object* holder = NULL; | 557 Object* holder = NULL; |
| 539 Context* global_context = Top::context()->global_context(); | 558 Context* global_context = Isolate::Current()->context()->global_context(); |
| 540 if (IsString()) { | 559 if (IsString()) { |
| 541 holder = global_context->string_function()->instance_prototype(); | 560 holder = global_context->string_function()->instance_prototype(); |
| 542 } else if (IsNumber()) { | 561 } else if (IsNumber()) { |
| 543 holder = global_context->number_function()->instance_prototype(); | 562 holder = global_context->number_function()->instance_prototype(); |
| 544 } else if (IsBoolean()) { | 563 } else if (IsBoolean()) { |
| 545 holder = global_context->boolean_function()->instance_prototype(); | 564 holder = global_context->boolean_function()->instance_prototype(); |
| 546 } else { | 565 } else { |
| 547 // Undefined and null have no indexed properties. | 566 // Undefined and null have no indexed properties. |
| 548 ASSERT(IsUndefined() || IsNull()); | 567 ASSERT(IsUndefined() || IsNull()); |
| 549 return Heap::undefined_value(); | 568 return HEAP->undefined_value(); |
| 550 } | 569 } |
| 551 | 570 |
| 552 return JSObject::cast(holder)->GetElementWithReceiver(receiver, index); | 571 return JSObject::cast(holder)->GetElementWithReceiver(receiver, index); |
| 553 } | 572 } |
| 554 | 573 |
| 555 | 574 |
| 556 Object* Object::GetPrototype() { | 575 Object* Object::GetPrototype() { |
| 557 // The object is either a number, a string, a boolean, or a real JS object. | 576 // The object is either a number, a string, a boolean, or a real JS object. |
| 558 if (IsJSObject()) return JSObject::cast(this)->map()->prototype(); | 577 if (IsJSObject()) return JSObject::cast(this)->map()->prototype(); |
| 559 Context* context = Top::context()->global_context(); | 578 Heap* heap = Isolate::Current()->heap(); |
| 579 Context* context = heap->isolate()->context()->global_context(); |
| 560 | 580 |
| 561 if (IsNumber()) return context->number_function()->instance_prototype(); | 581 if (IsNumber()) return context->number_function()->instance_prototype(); |
| 562 if (IsString()) return context->string_function()->instance_prototype(); | 582 if (IsString()) return context->string_function()->instance_prototype(); |
| 563 if (IsBoolean()) { | 583 if (IsBoolean()) { |
| 564 return context->boolean_function()->instance_prototype(); | 584 return context->boolean_function()->instance_prototype(); |
| 565 } else { | 585 } else { |
| 566 return Heap::null_value(); | 586 return heap->null_value(); |
| 567 } | 587 } |
| 568 } | 588 } |
| 569 | 589 |
| 570 | 590 |
| 571 void Object::ShortPrint(FILE* out) { | 591 void Object::ShortPrint(FILE* out) { |
| 572 HeapStringAllocator allocator; | 592 HeapStringAllocator allocator; |
| 573 StringStream accumulator(&allocator); | 593 StringStream accumulator(&allocator); |
| 574 ShortPrint(&accumulator); | 594 ShortPrint(&accumulator); |
| 575 accumulator.OutputToFile(out); | 595 accumulator.OutputToFile(out); |
| 576 } | 596 } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 630 return false; | 650 return false; |
| 631 } | 651 } |
| 632 | 652 |
| 633 | 653 |
| 634 MaybeObject* String::SlowTryFlatten(PretenureFlag pretenure) { | 654 MaybeObject* String::SlowTryFlatten(PretenureFlag pretenure) { |
| 635 #ifdef DEBUG | 655 #ifdef DEBUG |
| 636 // Do not attempt to flatten in debug mode when allocation is not | 656 // Do not attempt to flatten in debug mode when allocation is not |
| 637 // allowed. This is to avoid an assertion failure when allocating. | 657 // allowed. This is to avoid an assertion failure when allocating. |
| 638 // Flattening strings is the only case where we always allow | 658 // Flattening strings is the only case where we always allow |
| 639 // allocation because no GC is performed if the allocation fails. | 659 // allocation because no GC is performed if the allocation fails. |
| 640 if (!Heap::IsAllocationAllowed()) return this; | 660 if (!HEAP->IsAllocationAllowed()) return this; |
| 641 #endif | 661 #endif |
| 642 | 662 |
| 663 Heap* heap = GetHeap(); |
| 643 switch (StringShape(this).representation_tag()) { | 664 switch (StringShape(this).representation_tag()) { |
| 644 case kConsStringTag: { | 665 case kConsStringTag: { |
| 645 ConsString* cs = ConsString::cast(this); | 666 ConsString* cs = ConsString::cast(this); |
| 646 if (cs->second()->length() == 0) { | 667 if (cs->second()->length() == 0) { |
| 647 return cs->first(); | 668 return cs->first(); |
| 648 } | 669 } |
| 649 // There's little point in putting the flat string in new space if the | 670 // There's little point in putting the flat string in new space if the |
| 650 // cons string is in old space. It can never get GCed until there is | 671 // cons string is in old space. It can never get GCed until there is |
| 651 // an old space GC. | 672 // an old space GC. |
| 652 PretenureFlag tenure = Heap::InNewSpace(this) ? pretenure : TENURED; | 673 PretenureFlag tenure = heap->InNewSpace(this) ? pretenure : TENURED; |
| 653 int len = length(); | 674 int len = length(); |
| 654 Object* object; | 675 Object* object; |
| 655 String* result; | 676 String* result; |
| 656 if (IsAsciiRepresentation()) { | 677 if (IsAsciiRepresentation()) { |
| 657 { MaybeObject* maybe_object = Heap::AllocateRawAsciiString(len, tenure); | 678 { MaybeObject* maybe_object = heap->AllocateRawAsciiString(len, tenure); |
| 658 if (!maybe_object->ToObject(&object)) return maybe_object; | 679 if (!maybe_object->ToObject(&object)) return maybe_object; |
| 659 } | 680 } |
| 660 result = String::cast(object); | 681 result = String::cast(object); |
| 661 String* first = cs->first(); | 682 String* first = cs->first(); |
| 662 int first_length = first->length(); | 683 int first_length = first->length(); |
| 663 char* dest = SeqAsciiString::cast(result)->GetChars(); | 684 char* dest = SeqAsciiString::cast(result)->GetChars(); |
| 664 WriteToFlat(first, dest, 0, first_length); | 685 WriteToFlat(first, dest, 0, first_length); |
| 665 String* second = cs->second(); | 686 String* second = cs->second(); |
| 666 WriteToFlat(second, | 687 WriteToFlat(second, |
| 667 dest + first_length, | 688 dest + first_length, |
| 668 0, | 689 0, |
| 669 len - first_length); | 690 len - first_length); |
| 670 } else { | 691 } else { |
| 671 { MaybeObject* maybe_object = | 692 { MaybeObject* maybe_object = |
| 672 Heap::AllocateRawTwoByteString(len, tenure); | 693 heap->AllocateRawTwoByteString(len, tenure); |
| 673 if (!maybe_object->ToObject(&object)) return maybe_object; | 694 if (!maybe_object->ToObject(&object)) return maybe_object; |
| 674 } | 695 } |
| 675 result = String::cast(object); | 696 result = String::cast(object); |
| 676 uc16* dest = SeqTwoByteString::cast(result)->GetChars(); | 697 uc16* dest = SeqTwoByteString::cast(result)->GetChars(); |
| 677 String* first = cs->first(); | 698 String* first = cs->first(); |
| 678 int first_length = first->length(); | 699 int first_length = first->length(); |
| 679 WriteToFlat(first, dest, 0, first_length); | 700 WriteToFlat(first, dest, 0, first_length); |
| 680 String* second = cs->second(); | 701 String* second = cs->second(); |
| 681 WriteToFlat(second, | 702 WriteToFlat(second, |
| 682 dest + first_length, | 703 dest + first_length, |
| 683 0, | 704 0, |
| 684 len - first_length); | 705 len - first_length); |
| 685 } | 706 } |
| 686 cs->set_first(result); | 707 cs->set_first(result); |
| 687 cs->set_second(Heap::empty_string()); | 708 cs->set_second(heap->empty_string()); |
| 688 return result; | 709 return result; |
| 689 } | 710 } |
| 690 default: | 711 default: |
| 691 return this; | 712 return this; |
| 692 } | 713 } |
| 693 } | 714 } |
| 694 | 715 |
| 695 | 716 |
| 696 bool String::MakeExternal(v8::String::ExternalStringResource* resource) { | 717 bool String::MakeExternal(v8::String::ExternalStringResource* resource) { |
| 697 // Externalizing twice leaks the external resource, so it's | 718 // Externalizing twice leaks the external resource, so it's |
| 698 // prohibited by the API. | 719 // prohibited by the API. |
| 699 ASSERT(!this->IsExternalString()); | 720 ASSERT(!this->IsExternalString()); |
| 700 #ifdef DEBUG | 721 #ifdef DEBUG |
| 701 if (FLAG_enable_slow_asserts) { | 722 if (FLAG_enable_slow_asserts) { |
| 702 // Assert that the resource and the string are equivalent. | 723 // Assert that the resource and the string are equivalent. |
| 703 ASSERT(static_cast<size_t>(this->length()) == resource->length()); | 724 ASSERT(static_cast<size_t>(this->length()) == resource->length()); |
| 704 ScopedVector<uc16> smart_chars(this->length()); | 725 ScopedVector<uc16> smart_chars(this->length()); |
| 705 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); | 726 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); |
| 706 ASSERT(memcmp(smart_chars.start(), | 727 ASSERT(memcmp(smart_chars.start(), |
| 707 resource->data(), | 728 resource->data(), |
| 708 resource->length() * sizeof(smart_chars[0])) == 0); | 729 resource->length() * sizeof(smart_chars[0])) == 0); |
| 709 } | 730 } |
| 710 #endif // DEBUG | 731 #endif // DEBUG |
| 711 | 732 Heap* heap = GetHeap(); |
| 712 int size = this->Size(); // Byte size of the original string. | 733 int size = this->Size(); // Byte size of the original string. |
| 713 if (size < ExternalString::kSize) { | 734 if (size < ExternalString::kSize) { |
| 714 // The string is too small to fit an external String in its place. This can | 735 // The string is too small to fit an external String in its place. This can |
| 715 // only happen for zero length strings. | 736 // only happen for zero length strings. |
| 716 return false; | 737 return false; |
| 717 } | 738 } |
| 718 ASSERT(size >= ExternalString::kSize); | 739 ASSERT(size >= ExternalString::kSize); |
| 719 bool is_ascii = this->IsAsciiRepresentation(); | 740 bool is_ascii = this->IsAsciiRepresentation(); |
| 720 bool is_symbol = this->IsSymbol(); | 741 bool is_symbol = this->IsSymbol(); |
| 721 int length = this->length(); | 742 int length = this->length(); |
| 722 int hash_field = this->hash_field(); | 743 int hash_field = this->hash_field(); |
| 723 | 744 |
| 724 // Morph the object to an external string by adjusting the map and | 745 // Morph the object to an external string by adjusting the map and |
| 725 // reinitializing the fields. | 746 // reinitializing the fields. |
| 726 this->set_map(is_ascii ? | 747 this->set_map(is_ascii ? |
| 727 Heap::external_string_with_ascii_data_map() : | 748 heap->external_string_with_ascii_data_map() : |
| 728 Heap::external_string_map()); | 749 heap->external_string_map()); |
| 729 ExternalTwoByteString* self = ExternalTwoByteString::cast(this); | 750 ExternalTwoByteString* self = ExternalTwoByteString::cast(this); |
| 730 self->set_length(length); | 751 self->set_length(length); |
| 731 self->set_hash_field(hash_field); | 752 self->set_hash_field(hash_field); |
| 732 self->set_resource(resource); | 753 self->set_resource(resource); |
| 733 // Additionally make the object into an external symbol if the original string | 754 // Additionally make the object into an external symbol if the original string |
| 734 // was a symbol to start with. | 755 // was a symbol to start with. |
| 735 if (is_symbol) { | 756 if (is_symbol) { |
| 736 self->Hash(); // Force regeneration of the hash value. | 757 self->Hash(); // Force regeneration of the hash value. |
| 737 // Now morph this external string into a external symbol. | 758 // Now morph this external string into a external symbol. |
| 738 this->set_map(is_ascii ? | 759 this->set_map(is_ascii ? |
| 739 Heap::external_symbol_with_ascii_data_map() : | 760 heap->external_symbol_with_ascii_data_map() : |
| 740 Heap::external_symbol_map()); | 761 heap->external_symbol_map()); |
| 741 } | 762 } |
| 742 | 763 |
| 743 // Fill the remainder of the string with dead wood. | 764 // Fill the remainder of the string with dead wood. |
| 744 int new_size = this->Size(); // Byte size of the external String object. | 765 int new_size = this->Size(); // Byte size of the external String object. |
| 745 Heap::CreateFillerObjectAt(this->address() + new_size, size - new_size); | 766 heap->CreateFillerObjectAt(this->address() + new_size, size - new_size); |
| 746 return true; | 767 return true; |
| 747 } | 768 } |
| 748 | 769 |
| 749 | 770 |
| 750 bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) { | 771 bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) { |
| 751 #ifdef DEBUG | 772 #ifdef DEBUG |
| 752 if (FLAG_enable_slow_asserts) { | 773 if (FLAG_enable_slow_asserts) { |
| 753 // Assert that the resource and the string are equivalent. | 774 // Assert that the resource and the string are equivalent. |
| 754 ASSERT(static_cast<size_t>(this->length()) == resource->length()); | 775 ASSERT(static_cast<size_t>(this->length()) == resource->length()); |
| 755 ScopedVector<char> smart_chars(this->length()); | 776 ScopedVector<char> smart_chars(this->length()); |
| 756 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); | 777 String::WriteToFlat(this, smart_chars.start(), 0, this->length()); |
| 757 ASSERT(memcmp(smart_chars.start(), | 778 ASSERT(memcmp(smart_chars.start(), |
| 758 resource->data(), | 779 resource->data(), |
| 759 resource->length() * sizeof(smart_chars[0])) == 0); | 780 resource->length() * sizeof(smart_chars[0])) == 0); |
| 760 } | 781 } |
| 761 #endif // DEBUG | 782 #endif // DEBUG |
| 762 | 783 Heap* heap = GetHeap(); |
| 763 int size = this->Size(); // Byte size of the original string. | 784 int size = this->Size(); // Byte size of the original string. |
| 764 if (size < ExternalString::kSize) { | 785 if (size < ExternalString::kSize) { |
| 765 // The string is too small to fit an external String in its place. This can | 786 // The string is too small to fit an external String in its place. This can |
| 766 // only happen for zero length strings. | 787 // only happen for zero length strings. |
| 767 return false; | 788 return false; |
| 768 } | 789 } |
| 769 ASSERT(size >= ExternalString::kSize); | 790 ASSERT(size >= ExternalString::kSize); |
| 770 bool is_symbol = this->IsSymbol(); | 791 bool is_symbol = this->IsSymbol(); |
| 771 int length = this->length(); | 792 int length = this->length(); |
| 772 int hash_field = this->hash_field(); | 793 int hash_field = this->hash_field(); |
| 773 | 794 |
| 774 // Morph the object to an external string by adjusting the map and | 795 // Morph the object to an external string by adjusting the map and |
| 775 // reinitializing the fields. | 796 // reinitializing the fields. |
| 776 this->set_map(Heap::external_ascii_string_map()); | 797 this->set_map(heap->external_ascii_string_map()); |
| 777 ExternalAsciiString* self = ExternalAsciiString::cast(this); | 798 ExternalAsciiString* self = ExternalAsciiString::cast(this); |
| 778 self->set_length(length); | 799 self->set_length(length); |
| 779 self->set_hash_field(hash_field); | 800 self->set_hash_field(hash_field); |
| 780 self->set_resource(resource); | 801 self->set_resource(resource); |
| 781 // Additionally make the object into an external symbol if the original string | 802 // Additionally make the object into an external symbol if the original string |
| 782 // was a symbol to start with. | 803 // was a symbol to start with. |
| 783 if (is_symbol) { | 804 if (is_symbol) { |
| 784 self->Hash(); // Force regeneration of the hash value. | 805 self->Hash(); // Force regeneration of the hash value. |
| 785 // Now morph this external string into a external symbol. | 806 // Now morph this external string into a external symbol. |
| 786 this->set_map(Heap::external_ascii_symbol_map()); | 807 this->set_map(heap->external_ascii_symbol_map()); |
| 787 } | 808 } |
| 788 | 809 |
| 789 // Fill the remainder of the string with dead wood. | 810 // Fill the remainder of the string with dead wood. |
| 790 int new_size = this->Size(); // Byte size of the external String object. | 811 int new_size = this->Size(); // Byte size of the external String object. |
| 791 Heap::CreateFillerObjectAt(this->address() + new_size, size - new_size); | 812 heap->CreateFillerObjectAt(this->address() + new_size, size - new_size); |
| 792 return true; | 813 return true; |
| 793 } | 814 } |
| 794 | 815 |
| 795 | 816 |
| 796 void String::StringShortPrint(StringStream* accumulator) { | 817 void String::StringShortPrint(StringStream* accumulator) { |
| 797 int len = length(); | 818 int len = length(); |
| 798 if (len > kMaxShortPrintLength) { | 819 if (len > kMaxShortPrintLength) { |
| 799 accumulator->Add("<Very long string[%u]>", len); | 820 accumulator->Add("<Very long string[%u]>", len); |
| 800 return; | 821 return; |
| 801 } | 822 } |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 880 } | 901 } |
| 881 } | 902 } |
| 882 if (!printed) { | 903 if (!printed) { |
| 883 accumulator->Add("<JS Function>"); | 904 accumulator->Add("<JS Function>"); |
| 884 } | 905 } |
| 885 break; | 906 break; |
| 886 } | 907 } |
| 887 // All other JSObjects are rather similar to each other (JSObject, | 908 // All other JSObjects are rather similar to each other (JSObject, |
| 888 // JSGlobalProxy, JSGlobalObject, JSUndetectableObject, JSValue). | 909 // JSGlobalProxy, JSGlobalObject, JSUndetectableObject, JSValue). |
| 889 default: { | 910 default: { |
| 911 Heap* heap = GetHeap(); |
| 890 Object* constructor = map()->constructor(); | 912 Object* constructor = map()->constructor(); |
| 891 bool printed = false; | 913 bool printed = false; |
| 892 if (constructor->IsHeapObject() && | 914 if (constructor->IsHeapObject() && |
| 893 !Heap::Contains(HeapObject::cast(constructor))) { | 915 !heap->Contains(HeapObject::cast(constructor))) { |
| 894 accumulator->Add("!!!INVALID CONSTRUCTOR!!!"); | 916 accumulator->Add("!!!INVALID CONSTRUCTOR!!!"); |
| 895 } else { | 917 } else { |
| 896 bool global_object = IsJSGlobalProxy(); | 918 bool global_object = IsJSGlobalProxy(); |
| 897 if (constructor->IsJSFunction()) { | 919 if (constructor->IsJSFunction()) { |
| 898 if (!Heap::Contains(JSFunction::cast(constructor)->shared())) { | 920 if (!heap->Contains(JSFunction::cast(constructor)->shared())) { |
| 899 accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!"); | 921 accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!"); |
| 900 } else { | 922 } else { |
| 901 Object* constructor_name = | 923 Object* constructor_name = |
| 902 JSFunction::cast(constructor)->shared()->name(); | 924 JSFunction::cast(constructor)->shared()->name(); |
| 903 if (constructor_name->IsString()) { | 925 if (constructor_name->IsString()) { |
| 904 String* str = String::cast(constructor_name); | 926 String* str = String::cast(constructor_name); |
| 905 if (str->length() > 0) { | 927 if (str->length() > 0) { |
| 906 bool vowel = AnWord(str); | 928 bool vowel = AnWord(str); |
| 907 accumulator->Add("<%sa%s ", | 929 accumulator->Add("<%sa%s ", |
| 908 global_object ? "Global Object: " : "", | 930 global_object ? "Global Object: " : "", |
| (...skipping 14 matching lines...) Expand all Loading... |
| 923 JSValue::cast(this)->value()->ShortPrint(accumulator); | 945 JSValue::cast(this)->value()->ShortPrint(accumulator); |
| 924 } | 946 } |
| 925 accumulator->Put('>'); | 947 accumulator->Put('>'); |
| 926 break; | 948 break; |
| 927 } | 949 } |
| 928 } | 950 } |
| 929 } | 951 } |
| 930 | 952 |
| 931 | 953 |
| 932 void HeapObject::HeapObjectShortPrint(StringStream* accumulator) { | 954 void HeapObject::HeapObjectShortPrint(StringStream* accumulator) { |
| 933 // if (!Heap::InNewSpace(this)) PrintF("*", this); | 955 // if (!HEAP->InNewSpace(this)) PrintF("*", this); |
| 934 if (!Heap::Contains(this)) { | 956 Heap* heap = GetHeap(); |
| 957 if (!heap->Contains(this)) { |
| 935 accumulator->Add("!!!INVALID POINTER!!!"); | 958 accumulator->Add("!!!INVALID POINTER!!!"); |
| 936 return; | 959 return; |
| 937 } | 960 } |
| 938 if (!Heap::Contains(map())) { | 961 if (!heap->Contains(map())) { |
| 939 accumulator->Add("!!!INVALID MAP!!!"); | 962 accumulator->Add("!!!INVALID MAP!!!"); |
| 940 return; | 963 return; |
| 941 } | 964 } |
| 942 | 965 |
| 943 accumulator->Add("%p ", this); | 966 accumulator->Add("%p ", this); |
| 944 | 967 |
| 945 if (IsString()) { | 968 if (IsString()) { |
| 946 String::cast(this)->StringShortPrint(accumulator); | 969 String::cast(this)->StringShortPrint(accumulator); |
| 947 return; | 970 return; |
| 948 } | 971 } |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1143 // NaN, +0, and -0 should return the false object | 1166 // NaN, +0, and -0 should return the false object |
| 1144 #if __BYTE_ORDER == __LITTLE_ENDIAN | 1167 #if __BYTE_ORDER == __LITTLE_ENDIAN |
| 1145 union IeeeDoubleLittleEndianArchType u; | 1168 union IeeeDoubleLittleEndianArchType u; |
| 1146 #elif __BYTE_ORDER == __BIG_ENDIAN | 1169 #elif __BYTE_ORDER == __BIG_ENDIAN |
| 1147 union IeeeDoubleBigEndianArchType u; | 1170 union IeeeDoubleBigEndianArchType u; |
| 1148 #endif | 1171 #endif |
| 1149 u.d = value(); | 1172 u.d = value(); |
| 1150 if (u.bits.exp == 2047) { | 1173 if (u.bits.exp == 2047) { |
| 1151 // Detect NaN for IEEE double precision floating point. | 1174 // Detect NaN for IEEE double precision floating point. |
| 1152 if ((u.bits.man_low | u.bits.man_high) != 0) | 1175 if ((u.bits.man_low | u.bits.man_high) != 0) |
| 1153 return Heap::false_value(); | 1176 return GetHeap()->false_value(); |
| 1154 } | 1177 } |
| 1155 if (u.bits.exp == 0) { | 1178 if (u.bits.exp == 0) { |
| 1156 // Detect +0, and -0 for IEEE double precision floating point. | 1179 // Detect +0, and -0 for IEEE double precision floating point. |
| 1157 if ((u.bits.man_low | u.bits.man_high) == 0) | 1180 if ((u.bits.man_low | u.bits.man_high) == 0) |
| 1158 return Heap::false_value(); | 1181 return GetHeap()->false_value(); |
| 1159 } | 1182 } |
| 1160 return Heap::true_value(); | 1183 return GetHeap()->true_value(); |
| 1161 } | 1184 } |
| 1162 | 1185 |
| 1163 | 1186 |
| 1164 void HeapNumber::HeapNumberPrint(FILE* out) { | 1187 void HeapNumber::HeapNumberPrint(FILE* out) { |
| 1165 PrintF(out, "%.16g", Number()); | 1188 PrintF(out, "%.16g", Number()); |
| 1166 } | 1189 } |
| 1167 | 1190 |
| 1168 | 1191 |
| 1169 void HeapNumber::HeapNumberPrint(StringStream* accumulator) { | 1192 void HeapNumber::HeapNumberPrint(StringStream* accumulator) { |
| 1170 // The Windows version of vsnprintf can allocate when printing a %g string | 1193 // The Windows version of vsnprintf can allocate when printing a %g string |
| 1171 // into a buffer that may not be big enough. We don't want random memory | 1194 // into a buffer that may not be big enough. We don't want random memory |
| 1172 // allocation when producing post-crash stack traces, so we print into a | 1195 // allocation when producing post-crash stack traces, so we print into a |
| 1173 // buffer that is plenty big enough for any floating point number, then | 1196 // buffer that is plenty big enough for any floating point number, then |
| 1174 // print that using vsnprintf (which may truncate but never allocate if | 1197 // print that using vsnprintf (which may truncate but never allocate if |
| 1175 // there is no more space in the buffer). | 1198 // there is no more space in the buffer). |
| 1176 EmbeddedVector<char, 100> buffer; | 1199 EmbeddedVector<char, 100> buffer; |
| 1177 OS::SNPrintF(buffer, "%.16g", Number()); | 1200 OS::SNPrintF(buffer, "%.16g", Number()); |
| 1178 accumulator->Add("%s", buffer.start()); | 1201 accumulator->Add("%s", buffer.start()); |
| 1179 } | 1202 } |
| 1180 | 1203 |
| 1181 | 1204 |
| 1182 String* JSObject::class_name() { | 1205 String* JSObject::class_name() { |
| 1183 if (IsJSFunction()) { | 1206 if (IsJSFunction()) { |
| 1184 return Heap::function_class_symbol(); | 1207 return GetHeap()->function_class_symbol(); |
| 1185 } | 1208 } |
| 1186 if (map()->constructor()->IsJSFunction()) { | 1209 if (map()->constructor()->IsJSFunction()) { |
| 1187 JSFunction* constructor = JSFunction::cast(map()->constructor()); | 1210 JSFunction* constructor = JSFunction::cast(map()->constructor()); |
| 1188 return String::cast(constructor->shared()->instance_class_name()); | 1211 return String::cast(constructor->shared()->instance_class_name()); |
| 1189 } | 1212 } |
| 1190 // If the constructor is not present, return "Object". | 1213 // If the constructor is not present, return "Object". |
| 1191 return Heap::Object_symbol(); | 1214 return GetHeap()->Object_symbol(); |
| 1192 } | 1215 } |
| 1193 | 1216 |
| 1194 | 1217 |
| 1195 String* JSObject::constructor_name() { | 1218 String* JSObject::constructor_name() { |
| 1196 if (map()->constructor()->IsJSFunction()) { | 1219 if (map()->constructor()->IsJSFunction()) { |
| 1197 JSFunction* constructor = JSFunction::cast(map()->constructor()); | 1220 JSFunction* constructor = JSFunction::cast(map()->constructor()); |
| 1198 String* name = String::cast(constructor->shared()->name()); | 1221 String* name = String::cast(constructor->shared()->name()); |
| 1199 if (name->length() > 0) return name; | 1222 if (name->length() > 0) return name; |
| 1200 String* inferred_name = constructor->shared()->inferred_name(); | 1223 String* inferred_name = constructor->shared()->inferred_name(); |
| 1201 if (inferred_name->length() > 0) return inferred_name; | 1224 if (inferred_name->length() > 0) return inferred_name; |
| 1202 Object* proto = GetPrototype(); | 1225 Object* proto = GetPrototype(); |
| 1203 if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name(); | 1226 if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name(); |
| 1204 } | 1227 } |
| 1205 // If the constructor is not present, return "Object". | 1228 // If the constructor is not present, return "Object". |
| 1206 return Heap::Object_symbol(); | 1229 return GetHeap()->Object_symbol(); |
| 1207 } | 1230 } |
| 1208 | 1231 |
| 1209 | 1232 |
| 1210 MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map, | 1233 MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map, |
| 1211 String* name, | 1234 String* name, |
| 1212 Object* value) { | 1235 Object* value) { |
| 1213 int index = new_map->PropertyIndexFor(name); | 1236 int index = new_map->PropertyIndexFor(name); |
| 1214 if (map()->unused_property_fields() == 0) { | 1237 if (map()->unused_property_fields() == 0) { |
| 1215 ASSERT(map()->unused_property_fields() == 0); | 1238 ASSERT(map()->unused_property_fields() == 0); |
| 1216 int new_unused = new_map->unused_property_fields(); | 1239 int new_unused = new_map->unused_property_fields(); |
| 1217 Object* values; | 1240 Object* values; |
| 1218 { MaybeObject* maybe_values = | 1241 { MaybeObject* maybe_values = |
| 1219 properties()->CopySize(properties()->length() + new_unused + 1); | 1242 properties()->CopySize(properties()->length() + new_unused + 1); |
| 1220 if (!maybe_values->ToObject(&values)) return maybe_values; | 1243 if (!maybe_values->ToObject(&values)) return maybe_values; |
| 1221 } | 1244 } |
| 1222 set_properties(FixedArray::cast(values)); | 1245 set_properties(FixedArray::cast(values)); |
| 1223 } | 1246 } |
| 1224 set_map(new_map); | 1247 set_map(new_map); |
| 1225 return FastPropertyAtPut(index, value); | 1248 return FastPropertyAtPut(index, value); |
| 1226 } | 1249 } |
| 1227 | 1250 |
| 1228 | 1251 |
| 1229 MaybeObject* JSObject::AddFastProperty(String* name, | 1252 MaybeObject* JSObject::AddFastProperty(String* name, |
| 1230 Object* value, | 1253 Object* value, |
| 1231 PropertyAttributes attributes) { | 1254 PropertyAttributes attributes) { |
| 1232 ASSERT(!IsJSGlobalProxy()); | 1255 ASSERT(!IsJSGlobalProxy()); |
| 1233 | 1256 |
| 1234 // Normalize the object if the name is an actual string (not the | 1257 // Normalize the object if the name is an actual string (not the |
| 1235 // hidden symbols) and is not a real identifier. | 1258 // hidden symbols) and is not a real identifier. |
| 1259 Isolate* isolate = GetHeap()->isolate(); |
| 1236 StringInputBuffer buffer(name); | 1260 StringInputBuffer buffer(name); |
| 1237 if (!ScannerConstants::IsIdentifier(&buffer) | 1261 if (!isolate->scanner_constants()->IsIdentifier(&buffer) |
| 1238 && name != Heap::hidden_symbol()) { | 1262 && name != HEAP->hidden_symbol()) { |
| 1239 Object* obj; | 1263 Object* obj; |
| 1240 { MaybeObject* maybe_obj = | 1264 { MaybeObject* maybe_obj = |
| 1241 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 1265 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
| 1242 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1266 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 1243 } | 1267 } |
| 1244 return AddSlowProperty(name, value, attributes); | 1268 return AddSlowProperty(name, value, attributes); |
| 1245 } | 1269 } |
| 1246 | 1270 |
| 1247 DescriptorArray* old_descriptors = map()->instance_descriptors(); | 1271 DescriptorArray* old_descriptors = map()->instance_descriptors(); |
| 1248 // Compute the new index for new field. | 1272 // Compute the new index for new field. |
| 1249 int index = map()->NextFreePropertyIndex(); | 1273 int index = map()->NextFreePropertyIndex(); |
| 1250 | 1274 |
| 1251 // Allocate new instance descriptors with (name, index) added | 1275 // Allocate new instance descriptors with (name, index) added |
| 1252 FieldDescriptor new_field(name, index, attributes); | 1276 FieldDescriptor new_field(name, index, attributes); |
| 1253 Object* new_descriptors; | 1277 Object* new_descriptors; |
| 1254 { MaybeObject* maybe_new_descriptors = | 1278 { MaybeObject* maybe_new_descriptors = |
| 1255 old_descriptors->CopyInsert(&new_field, REMOVE_TRANSITIONS); | 1279 old_descriptors->CopyInsert(&new_field, REMOVE_TRANSITIONS); |
| 1256 if (!maybe_new_descriptors->ToObject(&new_descriptors)) { | 1280 if (!maybe_new_descriptors->ToObject(&new_descriptors)) { |
| 1257 return maybe_new_descriptors; | 1281 return maybe_new_descriptors; |
| 1258 } | 1282 } |
| 1259 } | 1283 } |
| 1260 | 1284 |
| 1261 // Only allow map transition if the object's map is NOT equal to the | 1285 // Only allow map transition if the object's map is NOT equal to the |
| 1262 // global object_function's map and there is not a transition for name. | 1286 // global object_function's map and there is not a transition for name. |
| 1263 bool allow_map_transition = | 1287 bool allow_map_transition = |
| 1264 !old_descriptors->Contains(name) && | 1288 !old_descriptors->Contains(name) && |
| 1265 (Top::context()->global_context()->object_function()->map() != map()); | 1289 (isolate->context()->global_context()->object_function()-> |
| 1290 map() != map()); |
| 1266 | 1291 |
| 1267 ASSERT(index < map()->inobject_properties() || | 1292 ASSERT(index < map()->inobject_properties() || |
| 1268 (index - map()->inobject_properties()) < properties()->length() || | 1293 (index - map()->inobject_properties()) < properties()->length() || |
| 1269 map()->unused_property_fields() == 0); | 1294 map()->unused_property_fields() == 0); |
| 1270 // Allocate a new map for the object. | 1295 // Allocate a new map for the object. |
| 1271 Object* r; | 1296 Object* r; |
| 1272 { MaybeObject* maybe_r = map()->CopyDropDescriptors(); | 1297 { MaybeObject* maybe_r = map()->CopyDropDescriptors(); |
| 1273 if (!maybe_r->ToObject(&r)) return maybe_r; | 1298 if (!maybe_r->ToObject(&r)) return maybe_r; |
| 1274 } | 1299 } |
| 1275 Map* new_map = Map::cast(r); | 1300 Map* new_map = Map::cast(r); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1309 new_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors)); | 1334 new_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors)); |
| 1310 set_map(new_map); | 1335 set_map(new_map); |
| 1311 return FastPropertyAtPut(index, value); | 1336 return FastPropertyAtPut(index, value); |
| 1312 } | 1337 } |
| 1313 | 1338 |
| 1314 | 1339 |
| 1315 MaybeObject* JSObject::AddConstantFunctionProperty( | 1340 MaybeObject* JSObject::AddConstantFunctionProperty( |
| 1316 String* name, | 1341 String* name, |
| 1317 JSFunction* function, | 1342 JSFunction* function, |
| 1318 PropertyAttributes attributes) { | 1343 PropertyAttributes attributes) { |
| 1319 ASSERT(!Heap::InNewSpace(function)); | 1344 Heap* heap = GetHeap(); |
| 1345 ASSERT(!heap->InNewSpace(function)); |
| 1320 | 1346 |
| 1321 // Allocate new instance descriptors with (name, function) added | 1347 // Allocate new instance descriptors with (name, function) added |
| 1322 ConstantFunctionDescriptor d(name, function, attributes); | 1348 ConstantFunctionDescriptor d(name, function, attributes); |
| 1323 Object* new_descriptors; | 1349 Object* new_descriptors; |
| 1324 { MaybeObject* maybe_new_descriptors = | 1350 { MaybeObject* maybe_new_descriptors = |
| 1325 map()->instance_descriptors()->CopyInsert(&d, REMOVE_TRANSITIONS); | 1351 map()->instance_descriptors()->CopyInsert(&d, REMOVE_TRANSITIONS); |
| 1326 if (!maybe_new_descriptors->ToObject(&new_descriptors)) { | 1352 if (!maybe_new_descriptors->ToObject(&new_descriptors)) { |
| 1327 return maybe_new_descriptors; | 1353 return maybe_new_descriptors; |
| 1328 } | 1354 } |
| 1329 } | 1355 } |
| 1330 | 1356 |
| 1331 // Allocate a new map for the object. | 1357 // Allocate a new map for the object. |
| 1332 Object* new_map; | 1358 Object* new_map; |
| 1333 { MaybeObject* maybe_new_map = map()->CopyDropDescriptors(); | 1359 { MaybeObject* maybe_new_map = map()->CopyDropDescriptors(); |
| 1334 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; | 1360 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; |
| 1335 } | 1361 } |
| 1336 | 1362 |
| 1337 DescriptorArray* descriptors = DescriptorArray::cast(new_descriptors); | 1363 DescriptorArray* descriptors = DescriptorArray::cast(new_descriptors); |
| 1338 Map::cast(new_map)->set_instance_descriptors(descriptors); | 1364 Map::cast(new_map)->set_instance_descriptors(descriptors); |
| 1339 Map* old_map = map(); | 1365 Map* old_map = map(); |
| 1340 set_map(Map::cast(new_map)); | 1366 set_map(Map::cast(new_map)); |
| 1341 | 1367 |
| 1342 // If the old map is the global object map (from new Object()), | 1368 // If the old map is the global object map (from new Object()), |
| 1343 // then transitions are not added to it, so we are done. | 1369 // then transitions are not added to it, so we are done. |
| 1344 if (old_map == Top::context()->global_context()->object_function()->map()) { | 1370 if (old_map == heap->isolate()->context()->global_context()-> |
| 1371 object_function()->map()) { |
| 1345 return function; | 1372 return function; |
| 1346 } | 1373 } |
| 1347 | 1374 |
| 1348 // Do not add CONSTANT_TRANSITIONS to global objects | 1375 // Do not add CONSTANT_TRANSITIONS to global objects |
| 1349 if (IsGlobalObject()) { | 1376 if (IsGlobalObject()) { |
| 1350 return function; | 1377 return function; |
| 1351 } | 1378 } |
| 1352 | 1379 |
| 1353 // Add a CONSTANT_TRANSITION descriptor to the old map, | 1380 // Add a CONSTANT_TRANSITION descriptor to the old map, |
| 1354 // so future assignments to this property on other objects | 1381 // so future assignments to this property on other objects |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1369 | 1396 |
| 1370 return function; | 1397 return function; |
| 1371 } | 1398 } |
| 1372 | 1399 |
| 1373 | 1400 |
| 1374 // Add property in slow mode | 1401 // Add property in slow mode |
| 1375 MaybeObject* JSObject::AddSlowProperty(String* name, | 1402 MaybeObject* JSObject::AddSlowProperty(String* name, |
| 1376 Object* value, | 1403 Object* value, |
| 1377 PropertyAttributes attributes) { | 1404 PropertyAttributes attributes) { |
| 1378 ASSERT(!HasFastProperties()); | 1405 ASSERT(!HasFastProperties()); |
| 1406 Heap* heap = GetHeap(); |
| 1379 StringDictionary* dict = property_dictionary(); | 1407 StringDictionary* dict = property_dictionary(); |
| 1380 Object* store_value = value; | 1408 Object* store_value = value; |
| 1381 if (IsGlobalObject()) { | 1409 if (IsGlobalObject()) { |
| 1382 // In case name is an orphaned property reuse the cell. | 1410 // In case name is an orphaned property reuse the cell. |
| 1383 int entry = dict->FindEntry(name); | 1411 int entry = dict->FindEntry(name); |
| 1384 if (entry != StringDictionary::kNotFound) { | 1412 if (entry != StringDictionary::kNotFound) { |
| 1385 store_value = dict->ValueAt(entry); | 1413 store_value = dict->ValueAt(entry); |
| 1386 JSGlobalPropertyCell::cast(store_value)->set_value(value); | 1414 JSGlobalPropertyCell::cast(store_value)->set_value(value); |
| 1387 // Assign an enumeration index to the property and update | 1415 // Assign an enumeration index to the property and update |
| 1388 // SetNextEnumerationIndex. | 1416 // SetNextEnumerationIndex. |
| 1389 int index = dict->NextEnumerationIndex(); | 1417 int index = dict->NextEnumerationIndex(); |
| 1390 PropertyDetails details = PropertyDetails(attributes, NORMAL, index); | 1418 PropertyDetails details = PropertyDetails(attributes, NORMAL, index); |
| 1391 dict->SetNextEnumerationIndex(index + 1); | 1419 dict->SetNextEnumerationIndex(index + 1); |
| 1392 dict->SetEntry(entry, name, store_value, details); | 1420 dict->SetEntry(entry, name, store_value, details); |
| 1393 return value; | 1421 return value; |
| 1394 } | 1422 } |
| 1395 { MaybeObject* maybe_store_value = | 1423 { MaybeObject* maybe_store_value = |
| 1396 Heap::AllocateJSGlobalPropertyCell(value); | 1424 heap->AllocateJSGlobalPropertyCell(value); |
| 1397 if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value; | 1425 if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value; |
| 1398 } | 1426 } |
| 1399 JSGlobalPropertyCell::cast(store_value)->set_value(value); | 1427 JSGlobalPropertyCell::cast(store_value)->set_value(value); |
| 1400 } | 1428 } |
| 1401 PropertyDetails details = PropertyDetails(attributes, NORMAL); | 1429 PropertyDetails details = PropertyDetails(attributes, NORMAL); |
| 1402 Object* result; | 1430 Object* result; |
| 1403 { MaybeObject* maybe_result = dict->Add(name, store_value, details); | 1431 { MaybeObject* maybe_result = dict->Add(name, store_value, details); |
| 1404 if (!maybe_result->ToObject(&result)) return maybe_result; | 1432 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 1405 } | 1433 } |
| 1406 if (dict != result) set_properties(StringDictionary::cast(result)); | 1434 if (dict != result) set_properties(StringDictionary::cast(result)); |
| 1407 return value; | 1435 return value; |
| 1408 } | 1436 } |
| 1409 | 1437 |
| 1410 | 1438 |
| 1411 MaybeObject* JSObject::AddProperty(String* name, | 1439 MaybeObject* JSObject::AddProperty(String* name, |
| 1412 Object* value, | 1440 Object* value, |
| 1413 PropertyAttributes attributes) { | 1441 PropertyAttributes attributes) { |
| 1414 ASSERT(!IsJSGlobalProxy()); | 1442 ASSERT(!IsJSGlobalProxy()); |
| 1443 Heap* heap = GetHeap(); |
| 1415 if (!map()->is_extensible()) { | 1444 if (!map()->is_extensible()) { |
| 1416 Handle<Object> args[1] = {Handle<String>(name)}; | 1445 Handle<Object> args[1] = {Handle<String>(name)}; |
| 1417 return Top::Throw(*Factory::NewTypeError("object_not_extensible", | 1446 return heap->isolate()->Throw( |
| 1418 HandleVector(args, 1))); | 1447 *FACTORY->NewTypeError("object_not_extensible", HandleVector(args, 1))); |
| 1419 } | 1448 } |
| 1420 if (HasFastProperties()) { | 1449 if (HasFastProperties()) { |
| 1421 // Ensure the descriptor array does not get too big. | 1450 // Ensure the descriptor array does not get too big. |
| 1422 if (map()->instance_descriptors()->number_of_descriptors() < | 1451 if (map()->instance_descriptors()->number_of_descriptors() < |
| 1423 DescriptorArray::kMaxNumberOfDescriptors) { | 1452 DescriptorArray::kMaxNumberOfDescriptors) { |
| 1424 if (value->IsJSFunction() && !Heap::InNewSpace(value)) { | 1453 if (value->IsJSFunction() && !heap->InNewSpace(value)) { |
| 1425 return AddConstantFunctionProperty(name, | 1454 return AddConstantFunctionProperty(name, |
| 1426 JSFunction::cast(value), | 1455 JSFunction::cast(value), |
| 1427 attributes); | 1456 attributes); |
| 1428 } else { | 1457 } else { |
| 1429 return AddFastProperty(name, value, attributes); | 1458 return AddFastProperty(name, value, attributes); |
| 1430 } | 1459 } |
| 1431 } else { | 1460 } else { |
| 1432 // Normalize the object to prevent very large instance descriptors. | 1461 // Normalize the object to prevent very large instance descriptors. |
| 1433 // This eliminates unwanted N^2 allocation and lookup behavior. | 1462 // This eliminates unwanted N^2 allocation and lookup behavior. |
| 1434 Object* obj; | 1463 Object* obj; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1486 { MaybeObject* maybe_result = | 1515 { MaybeObject* maybe_result = |
| 1487 ConvertDescriptorToField(name, new_value, attributes); | 1516 ConvertDescriptorToField(name, new_value, attributes); |
| 1488 if (!maybe_result->ToObject(&result)) return maybe_result; | 1517 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 1489 } | 1518 } |
| 1490 // If we get to this point we have succeeded - do not return failure | 1519 // If we get to this point we have succeeded - do not return failure |
| 1491 // after this point. Later stuff is optional. | 1520 // after this point. Later stuff is optional. |
| 1492 if (!HasFastProperties()) { | 1521 if (!HasFastProperties()) { |
| 1493 return result; | 1522 return result; |
| 1494 } | 1523 } |
| 1495 // Do not add transitions to the map of "new Object()". | 1524 // Do not add transitions to the map of "new Object()". |
| 1496 if (map() == Top::context()->global_context()->object_function()->map()) { | 1525 if (map() == GetHeap()->isolate()->context()->global_context()-> |
| 1526 object_function()->map()) { |
| 1497 return result; | 1527 return result; |
| 1498 } | 1528 } |
| 1499 | 1529 |
| 1500 MapTransitionDescriptor transition(name, | 1530 MapTransitionDescriptor transition(name, |
| 1501 map(), | 1531 map(), |
| 1502 attributes); | 1532 attributes); |
| 1503 Object* new_descriptors; | 1533 Object* new_descriptors; |
| 1504 { MaybeObject* maybe_new_descriptors = old_map->instance_descriptors()-> | 1534 { MaybeObject* maybe_new_descriptors = old_map->instance_descriptors()-> |
| 1505 CopyInsert(&transition, KEEP_TRANSITIONS); | 1535 CopyInsert(&transition, KEEP_TRANSITIONS); |
| 1506 if (!maybe_new_descriptors->ToObject(&new_descriptors)) { | 1536 if (!maybe_new_descriptors->ToObject(&new_descriptors)) { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1573 return FastPropertyAtPut(index, new_value); | 1603 return FastPropertyAtPut(index, new_value); |
| 1574 } | 1604 } |
| 1575 | 1605 |
| 1576 | 1606 |
| 1577 | 1607 |
| 1578 MaybeObject* JSObject::SetPropertyWithInterceptor( | 1608 MaybeObject* JSObject::SetPropertyWithInterceptor( |
| 1579 String* name, | 1609 String* name, |
| 1580 Object* value, | 1610 Object* value, |
| 1581 PropertyAttributes attributes, | 1611 PropertyAttributes attributes, |
| 1582 StrictModeFlag strict_mode) { | 1612 StrictModeFlag strict_mode) { |
| 1583 HandleScope scope; | 1613 Isolate* isolate = GetIsolate(); |
| 1614 HandleScope scope(isolate); |
| 1584 Handle<JSObject> this_handle(this); | 1615 Handle<JSObject> this_handle(this); |
| 1585 Handle<String> name_handle(name); | 1616 Handle<String> name_handle(name); |
| 1586 Handle<Object> value_handle(value); | 1617 Handle<Object> value_handle(value, isolate); |
| 1587 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); | 1618 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); |
| 1588 if (!interceptor->setter()->IsUndefined()) { | 1619 if (!interceptor->setter()->IsUndefined()) { |
| 1589 LOG(ApiNamedPropertyAccess("interceptor-named-set", this, name)); | 1620 LOG(isolate, ApiNamedPropertyAccess("interceptor-named-set", this, name)); |
| 1590 CustomArguments args(interceptor->data(), this, this); | 1621 CustomArguments args(isolate, interceptor->data(), this, this); |
| 1591 v8::AccessorInfo info(args.end()); | 1622 v8::AccessorInfo info(args.end()); |
| 1592 v8::NamedPropertySetter setter = | 1623 v8::NamedPropertySetter setter = |
| 1593 v8::ToCData<v8::NamedPropertySetter>(interceptor->setter()); | 1624 v8::ToCData<v8::NamedPropertySetter>(interceptor->setter()); |
| 1594 v8::Handle<v8::Value> result; | 1625 v8::Handle<v8::Value> result; |
| 1595 { | 1626 { |
| 1596 // Leaving JavaScript. | 1627 // Leaving JavaScript. |
| 1597 VMState state(EXTERNAL); | 1628 VMState state(isolate, EXTERNAL); |
| 1598 Handle<Object> value_unhole(value->IsTheHole() ? | 1629 Handle<Object> value_unhole(value->IsTheHole() ? |
| 1599 Heap::undefined_value() : | 1630 isolate->heap()->undefined_value() : |
| 1600 value); | 1631 value, |
| 1632 isolate); |
| 1601 result = setter(v8::Utils::ToLocal(name_handle), | 1633 result = setter(v8::Utils::ToLocal(name_handle), |
| 1602 v8::Utils::ToLocal(value_unhole), | 1634 v8::Utils::ToLocal(value_unhole), |
| 1603 info); | 1635 info); |
| 1604 } | 1636 } |
| 1605 RETURN_IF_SCHEDULED_EXCEPTION(); | 1637 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 1606 if (!result.IsEmpty()) return *value_handle; | 1638 if (!result.IsEmpty()) return *value_handle; |
| 1607 } | 1639 } |
| 1608 MaybeObject* raw_result = | 1640 MaybeObject* raw_result = |
| 1609 this_handle->SetPropertyPostInterceptor(*name_handle, | 1641 this_handle->SetPropertyPostInterceptor(*name_handle, |
| 1610 *value_handle, | 1642 *value_handle, |
| 1611 attributes, | 1643 attributes, |
| 1612 strict_mode); | 1644 strict_mode); |
| 1613 RETURN_IF_SCHEDULED_EXCEPTION(); | 1645 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 1614 return raw_result; | 1646 return raw_result; |
| 1615 } | 1647 } |
| 1616 | 1648 |
| 1617 | 1649 |
| 1618 MaybeObject* JSObject::SetProperty(String* name, | 1650 MaybeObject* JSObject::SetProperty(String* name, |
| 1619 Object* value, | 1651 Object* value, |
| 1620 PropertyAttributes attributes, | 1652 PropertyAttributes attributes, |
| 1621 StrictModeFlag strict_mode) { | 1653 StrictModeFlag strict_mode) { |
| 1622 LookupResult result; | 1654 LookupResult result; |
| 1623 LocalLookup(name, &result); | 1655 LocalLookup(name, &result); |
| 1624 return SetProperty(&result, name, value, attributes, strict_mode); | 1656 return SetProperty(&result, name, value, attributes, strict_mode); |
| 1625 } | 1657 } |
| 1626 | 1658 |
| 1627 | 1659 |
| 1628 MaybeObject* JSObject::SetPropertyWithCallback(Object* structure, | 1660 MaybeObject* JSObject::SetPropertyWithCallback(Object* structure, |
| 1629 String* name, | 1661 String* name, |
| 1630 Object* value, | 1662 Object* value, |
| 1631 JSObject* holder) { | 1663 JSObject* holder) { |
| 1632 HandleScope scope; | 1664 Isolate* isolate = GetIsolate(); |
| 1665 HandleScope scope(isolate); |
| 1633 | 1666 |
| 1634 // We should never get here to initialize a const with the hole | 1667 // We should never get here to initialize a const with the hole |
| 1635 // value since a const declaration would conflict with the setter. | 1668 // value since a const declaration would conflict with the setter. |
| 1636 ASSERT(!value->IsTheHole()); | 1669 ASSERT(!value->IsTheHole()); |
| 1637 Handle<Object> value_handle(value); | 1670 Handle<Object> value_handle(value, isolate); |
| 1638 | 1671 |
| 1639 // To accommodate both the old and the new api we switch on the | 1672 // To accommodate both the old and the new api we switch on the |
| 1640 // data structure used to store the callbacks. Eventually proxy | 1673 // data structure used to store the callbacks. Eventually proxy |
| 1641 // callbacks should be phased out. | 1674 // callbacks should be phased out. |
| 1642 if (structure->IsProxy()) { | 1675 if (structure->IsProxy()) { |
| 1643 AccessorDescriptor* callback = | 1676 AccessorDescriptor* callback = |
| 1644 reinterpret_cast<AccessorDescriptor*>(Proxy::cast(structure)->proxy()); | 1677 reinterpret_cast<AccessorDescriptor*>(Proxy::cast(structure)->proxy()); |
| 1645 MaybeObject* obj = (callback->setter)(this, value, callback->data); | 1678 MaybeObject* obj = (callback->setter)(this, value, callback->data); |
| 1646 RETURN_IF_SCHEDULED_EXCEPTION(); | 1679 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 1647 if (obj->IsFailure()) return obj; | 1680 if (obj->IsFailure()) return obj; |
| 1648 return *value_handle; | 1681 return *value_handle; |
| 1649 } | 1682 } |
| 1650 | 1683 |
| 1651 if (structure->IsAccessorInfo()) { | 1684 if (structure->IsAccessorInfo()) { |
| 1652 // api style callbacks | 1685 // api style callbacks |
| 1653 AccessorInfo* data = AccessorInfo::cast(structure); | 1686 AccessorInfo* data = AccessorInfo::cast(structure); |
| 1654 Object* call_obj = data->setter(); | 1687 Object* call_obj = data->setter(); |
| 1655 v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj); | 1688 v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj); |
| 1656 if (call_fun == NULL) return value; | 1689 if (call_fun == NULL) return value; |
| 1657 Handle<String> key(name); | 1690 Handle<String> key(name); |
| 1658 LOG(ApiNamedPropertyAccess("store", this, name)); | 1691 LOG(isolate, ApiNamedPropertyAccess("store", this, name)); |
| 1659 CustomArguments args(data->data(), this, JSObject::cast(holder)); | 1692 CustomArguments args(isolate, data->data(), this, JSObject::cast(holder)); |
| 1660 v8::AccessorInfo info(args.end()); | 1693 v8::AccessorInfo info(args.end()); |
| 1661 { | 1694 { |
| 1662 // Leaving JavaScript. | 1695 // Leaving JavaScript. |
| 1663 VMState state(EXTERNAL); | 1696 VMState state(isolate, EXTERNAL); |
| 1664 call_fun(v8::Utils::ToLocal(key), | 1697 call_fun(v8::Utils::ToLocal(key), |
| 1665 v8::Utils::ToLocal(value_handle), | 1698 v8::Utils::ToLocal(value_handle), |
| 1666 info); | 1699 info); |
| 1667 } | 1700 } |
| 1668 RETURN_IF_SCHEDULED_EXCEPTION(); | 1701 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 1669 return *value_handle; | 1702 return *value_handle; |
| 1670 } | 1703 } |
| 1671 | 1704 |
| 1672 if (structure->IsFixedArray()) { | 1705 if (structure->IsFixedArray()) { |
| 1673 Object* setter = FixedArray::cast(structure)->get(kSetterIndex); | 1706 Object* setter = FixedArray::cast(structure)->get(kSetterIndex); |
| 1674 if (setter->IsJSFunction()) { | 1707 if (setter->IsJSFunction()) { |
| 1675 return SetPropertyWithDefinedSetter(JSFunction::cast(setter), value); | 1708 return SetPropertyWithDefinedSetter(JSFunction::cast(setter), value); |
| 1676 } else { | 1709 } else { |
| 1677 Handle<String> key(name); | 1710 Handle<String> key(name); |
| 1678 Handle<Object> holder_handle(holder); | 1711 Handle<Object> holder_handle(holder, isolate); |
| 1679 Handle<Object> args[2] = { key, holder_handle }; | 1712 Handle<Object> args[2] = { key, holder_handle }; |
| 1680 return Top::Throw(*Factory::NewTypeError("no_setter_in_callback", | 1713 return isolate->Throw( |
| 1681 HandleVector(args, 2))); | 1714 *isolate->factory()->NewTypeError("no_setter_in_callback", |
| 1715 HandleVector(args, 2))); |
| 1682 } | 1716 } |
| 1683 } | 1717 } |
| 1684 | 1718 |
| 1685 UNREACHABLE(); | 1719 UNREACHABLE(); |
| 1686 return NULL; | 1720 return NULL; |
| 1687 } | 1721 } |
| 1688 | 1722 |
| 1689 | 1723 |
| 1690 MaybeObject* JSObject::SetPropertyWithDefinedSetter(JSFunction* setter, | 1724 MaybeObject* JSObject::SetPropertyWithDefinedSetter(JSFunction* setter, |
| 1691 Object* value) { | 1725 Object* value) { |
| 1692 Handle<Object> value_handle(value); | 1726 Isolate* isolate = GetIsolate(); |
| 1693 Handle<JSFunction> fun(JSFunction::cast(setter)); | 1727 Handle<Object> value_handle(value, isolate); |
| 1694 Handle<JSObject> self(this); | 1728 Handle<JSFunction> fun(JSFunction::cast(setter), isolate); |
| 1729 Handle<JSObject> self(this, isolate); |
| 1695 #ifdef ENABLE_DEBUGGER_SUPPORT | 1730 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 1731 Debug* debug = isolate->debug(); |
| 1696 // Handle stepping into a setter if step into is active. | 1732 // Handle stepping into a setter if step into is active. |
| 1697 if (Debug::StepInActive()) { | 1733 if (debug->StepInActive()) { |
| 1698 Debug::HandleStepIn(fun, Handle<Object>::null(), 0, false); | 1734 debug->HandleStepIn(fun, Handle<Object>::null(), 0, false); |
| 1699 } | 1735 } |
| 1700 #endif | 1736 #endif |
| 1701 bool has_pending_exception; | 1737 bool has_pending_exception; |
| 1702 Object** argv[] = { value_handle.location() }; | 1738 Object** argv[] = { value_handle.location() }; |
| 1703 Execution::Call(fun, self, 1, argv, &has_pending_exception); | 1739 Execution::Call(fun, self, 1, argv, &has_pending_exception); |
| 1704 // Check for pending exception and return the result. | 1740 // Check for pending exception and return the result. |
| 1705 if (has_pending_exception) return Failure::Exception(); | 1741 if (has_pending_exception) return Failure::Exception(); |
| 1706 return *value_handle; | 1742 return *value_handle; |
| 1707 } | 1743 } |
| 1708 | 1744 |
| 1709 | 1745 |
| 1710 void JSObject::LookupCallbackSetterInPrototypes(String* name, | 1746 void JSObject::LookupCallbackSetterInPrototypes(String* name, |
| 1711 LookupResult* result) { | 1747 LookupResult* result) { |
| 1748 Heap* heap = GetHeap(); |
| 1712 for (Object* pt = GetPrototype(); | 1749 for (Object* pt = GetPrototype(); |
| 1713 pt != Heap::null_value(); | 1750 pt != heap->null_value(); |
| 1714 pt = pt->GetPrototype()) { | 1751 pt = pt->GetPrototype()) { |
| 1715 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result); | 1752 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result); |
| 1716 if (result->IsProperty()) { | 1753 if (result->IsProperty()) { |
| 1717 if (result->IsReadOnly()) { | 1754 if (result->IsReadOnly()) { |
| 1718 result->NotFound(); | 1755 result->NotFound(); |
| 1719 return; | 1756 return; |
| 1720 } | 1757 } |
| 1721 if (result->type() == CALLBACKS) { | 1758 if (result->type() == CALLBACKS) { |
| 1722 return; | 1759 return; |
| 1723 } | 1760 } |
| 1724 } | 1761 } |
| 1725 } | 1762 } |
| 1726 result->NotFound(); | 1763 result->NotFound(); |
| 1727 } | 1764 } |
| 1728 | 1765 |
| 1729 | 1766 |
| 1730 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(uint32_t index, | 1767 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(uint32_t index, |
| 1731 Object* value, | 1768 Object* value, |
| 1732 bool* found) { | 1769 bool* found) { |
| 1770 Heap* heap = GetHeap(); |
| 1733 for (Object* pt = GetPrototype(); | 1771 for (Object* pt = GetPrototype(); |
| 1734 pt != Heap::null_value(); | 1772 pt != heap->null_value(); |
| 1735 pt = pt->GetPrototype()) { | 1773 pt = pt->GetPrototype()) { |
| 1736 if (!JSObject::cast(pt)->HasDictionaryElements()) { | 1774 if (!JSObject::cast(pt)->HasDictionaryElements()) { |
| 1737 continue; | 1775 continue; |
| 1738 } | 1776 } |
| 1739 NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary(); | 1777 NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary(); |
| 1740 int entry = dictionary->FindEntry(index); | 1778 int entry = dictionary->FindEntry(index); |
| 1741 if (entry != NumberDictionary::kNotFound) { | 1779 if (entry != NumberDictionary::kNotFound) { |
| 1742 PropertyDetails details = dictionary->DetailsAt(entry); | 1780 PropertyDetails details = dictionary->DetailsAt(entry); |
| 1743 if (details.type() == CALLBACKS) { | 1781 if (details.type() == CALLBACKS) { |
| 1744 *found = true; | 1782 *found = true; |
| 1745 return SetElementWithCallback( | 1783 return SetElementWithCallback( |
| 1746 dictionary->ValueAt(entry), index, value, JSObject::cast(pt)); | 1784 dictionary->ValueAt(entry), index, value, JSObject::cast(pt)); |
| 1747 } | 1785 } |
| 1748 } | 1786 } |
| 1749 } | 1787 } |
| 1750 *found = false; | 1788 *found = false; |
| 1751 return Heap::the_hole_value(); | 1789 return heap->the_hole_value(); |
| 1752 } | 1790 } |
| 1753 | 1791 |
| 1754 | 1792 |
| 1755 void JSObject::LookupInDescriptor(String* name, LookupResult* result) { | 1793 void JSObject::LookupInDescriptor(String* name, LookupResult* result) { |
| 1756 DescriptorArray* descriptors = map()->instance_descriptors(); | 1794 DescriptorArray* descriptors = map()->instance_descriptors(); |
| 1757 int number = descriptors->SearchWithCache(name); | 1795 int number = descriptors->SearchWithCache(name); |
| 1758 if (number != DescriptorArray::kNotFound) { | 1796 if (number != DescriptorArray::kNotFound) { |
| 1759 result->DescriptorResult(this, descriptors->GetDetails(number), number); | 1797 result->DescriptorResult(this, descriptors->GetDetails(number), number); |
| 1760 } else { | 1798 } else { |
| 1761 result->NotFound(); | 1799 result->NotFound(); |
| 1762 } | 1800 } |
| 1763 } | 1801 } |
| 1764 | 1802 |
| 1765 | 1803 |
| 1766 void Map::LookupInDescriptors(JSObject* holder, | 1804 void Map::LookupInDescriptors(JSObject* holder, |
| 1767 String* name, | 1805 String* name, |
| 1768 LookupResult* result) { | 1806 LookupResult* result) { |
| 1769 DescriptorArray* descriptors = instance_descriptors(); | 1807 DescriptorArray* descriptors = instance_descriptors(); |
| 1770 int number = DescriptorLookupCache::Lookup(descriptors, name); | 1808 DescriptorLookupCache* cache = heap()->isolate()->descriptor_lookup_cache(); |
| 1809 int number = cache->Lookup(descriptors, name); |
| 1771 if (number == DescriptorLookupCache::kAbsent) { | 1810 if (number == DescriptorLookupCache::kAbsent) { |
| 1772 number = descriptors->Search(name); | 1811 number = descriptors->Search(name); |
| 1773 DescriptorLookupCache::Update(descriptors, name, number); | 1812 cache->Update(descriptors, name, number); |
| 1774 } | 1813 } |
| 1775 if (number != DescriptorArray::kNotFound) { | 1814 if (number != DescriptorArray::kNotFound) { |
| 1776 result->DescriptorResult(holder, descriptors->GetDetails(number), number); | 1815 result->DescriptorResult(holder, descriptors->GetDetails(number), number); |
| 1777 } else { | 1816 } else { |
| 1778 result->NotFound(); | 1817 result->NotFound(); |
| 1779 } | 1818 } |
| 1780 } | 1819 } |
| 1781 | 1820 |
| 1782 | 1821 |
| 1783 void JSObject::LocalLookupRealNamedProperty(String* name, | 1822 void JSObject::LocalLookupRealNamedProperty(String* name, |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1831 void JSObject::LookupRealNamedProperty(String* name, LookupResult* result) { | 1870 void JSObject::LookupRealNamedProperty(String* name, LookupResult* result) { |
| 1832 LocalLookupRealNamedProperty(name, result); | 1871 LocalLookupRealNamedProperty(name, result); |
| 1833 if (result->IsProperty()) return; | 1872 if (result->IsProperty()) return; |
| 1834 | 1873 |
| 1835 LookupRealNamedPropertyInPrototypes(name, result); | 1874 LookupRealNamedPropertyInPrototypes(name, result); |
| 1836 } | 1875 } |
| 1837 | 1876 |
| 1838 | 1877 |
| 1839 void JSObject::LookupRealNamedPropertyInPrototypes(String* name, | 1878 void JSObject::LookupRealNamedPropertyInPrototypes(String* name, |
| 1840 LookupResult* result) { | 1879 LookupResult* result) { |
| 1880 Heap* heap = GetHeap(); |
| 1841 for (Object* pt = GetPrototype(); | 1881 for (Object* pt = GetPrototype(); |
| 1842 pt != Heap::null_value(); | 1882 pt != heap->null_value(); |
| 1843 pt = JSObject::cast(pt)->GetPrototype()) { | 1883 pt = JSObject::cast(pt)->GetPrototype()) { |
| 1844 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result); | 1884 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result); |
| 1845 if (result->IsProperty() && (result->type() != INTERCEPTOR)) return; | 1885 if (result->IsProperty() && (result->type() != INTERCEPTOR)) return; |
| 1846 } | 1886 } |
| 1847 result->NotFound(); | 1887 result->NotFound(); |
| 1848 } | 1888 } |
| 1849 | 1889 |
| 1850 | 1890 |
| 1851 // We only need to deal with CALLBACKS and INTERCEPTORS | 1891 // We only need to deal with CALLBACKS and INTERCEPTORS |
| 1852 MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(LookupResult* result, | 1892 MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(LookupResult* result, |
| 1853 String* name, | 1893 String* name, |
| 1854 Object* value, | 1894 Object* value, |
| 1855 bool check_prototype) { | 1895 bool check_prototype) { |
| 1896 Heap* heap = GetHeap(); |
| 1856 if (check_prototype && !result->IsProperty()) { | 1897 if (check_prototype && !result->IsProperty()) { |
| 1857 LookupCallbackSetterInPrototypes(name, result); | 1898 LookupCallbackSetterInPrototypes(name, result); |
| 1858 } | 1899 } |
| 1859 | 1900 |
| 1860 if (result->IsProperty()) { | 1901 if (result->IsProperty()) { |
| 1861 if (!result->IsReadOnly()) { | 1902 if (!result->IsReadOnly()) { |
| 1862 switch (result->type()) { | 1903 switch (result->type()) { |
| 1863 case CALLBACKS: { | 1904 case CALLBACKS: { |
| 1864 Object* obj = result->GetCallbackObject(); | 1905 Object* obj = result->GetCallbackObject(); |
| 1865 if (obj->IsAccessorInfo()) { | 1906 if (obj->IsAccessorInfo()) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1886 } | 1927 } |
| 1887 default: { | 1928 default: { |
| 1888 break; | 1929 break; |
| 1889 } | 1930 } |
| 1890 } | 1931 } |
| 1891 } | 1932 } |
| 1892 } | 1933 } |
| 1893 | 1934 |
| 1894 HandleScope scope; | 1935 HandleScope scope; |
| 1895 Handle<Object> value_handle(value); | 1936 Handle<Object> value_handle(value); |
| 1896 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); | 1937 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET); |
| 1897 return *value_handle; | 1938 return *value_handle; |
| 1898 } | 1939 } |
| 1899 | 1940 |
| 1900 | 1941 |
| 1901 MaybeObject* JSObject::SetProperty(LookupResult* result, | 1942 MaybeObject* JSObject::SetProperty(LookupResult* result, |
| 1902 String* name, | 1943 String* name, |
| 1903 Object* value, | 1944 Object* value, |
| 1904 PropertyAttributes attributes, | 1945 PropertyAttributes attributes, |
| 1905 StrictModeFlag strict_mode) { | 1946 StrictModeFlag strict_mode) { |
| 1947 Heap* heap = GetHeap(); |
| 1906 // Make sure that the top context does not change when doing callbacks or | 1948 // Make sure that the top context does not change when doing callbacks or |
| 1907 // interceptor calls. | 1949 // interceptor calls. |
| 1908 AssertNoContextChange ncc; | 1950 AssertNoContextChange ncc; |
| 1909 | 1951 |
| 1910 // Optimization for 2-byte strings often used as keys in a decompression | 1952 // Optimization for 2-byte strings often used as keys in a decompression |
| 1911 // dictionary. We make these short keys into symbols to avoid constantly | 1953 // dictionary. We make these short keys into symbols to avoid constantly |
| 1912 // reallocating them. | 1954 // reallocating them. |
| 1913 if (!name->IsSymbol() && name->length() <= 2) { | 1955 if (!name->IsSymbol() && name->length() <= 2) { |
| 1914 Object* symbol_version; | 1956 Object* symbol_version; |
| 1915 { MaybeObject* maybe_symbol_version = Heap::LookupSymbol(name); | 1957 { MaybeObject* maybe_symbol_version = heap->LookupSymbol(name); |
| 1916 if (maybe_symbol_version->ToObject(&symbol_version)) { | 1958 if (maybe_symbol_version->ToObject(&symbol_version)) { |
| 1917 name = String::cast(symbol_version); | 1959 name = String::cast(symbol_version); |
| 1918 } | 1960 } |
| 1919 } | 1961 } |
| 1920 } | 1962 } |
| 1921 | 1963 |
| 1922 // Check access rights if needed. | 1964 // Check access rights if needed. |
| 1923 if (IsAccessCheckNeeded() | 1965 if (IsAccessCheckNeeded() |
| 1924 && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { | 1966 && !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_SET)) { |
| 1925 return SetPropertyWithFailedAccessCheck(result, name, value, true); | 1967 return SetPropertyWithFailedAccessCheck(result, name, value, true); |
| 1926 } | 1968 } |
| 1927 | 1969 |
| 1928 if (IsJSGlobalProxy()) { | 1970 if (IsJSGlobalProxy()) { |
| 1929 Object* proto = GetPrototype(); | 1971 Object* proto = GetPrototype(); |
| 1930 if (proto->IsNull()) return value; | 1972 if (proto->IsNull()) return value; |
| 1931 ASSERT(proto->IsJSGlobalObject()); | 1973 ASSERT(proto->IsJSGlobalObject()); |
| 1932 return JSObject::cast(proto)->SetProperty( | 1974 return JSObject::cast(proto)->SetProperty( |
| 1933 result, name, value, attributes, strict_mode); | 1975 result, name, value, attributes, strict_mode); |
| 1934 } | 1976 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1948 if (!result->IsFound()) { | 1990 if (!result->IsFound()) { |
| 1949 // Neither properties nor transitions found. | 1991 // Neither properties nor transitions found. |
| 1950 return AddProperty(name, value, attributes); | 1992 return AddProperty(name, value, attributes); |
| 1951 } | 1993 } |
| 1952 if (result->IsReadOnly() && result->IsProperty()) { | 1994 if (result->IsReadOnly() && result->IsProperty()) { |
| 1953 if (strict_mode == kStrictMode) { | 1995 if (strict_mode == kStrictMode) { |
| 1954 HandleScope scope; | 1996 HandleScope scope; |
| 1955 Handle<String> key(name); | 1997 Handle<String> key(name); |
| 1956 Handle<Object> holder(this); | 1998 Handle<Object> holder(this); |
| 1957 Handle<Object> args[2] = { key, holder }; | 1999 Handle<Object> args[2] = { key, holder }; |
| 1958 return Top::Throw(*Factory::NewTypeError("strict_read_only_property", | 2000 return heap->isolate()->Throw(*heap->isolate()->factory()->NewTypeError( |
| 1959 HandleVector(args, 2))); | 2001 "strict_read_only_property", HandleVector(args, 2))); |
| 1960 } else { | 2002 } else { |
| 1961 return value; | 2003 return value; |
| 1962 } | 2004 } |
| 1963 } | 2005 } |
| 1964 // This is a real property that is not read-only, or it is a | 2006 // This is a real property that is not read-only, or it is a |
| 1965 // transition or null descriptor and there are no setters in the prototypes. | 2007 // transition or null descriptor and there are no setters in the prototypes. |
| 1966 switch (result->type()) { | 2008 switch (result->type()) { |
| 1967 case NORMAL: | 2009 case NORMAL: |
| 1968 return SetNormalizedProperty(result, value); | 2010 return SetNormalizedProperty(result, value); |
| 1969 case FIELD: | 2011 case FIELD: |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1992 case CONSTANT_TRANSITION: { | 2034 case CONSTANT_TRANSITION: { |
| 1993 // If the same constant function is being added we can simply | 2035 // If the same constant function is being added we can simply |
| 1994 // transition to the target map. | 2036 // transition to the target map. |
| 1995 Map* target_map = result->GetTransitionMap(); | 2037 Map* target_map = result->GetTransitionMap(); |
| 1996 DescriptorArray* target_descriptors = target_map->instance_descriptors(); | 2038 DescriptorArray* target_descriptors = target_map->instance_descriptors(); |
| 1997 int number = target_descriptors->SearchWithCache(name); | 2039 int number = target_descriptors->SearchWithCache(name); |
| 1998 ASSERT(number != DescriptorArray::kNotFound); | 2040 ASSERT(number != DescriptorArray::kNotFound); |
| 1999 ASSERT(target_descriptors->GetType(number) == CONSTANT_FUNCTION); | 2041 ASSERT(target_descriptors->GetType(number) == CONSTANT_FUNCTION); |
| 2000 JSFunction* function = | 2042 JSFunction* function = |
| 2001 JSFunction::cast(target_descriptors->GetValue(number)); | 2043 JSFunction::cast(target_descriptors->GetValue(number)); |
| 2002 ASSERT(!Heap::InNewSpace(function)); | 2044 ASSERT(!HEAP->InNewSpace(function)); |
| 2003 if (value == function) { | 2045 if (value == function) { |
| 2004 set_map(target_map); | 2046 set_map(target_map); |
| 2005 return value; | 2047 return value; |
| 2006 } | 2048 } |
| 2007 // Otherwise, replace with a MAP_TRANSITION to a new map with a | 2049 // Otherwise, replace with a MAP_TRANSITION to a new map with a |
| 2008 // FIELD, even if the value is a constant function. | 2050 // FIELD, even if the value is a constant function. |
| 2009 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); | 2051 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); |
| 2010 } | 2052 } |
| 2011 case NULL_DESCRIPTOR: | 2053 case NULL_DESCRIPTOR: |
| 2012 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); | 2054 return ConvertDescriptorToFieldAndMapTransition(name, value, attributes); |
| 2013 default: | 2055 default: |
| 2014 UNREACHABLE(); | 2056 UNREACHABLE(); |
| 2015 } | 2057 } |
| 2016 UNREACHABLE(); | 2058 UNREACHABLE(); |
| 2017 return value; | 2059 return value; |
| 2018 } | 2060 } |
| 2019 | 2061 |
| 2020 | 2062 |
| 2021 // Set a real local property, even if it is READ_ONLY. If the property is not | 2063 // Set a real local property, even if it is READ_ONLY. If the property is not |
| 2022 // present, add it with attributes NONE. This code is an exact clone of | 2064 // present, add it with attributes NONE. This code is an exact clone of |
| 2023 // SetProperty, with the check for IsReadOnly and the check for a | 2065 // SetProperty, with the check for IsReadOnly and the check for a |
| 2024 // callback setter removed. The two lines looking up the LookupResult | 2066 // callback setter removed. The two lines looking up the LookupResult |
| 2025 // result are also added. If one of the functions is changed, the other | 2067 // result are also added. If one of the functions is changed, the other |
| 2026 // should be. | 2068 // should be. |
| 2027 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( | 2069 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( |
| 2028 String* name, | 2070 String* name, |
| 2029 Object* value, | 2071 Object* value, |
| 2030 PropertyAttributes attributes) { | 2072 PropertyAttributes attributes) { |
| 2073 Heap* heap = GetHeap(); |
| 2074 |
| 2031 // Make sure that the top context does not change when doing callbacks or | 2075 // Make sure that the top context does not change when doing callbacks or |
| 2032 // interceptor calls. | 2076 // interceptor calls. |
| 2033 AssertNoContextChange ncc; | 2077 AssertNoContextChange ncc; |
| 2034 LookupResult result; | 2078 LookupResult result; |
| 2035 LocalLookup(name, &result); | 2079 LocalLookup(name, &result); |
| 2036 // Check access rights if needed. | 2080 // Check access rights if needed. |
| 2037 if (IsAccessCheckNeeded() | 2081 if (IsAccessCheckNeeded() |
| 2038 && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { | 2082 && !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_SET)) { |
| 2039 return SetPropertyWithFailedAccessCheck(&result, name, value, false); | 2083 return SetPropertyWithFailedAccessCheck(&result, name, value, false); |
| 2040 } | 2084 } |
| 2041 | 2085 |
| 2042 if (IsJSGlobalProxy()) { | 2086 if (IsJSGlobalProxy()) { |
| 2043 Object* proto = GetPrototype(); | 2087 Object* proto = GetPrototype(); |
| 2044 if (proto->IsNull()) return value; | 2088 if (proto->IsNull()) return value; |
| 2045 ASSERT(proto->IsJSGlobalObject()); | 2089 ASSERT(proto->IsJSGlobalObject()); |
| 2046 return JSObject::cast(proto)->SetLocalPropertyIgnoreAttributes( | 2090 return JSObject::cast(proto)->SetLocalPropertyIgnoreAttributes( |
| 2047 name, | 2091 name, |
| 2048 value, | 2092 value, |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2100 String* name, | 2144 String* name, |
| 2101 bool continue_search) { | 2145 bool continue_search) { |
| 2102 // Check local property, ignore interceptor. | 2146 // Check local property, ignore interceptor. |
| 2103 LookupResult result; | 2147 LookupResult result; |
| 2104 LocalLookupRealNamedProperty(name, &result); | 2148 LocalLookupRealNamedProperty(name, &result); |
| 2105 if (result.IsProperty()) return result.GetAttributes(); | 2149 if (result.IsProperty()) return result.GetAttributes(); |
| 2106 | 2150 |
| 2107 if (continue_search) { | 2151 if (continue_search) { |
| 2108 // Continue searching via the prototype chain. | 2152 // Continue searching via the prototype chain. |
| 2109 Object* pt = GetPrototype(); | 2153 Object* pt = GetPrototype(); |
| 2110 if (pt != Heap::null_value()) { | 2154 if (!pt->IsNull()) { |
| 2111 return JSObject::cast(pt)-> | 2155 return JSObject::cast(pt)-> |
| 2112 GetPropertyAttributeWithReceiver(receiver, name); | 2156 GetPropertyAttributeWithReceiver(receiver, name); |
| 2113 } | 2157 } |
| 2114 } | 2158 } |
| 2115 return ABSENT; | 2159 return ABSENT; |
| 2116 } | 2160 } |
| 2117 | 2161 |
| 2118 | 2162 |
| 2119 PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor( | 2163 PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor( |
| 2120 JSObject* receiver, | 2164 JSObject* receiver, |
| 2121 String* name, | 2165 String* name, |
| 2122 bool continue_search) { | 2166 bool continue_search) { |
| 2167 Isolate* isolate = GetIsolate(); |
| 2168 |
| 2123 // Make sure that the top context does not change when doing | 2169 // Make sure that the top context does not change when doing |
| 2124 // callbacks or interceptor calls. | 2170 // callbacks or interceptor calls. |
| 2125 AssertNoContextChange ncc; | 2171 AssertNoContextChange ncc; |
| 2126 | 2172 |
| 2127 HandleScope scope; | 2173 HandleScope scope(isolate); |
| 2128 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); | 2174 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); |
| 2129 Handle<JSObject> receiver_handle(receiver); | 2175 Handle<JSObject> receiver_handle(receiver); |
| 2130 Handle<JSObject> holder_handle(this); | 2176 Handle<JSObject> holder_handle(this); |
| 2131 Handle<String> name_handle(name); | 2177 Handle<String> name_handle(name); |
| 2132 CustomArguments args(interceptor->data(), receiver, this); | 2178 CustomArguments args(isolate, interceptor->data(), receiver, this); |
| 2133 v8::AccessorInfo info(args.end()); | 2179 v8::AccessorInfo info(args.end()); |
| 2134 if (!interceptor->query()->IsUndefined()) { | 2180 if (!interceptor->query()->IsUndefined()) { |
| 2135 v8::NamedPropertyQuery query = | 2181 v8::NamedPropertyQuery query = |
| 2136 v8::ToCData<v8::NamedPropertyQuery>(interceptor->query()); | 2182 v8::ToCData<v8::NamedPropertyQuery>(interceptor->query()); |
| 2137 LOG(ApiNamedPropertyAccess("interceptor-named-has", *holder_handle, name)); | 2183 LOG(isolate, |
| 2184 ApiNamedPropertyAccess("interceptor-named-has", *holder_handle, name)); |
| 2138 v8::Handle<v8::Integer> result; | 2185 v8::Handle<v8::Integer> result; |
| 2139 { | 2186 { |
| 2140 // Leaving JavaScript. | 2187 // Leaving JavaScript. |
| 2141 VMState state(EXTERNAL); | 2188 VMState state(isolate, EXTERNAL); |
| 2142 result = query(v8::Utils::ToLocal(name_handle), info); | 2189 result = query(v8::Utils::ToLocal(name_handle), info); |
| 2143 } | 2190 } |
| 2144 if (!result.IsEmpty()) { | 2191 if (!result.IsEmpty()) { |
| 2145 ASSERT(result->IsInt32()); | 2192 ASSERT(result->IsInt32()); |
| 2146 return static_cast<PropertyAttributes>(result->Int32Value()); | 2193 return static_cast<PropertyAttributes>(result->Int32Value()); |
| 2147 } | 2194 } |
| 2148 } else if (!interceptor->getter()->IsUndefined()) { | 2195 } else if (!interceptor->getter()->IsUndefined()) { |
| 2149 v8::NamedPropertyGetter getter = | 2196 v8::NamedPropertyGetter getter = |
| 2150 v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter()); | 2197 v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter()); |
| 2151 LOG(ApiNamedPropertyAccess("interceptor-named-get-has", this, name)); | 2198 LOG(isolate, |
| 2199 ApiNamedPropertyAccess("interceptor-named-get-has", this, name)); |
| 2152 v8::Handle<v8::Value> result; | 2200 v8::Handle<v8::Value> result; |
| 2153 { | 2201 { |
| 2154 // Leaving JavaScript. | 2202 // Leaving JavaScript. |
| 2155 VMState state(EXTERNAL); | 2203 VMState state(isolate, EXTERNAL); |
| 2156 result = getter(v8::Utils::ToLocal(name_handle), info); | 2204 result = getter(v8::Utils::ToLocal(name_handle), info); |
| 2157 } | 2205 } |
| 2158 if (!result.IsEmpty()) return DONT_ENUM; | 2206 if (!result.IsEmpty()) return DONT_ENUM; |
| 2159 } | 2207 } |
| 2160 return holder_handle->GetPropertyAttributePostInterceptor(*receiver_handle, | 2208 return holder_handle->GetPropertyAttributePostInterceptor(*receiver_handle, |
| 2161 *name_handle, | 2209 *name_handle, |
| 2162 continue_search); | 2210 continue_search); |
| 2163 } | 2211 } |
| 2164 | 2212 |
| 2165 | 2213 |
| 2166 PropertyAttributes JSObject::GetPropertyAttributeWithReceiver( | 2214 PropertyAttributes JSObject::GetPropertyAttributeWithReceiver( |
| 2167 JSObject* receiver, | 2215 JSObject* receiver, |
| 2168 String* key) { | 2216 String* key) { |
| 2169 uint32_t index = 0; | 2217 uint32_t index = 0; |
| 2170 if (key->AsArrayIndex(&index)) { | 2218 if (key->AsArrayIndex(&index)) { |
| 2171 if (HasElementWithReceiver(receiver, index)) return NONE; | 2219 if (HasElementWithReceiver(receiver, index)) return NONE; |
| 2172 return ABSENT; | 2220 return ABSENT; |
| 2173 } | 2221 } |
| 2174 // Named property. | 2222 // Named property. |
| 2175 LookupResult result; | 2223 LookupResult result; |
| 2176 Lookup(key, &result); | 2224 Lookup(key, &result); |
| 2177 return GetPropertyAttribute(receiver, &result, key, true); | 2225 return GetPropertyAttribute(receiver, &result, key, true); |
| 2178 } | 2226 } |
| 2179 | 2227 |
| 2180 | 2228 |
| 2181 PropertyAttributes JSObject::GetPropertyAttribute(JSObject* receiver, | 2229 PropertyAttributes JSObject::GetPropertyAttribute(JSObject* receiver, |
| 2182 LookupResult* result, | 2230 LookupResult* result, |
| 2183 String* name, | 2231 String* name, |
| 2184 bool continue_search) { | 2232 bool continue_search) { |
| 2233 Heap* heap = GetHeap(); |
| 2185 // Check access rights if needed. | 2234 // Check access rights if needed. |
| 2186 if (IsAccessCheckNeeded() && | 2235 if (IsAccessCheckNeeded() && |
| 2187 !Top::MayNamedAccess(this, name, v8::ACCESS_HAS)) { | 2236 !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_HAS)) { |
| 2188 return GetPropertyAttributeWithFailedAccessCheck(receiver, | 2237 return GetPropertyAttributeWithFailedAccessCheck(receiver, |
| 2189 result, | 2238 result, |
| 2190 name, | 2239 name, |
| 2191 continue_search); | 2240 continue_search); |
| 2192 } | 2241 } |
| 2193 if (result->IsProperty()) { | 2242 if (result->IsProperty()) { |
| 2194 switch (result->type()) { | 2243 switch (result->type()) { |
| 2195 case NORMAL: // fall through | 2244 case NORMAL: // fall through |
| 2196 case FIELD: | 2245 case FIELD: |
| 2197 case CONSTANT_FUNCTION: | 2246 case CONSTANT_FUNCTION: |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2243 } | 2292 } |
| 2244 #endif | 2293 #endif |
| 2245 return result; | 2294 return result; |
| 2246 } | 2295 } |
| 2247 | 2296 |
| 2248 { MaybeObject* maybe_result = | 2297 { MaybeObject* maybe_result = |
| 2249 fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP); | 2298 fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP); |
| 2250 if (!maybe_result->ToObject(&result)) return maybe_result; | 2299 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2251 } | 2300 } |
| 2252 set(index, result); | 2301 set(index, result); |
| 2253 Counters::normalized_maps.Increment(); | 2302 COUNTERS->normalized_maps()->Increment(); |
| 2254 | 2303 |
| 2255 return result; | 2304 return result; |
| 2256 } | 2305 } |
| 2257 | 2306 |
| 2258 | 2307 |
| 2259 void NormalizedMapCache::Clear() { | 2308 void NormalizedMapCache::Clear() { |
| 2260 int entries = length(); | 2309 int entries = length(); |
| 2261 for (int i = 0; i != entries; i++) { | 2310 for (int i = 0; i != entries; i++) { |
| 2262 set_undefined(i); | 2311 set_undefined(i); |
| 2263 } | 2312 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2303 MaybeObject* JSObject::UpdateMapCodeCache(String* name, Code* code) { | 2352 MaybeObject* JSObject::UpdateMapCodeCache(String* name, Code* code) { |
| 2304 if (map()->is_shared()) { | 2353 if (map()->is_shared()) { |
| 2305 // Fast case maps are never marked as shared. | 2354 // Fast case maps are never marked as shared. |
| 2306 ASSERT(!HasFastProperties()); | 2355 ASSERT(!HasFastProperties()); |
| 2307 // Replace the map with an identical copy that can be safely modified. | 2356 // Replace the map with an identical copy that can be safely modified. |
| 2308 Object* obj; | 2357 Object* obj; |
| 2309 { MaybeObject* maybe_obj = map()->CopyNormalized(KEEP_INOBJECT_PROPERTIES, | 2358 { MaybeObject* maybe_obj = map()->CopyNormalized(KEEP_INOBJECT_PROPERTIES, |
| 2310 UNIQUE_NORMALIZED_MAP); | 2359 UNIQUE_NORMALIZED_MAP); |
| 2311 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 2360 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 2312 } | 2361 } |
| 2313 Counters::normalized_maps.Increment(); | 2362 COUNTERS->normalized_maps()->Increment(); |
| 2314 | 2363 |
| 2315 set_map(Map::cast(obj)); | 2364 set_map(Map::cast(obj)); |
| 2316 } | 2365 } |
| 2317 return map()->UpdateCodeCache(name, code); | 2366 return map()->UpdateCodeCache(name, code); |
| 2318 } | 2367 } |
| 2319 | 2368 |
| 2320 | 2369 |
| 2321 MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode, | 2370 MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode, |
| 2322 int expected_additional_properties) { | 2371 int expected_additional_properties) { |
| 2323 if (!HasFastProperties()) return this; | 2372 if (!HasFastProperties()) return this; |
| 2324 | 2373 |
| 2325 // The global object is always normalized. | 2374 // The global object is always normalized. |
| 2326 ASSERT(!IsGlobalObject()); | 2375 ASSERT(!IsGlobalObject()); |
| 2327 | |
| 2328 // JSGlobalProxy must never be normalized | 2376 // JSGlobalProxy must never be normalized |
| 2329 ASSERT(!IsJSGlobalProxy()); | 2377 ASSERT(!IsJSGlobalProxy()); |
| 2330 | 2378 |
| 2379 Heap* heap = GetHeap(); |
| 2380 |
| 2331 // Allocate new content. | 2381 // Allocate new content. |
| 2332 int property_count = map()->NumberOfDescribedProperties(); | 2382 int property_count = map()->NumberOfDescribedProperties(); |
| 2333 if (expected_additional_properties > 0) { | 2383 if (expected_additional_properties > 0) { |
| 2334 property_count += expected_additional_properties; | 2384 property_count += expected_additional_properties; |
| 2335 } else { | 2385 } else { |
| 2336 property_count += 2; // Make space for two more properties. | 2386 property_count += 2; // Make space for two more properties. |
| 2337 } | 2387 } |
| 2338 Object* obj; | 2388 Object* obj; |
| 2339 { MaybeObject* maybe_obj = | 2389 { MaybeObject* maybe_obj = |
| 2340 StringDictionary::Allocate(property_count); | 2390 StringDictionary::Allocate(property_count); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2389 break; | 2439 break; |
| 2390 default: | 2440 default: |
| 2391 UNREACHABLE(); | 2441 UNREACHABLE(); |
| 2392 } | 2442 } |
| 2393 } | 2443 } |
| 2394 | 2444 |
| 2395 // Copy the next enumeration index from instance descriptor. | 2445 // Copy the next enumeration index from instance descriptor. |
| 2396 int index = map()->instance_descriptors()->NextEnumerationIndex(); | 2446 int index = map()->instance_descriptors()->NextEnumerationIndex(); |
| 2397 dictionary->SetNextEnumerationIndex(index); | 2447 dictionary->SetNextEnumerationIndex(index); |
| 2398 | 2448 |
| 2399 { MaybeObject* maybe_obj = Top::context()->global_context()-> | 2449 { MaybeObject* maybe_obj = heap->isolate()->context()->global_context()-> |
| 2400 normalized_map_cache()->Get(this, mode); | 2450 normalized_map_cache()->Get(this, mode); |
| 2401 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 2451 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 2402 } | 2452 } |
| 2403 Map* new_map = Map::cast(obj); | 2453 Map* new_map = Map::cast(obj); |
| 2404 | 2454 |
| 2405 // We have now successfully allocated all the necessary objects. | 2455 // We have now successfully allocated all the necessary objects. |
| 2406 // Changes can now be made with the guarantee that all of them take effect. | 2456 // Changes can now be made with the guarantee that all of them take effect. |
| 2407 | 2457 |
| 2408 // Resize the object in the heap if necessary. | 2458 // Resize the object in the heap if necessary. |
| 2409 int new_instance_size = new_map->instance_size(); | 2459 int new_instance_size = new_map->instance_size(); |
| 2410 int instance_size_delta = map()->instance_size() - new_instance_size; | 2460 int instance_size_delta = map()->instance_size() - new_instance_size; |
| 2411 ASSERT(instance_size_delta >= 0); | 2461 ASSERT(instance_size_delta >= 0); |
| 2412 Heap::CreateFillerObjectAt(this->address() + new_instance_size, | 2462 heap->CreateFillerObjectAt(this->address() + new_instance_size, |
| 2413 instance_size_delta); | 2463 instance_size_delta); |
| 2414 | 2464 |
| 2415 set_map(new_map); | 2465 set_map(new_map); |
| 2466 map()->set_instance_descriptors(heap->empty_descriptor_array()); |
| 2416 | 2467 |
| 2417 set_properties(dictionary); | 2468 set_properties(dictionary); |
| 2418 | 2469 |
| 2419 Counters::props_to_dictionary.Increment(); | 2470 heap->isolate()->counters()->props_to_dictionary()->Increment(); |
| 2420 | 2471 |
| 2421 #ifdef DEBUG | 2472 #ifdef DEBUG |
| 2422 if (FLAG_trace_normalization) { | 2473 if (FLAG_trace_normalization) { |
| 2423 PrintF("Object properties have been normalized:\n"); | 2474 PrintF("Object properties have been normalized:\n"); |
| 2424 Print(); | 2475 Print(); |
| 2425 } | 2476 } |
| 2426 #endif | 2477 #endif |
| 2427 return this; | 2478 return this; |
| 2428 } | 2479 } |
| 2429 | 2480 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2470 } | 2521 } |
| 2471 dictionary = NumberDictionary::cast(result); | 2522 dictionary = NumberDictionary::cast(result); |
| 2472 } | 2523 } |
| 2473 } | 2524 } |
| 2474 // Switch to using the dictionary as the backing storage for | 2525 // Switch to using the dictionary as the backing storage for |
| 2475 // elements. Set the new map first to satify the elements type | 2526 // elements. Set the new map first to satify the elements type |
| 2476 // assert in set_elements(). | 2527 // assert in set_elements(). |
| 2477 set_map(new_map); | 2528 set_map(new_map); |
| 2478 set_elements(dictionary); | 2529 set_elements(dictionary); |
| 2479 | 2530 |
| 2480 Counters::elements_to_dictionary.Increment(); | 2531 new_map->GetHeap()->isolate()->counters()->elements_to_dictionary()-> |
| 2532 Increment(); |
| 2481 | 2533 |
| 2482 #ifdef DEBUG | 2534 #ifdef DEBUG |
| 2483 if (FLAG_trace_normalization) { | 2535 if (FLAG_trace_normalization) { |
| 2484 PrintF("Object elements have been normalized:\n"); | 2536 PrintF("Object elements have been normalized:\n"); |
| 2485 Print(); | 2537 Print(); |
| 2486 } | 2538 } |
| 2487 #endif | 2539 #endif |
| 2488 | 2540 |
| 2489 return this; | 2541 return this; |
| 2490 } | 2542 } |
| 2491 | 2543 |
| 2492 | 2544 |
| 2493 MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name, | 2545 MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name, |
| 2494 DeleteMode mode) { | 2546 DeleteMode mode) { |
| 2495 // Check local property, ignore interceptor. | 2547 // Check local property, ignore interceptor. |
| 2548 Heap* heap = GetHeap(); |
| 2496 LookupResult result; | 2549 LookupResult result; |
| 2497 LocalLookupRealNamedProperty(name, &result); | 2550 LocalLookupRealNamedProperty(name, &result); |
| 2498 if (!result.IsProperty()) return Heap::true_value(); | 2551 if (!result.IsProperty()) return heap->true_value(); |
| 2499 | 2552 |
| 2500 // Normalize object if needed. | 2553 // Normalize object if needed. |
| 2501 Object* obj; | 2554 Object* obj; |
| 2502 { MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 2555 { MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
| 2503 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 2556 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 2504 } | 2557 } |
| 2505 | 2558 |
| 2506 return DeleteNormalizedProperty(name, mode); | 2559 return DeleteNormalizedProperty(name, mode); |
| 2507 } | 2560 } |
| 2508 | 2561 |
| 2509 | 2562 |
| 2510 MaybeObject* JSObject::DeletePropertyWithInterceptor(String* name) { | 2563 MaybeObject* JSObject::DeletePropertyWithInterceptor(String* name) { |
| 2511 HandleScope scope; | 2564 Isolate* isolate = GetIsolate(); |
| 2565 HandleScope scope(isolate); |
| 2512 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); | 2566 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); |
| 2513 Handle<String> name_handle(name); | 2567 Handle<String> name_handle(name); |
| 2514 Handle<JSObject> this_handle(this); | 2568 Handle<JSObject> this_handle(this); |
| 2515 if (!interceptor->deleter()->IsUndefined()) { | 2569 if (!interceptor->deleter()->IsUndefined()) { |
| 2516 v8::NamedPropertyDeleter deleter = | 2570 v8::NamedPropertyDeleter deleter = |
| 2517 v8::ToCData<v8::NamedPropertyDeleter>(interceptor->deleter()); | 2571 v8::ToCData<v8::NamedPropertyDeleter>(interceptor->deleter()); |
| 2518 LOG(ApiNamedPropertyAccess("interceptor-named-delete", *this_handle, name)); | 2572 LOG(isolate, |
| 2519 CustomArguments args(interceptor->data(), this, this); | 2573 ApiNamedPropertyAccess("interceptor-named-delete", *this_handle, name)); |
| 2574 CustomArguments args(isolate, interceptor->data(), this, this); |
| 2520 v8::AccessorInfo info(args.end()); | 2575 v8::AccessorInfo info(args.end()); |
| 2521 v8::Handle<v8::Boolean> result; | 2576 v8::Handle<v8::Boolean> result; |
| 2522 { | 2577 { |
| 2523 // Leaving JavaScript. | 2578 // Leaving JavaScript. |
| 2524 VMState state(EXTERNAL); | 2579 VMState state(isolate, EXTERNAL); |
| 2525 result = deleter(v8::Utils::ToLocal(name_handle), info); | 2580 result = deleter(v8::Utils::ToLocal(name_handle), info); |
| 2526 } | 2581 } |
| 2527 RETURN_IF_SCHEDULED_EXCEPTION(); | 2582 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 2528 if (!result.IsEmpty()) { | 2583 if (!result.IsEmpty()) { |
| 2529 ASSERT(result->IsBoolean()); | 2584 ASSERT(result->IsBoolean()); |
| 2530 return *v8::Utils::OpenHandle(*result); | 2585 return *v8::Utils::OpenHandle(*result); |
| 2531 } | 2586 } |
| 2532 } | 2587 } |
| 2533 MaybeObject* raw_result = | 2588 MaybeObject* raw_result = |
| 2534 this_handle->DeletePropertyPostInterceptor(*name_handle, NORMAL_DELETION); | 2589 this_handle->DeletePropertyPostInterceptor(*name_handle, NORMAL_DELETION); |
| 2535 RETURN_IF_SCHEDULED_EXCEPTION(); | 2590 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 2536 return raw_result; | 2591 return raw_result; |
| 2537 } | 2592 } |
| 2538 | 2593 |
| 2539 | 2594 |
| 2540 MaybeObject* JSObject::DeleteElementPostInterceptor(uint32_t index, | 2595 MaybeObject* JSObject::DeleteElementPostInterceptor(uint32_t index, |
| 2541 DeleteMode mode) { | 2596 DeleteMode mode) { |
| 2597 Heap* heap = GetHeap(); |
| 2542 ASSERT(!HasExternalArrayElements()); | 2598 ASSERT(!HasExternalArrayElements()); |
| 2543 switch (GetElementsKind()) { | 2599 switch (GetElementsKind()) { |
| 2544 case FAST_ELEMENTS: { | 2600 case FAST_ELEMENTS: { |
| 2545 Object* obj; | 2601 Object* obj; |
| 2546 { MaybeObject* maybe_obj = EnsureWritableFastElements(); | 2602 { MaybeObject* maybe_obj = EnsureWritableFastElements(); |
| 2547 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 2603 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 2548 } | 2604 } |
| 2549 uint32_t length = IsJSArray() ? | 2605 uint32_t length = IsJSArray() ? |
| 2550 static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) : | 2606 static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) : |
| 2551 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 2607 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 2552 if (index < length) { | 2608 if (index < length) { |
| 2553 FixedArray::cast(elements())->set_the_hole(index); | 2609 FixedArray::cast(elements())->set_the_hole(index); |
| 2554 } | 2610 } |
| 2555 break; | 2611 break; |
| 2556 } | 2612 } |
| 2557 case DICTIONARY_ELEMENTS: { | 2613 case DICTIONARY_ELEMENTS: { |
| 2558 NumberDictionary* dictionary = element_dictionary(); | 2614 NumberDictionary* dictionary = element_dictionary(); |
| 2559 int entry = dictionary->FindEntry(index); | 2615 int entry = dictionary->FindEntry(index); |
| 2560 if (entry != NumberDictionary::kNotFound) { | 2616 if (entry != NumberDictionary::kNotFound) { |
| 2561 return dictionary->DeleteProperty(entry, mode); | 2617 return dictionary->DeleteProperty(entry, mode); |
| 2562 } | 2618 } |
| 2563 break; | 2619 break; |
| 2564 } | 2620 } |
| 2565 default: | 2621 default: |
| 2566 UNREACHABLE(); | 2622 UNREACHABLE(); |
| 2567 break; | 2623 break; |
| 2568 } | 2624 } |
| 2569 return Heap::true_value(); | 2625 return heap->true_value(); |
| 2570 } | 2626 } |
| 2571 | 2627 |
| 2572 | 2628 |
| 2573 MaybeObject* JSObject::DeleteElementWithInterceptor(uint32_t index) { | 2629 MaybeObject* JSObject::DeleteElementWithInterceptor(uint32_t index) { |
| 2630 Isolate* isolate = GetIsolate(); |
| 2631 Heap* heap = isolate->heap(); |
| 2574 // Make sure that the top context does not change when doing | 2632 // Make sure that the top context does not change when doing |
| 2575 // callbacks or interceptor calls. | 2633 // callbacks or interceptor calls. |
| 2576 AssertNoContextChange ncc; | 2634 AssertNoContextChange ncc; |
| 2577 HandleScope scope; | 2635 HandleScope scope(isolate); |
| 2578 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); | 2636 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); |
| 2579 if (interceptor->deleter()->IsUndefined()) return Heap::false_value(); | 2637 if (interceptor->deleter()->IsUndefined()) return heap->false_value(); |
| 2580 v8::IndexedPropertyDeleter deleter = | 2638 v8::IndexedPropertyDeleter deleter = |
| 2581 v8::ToCData<v8::IndexedPropertyDeleter>(interceptor->deleter()); | 2639 v8::ToCData<v8::IndexedPropertyDeleter>(interceptor->deleter()); |
| 2582 Handle<JSObject> this_handle(this); | 2640 Handle<JSObject> this_handle(this); |
| 2583 LOG(ApiIndexedPropertyAccess("interceptor-indexed-delete", this, index)); | 2641 LOG(isolate, |
| 2584 CustomArguments args(interceptor->data(), this, this); | 2642 ApiIndexedPropertyAccess("interceptor-indexed-delete", this, index)); |
| 2643 CustomArguments args(isolate, interceptor->data(), this, this); |
| 2585 v8::AccessorInfo info(args.end()); | 2644 v8::AccessorInfo info(args.end()); |
| 2586 v8::Handle<v8::Boolean> result; | 2645 v8::Handle<v8::Boolean> result; |
| 2587 { | 2646 { |
| 2588 // Leaving JavaScript. | 2647 // Leaving JavaScript. |
| 2589 VMState state(EXTERNAL); | 2648 VMState state(isolate, EXTERNAL); |
| 2590 result = deleter(index, info); | 2649 result = deleter(index, info); |
| 2591 } | 2650 } |
| 2592 RETURN_IF_SCHEDULED_EXCEPTION(); | 2651 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 2593 if (!result.IsEmpty()) { | 2652 if (!result.IsEmpty()) { |
| 2594 ASSERT(result->IsBoolean()); | 2653 ASSERT(result->IsBoolean()); |
| 2595 return *v8::Utils::OpenHandle(*result); | 2654 return *v8::Utils::OpenHandle(*result); |
| 2596 } | 2655 } |
| 2597 MaybeObject* raw_result = | 2656 MaybeObject* raw_result = |
| 2598 this_handle->DeleteElementPostInterceptor(index, NORMAL_DELETION); | 2657 this_handle->DeleteElementPostInterceptor(index, NORMAL_DELETION); |
| 2599 RETURN_IF_SCHEDULED_EXCEPTION(); | 2658 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 2600 return raw_result; | 2659 return raw_result; |
| 2601 } | 2660 } |
| 2602 | 2661 |
| 2603 | 2662 |
| 2604 MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) { | 2663 MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) { |
| 2664 Isolate* isolate = GetIsolate(); |
| 2605 // Check access rights if needed. | 2665 // Check access rights if needed. |
| 2606 if (IsAccessCheckNeeded() && | 2666 if (IsAccessCheckNeeded() && |
| 2607 !Top::MayIndexedAccess(this, index, v8::ACCESS_DELETE)) { | 2667 !isolate->MayIndexedAccess(this, index, v8::ACCESS_DELETE)) { |
| 2608 Top::ReportFailedAccessCheck(this, v8::ACCESS_DELETE); | 2668 isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE); |
| 2609 return Heap::false_value(); | 2669 return isolate->heap()->false_value(); |
| 2610 } | 2670 } |
| 2611 | 2671 |
| 2612 if (IsJSGlobalProxy()) { | 2672 if (IsJSGlobalProxy()) { |
| 2613 Object* proto = GetPrototype(); | 2673 Object* proto = GetPrototype(); |
| 2614 if (proto->IsNull()) return Heap::false_value(); | 2674 if (proto->IsNull()) return isolate->heap()->false_value(); |
| 2615 ASSERT(proto->IsJSGlobalObject()); | 2675 ASSERT(proto->IsJSGlobalObject()); |
| 2616 return JSGlobalObject::cast(proto)->DeleteElement(index, mode); | 2676 return JSGlobalObject::cast(proto)->DeleteElement(index, mode); |
| 2617 } | 2677 } |
| 2618 | 2678 |
| 2619 if (HasIndexedInterceptor()) { | 2679 if (HasIndexedInterceptor()) { |
| 2620 // Skip interceptor if forcing deletion. | 2680 // Skip interceptor if forcing deletion. |
| 2621 if (mode == FORCE_DELETION) { | 2681 if (mode == FORCE_DELETION) { |
| 2622 return DeleteElementPostInterceptor(index, mode); | 2682 return DeleteElementPostInterceptor(index, mode); |
| 2623 } | 2683 } |
| 2624 return DeleteElementWithInterceptor(index); | 2684 return DeleteElementWithInterceptor(index); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2647 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 2707 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 2648 case EXTERNAL_FLOAT_ELEMENTS: | 2708 case EXTERNAL_FLOAT_ELEMENTS: |
| 2649 // Pixel and external array elements cannot be deleted. Just | 2709 // Pixel and external array elements cannot be deleted. Just |
| 2650 // silently ignore here. | 2710 // silently ignore here. |
| 2651 break; | 2711 break; |
| 2652 case DICTIONARY_ELEMENTS: { | 2712 case DICTIONARY_ELEMENTS: { |
| 2653 NumberDictionary* dictionary = element_dictionary(); | 2713 NumberDictionary* dictionary = element_dictionary(); |
| 2654 int entry = dictionary->FindEntry(index); | 2714 int entry = dictionary->FindEntry(index); |
| 2655 if (entry != NumberDictionary::kNotFound) { | 2715 if (entry != NumberDictionary::kNotFound) { |
| 2656 Object* result = dictionary->DeleteProperty(entry, mode); | 2716 Object* result = dictionary->DeleteProperty(entry, mode); |
| 2657 if (mode == STRICT_DELETION && result == Heap::false_value()) { | 2717 if (mode == STRICT_DELETION && result == |
| 2718 isolate->heap()->false_value()) { |
| 2658 // In strict mode, deleting a non-configurable property throws | 2719 // In strict mode, deleting a non-configurable property throws |
| 2659 // exception. dictionary->DeleteProperty will return false_value() | 2720 // exception. dictionary->DeleteProperty will return false_value() |
| 2660 // if a non-configurable property is being deleted. | 2721 // if a non-configurable property is being deleted. |
| 2661 HandleScope scope; | 2722 HandleScope scope; |
| 2662 Handle<Object> i = Factory::NewNumberFromUint(index); | 2723 Handle<Object> i = isolate->factory()->NewNumberFromUint(index); |
| 2663 Handle<Object> args[2] = { i, Handle<Object>(this) }; | 2724 Handle<Object> args[2] = { i, Handle<Object>(this) }; |
| 2664 return Top::Throw(*Factory::NewTypeError("strict_delete_property", | 2725 return isolate->Throw(*isolate->factory()->NewTypeError( |
| 2665 HandleVector(args, 2))); | 2726 "strict_delete_property", HandleVector(args, 2))); |
| 2666 } | 2727 } |
| 2667 } | 2728 } |
| 2668 break; | 2729 break; |
| 2669 } | 2730 } |
| 2670 default: | 2731 default: |
| 2671 UNREACHABLE(); | 2732 UNREACHABLE(); |
| 2672 break; | 2733 break; |
| 2673 } | 2734 } |
| 2674 return Heap::true_value(); | 2735 return isolate->heap()->true_value(); |
| 2675 } | 2736 } |
| 2676 | 2737 |
| 2677 | 2738 |
| 2678 MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) { | 2739 MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) { |
| 2740 Isolate* isolate = GetIsolate(); |
| 2679 // ECMA-262, 3rd, 8.6.2.5 | 2741 // ECMA-262, 3rd, 8.6.2.5 |
| 2680 ASSERT(name->IsString()); | 2742 ASSERT(name->IsString()); |
| 2681 | 2743 |
| 2682 // Check access rights if needed. | 2744 // Check access rights if needed. |
| 2683 if (IsAccessCheckNeeded() && | 2745 if (IsAccessCheckNeeded() && |
| 2684 !Top::MayNamedAccess(this, name, v8::ACCESS_DELETE)) { | 2746 !isolate->MayNamedAccess(this, name, v8::ACCESS_DELETE)) { |
| 2685 Top::ReportFailedAccessCheck(this, v8::ACCESS_DELETE); | 2747 isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE); |
| 2686 return Heap::false_value(); | 2748 return isolate->heap()->false_value(); |
| 2687 } | 2749 } |
| 2688 | 2750 |
| 2689 if (IsJSGlobalProxy()) { | 2751 if (IsJSGlobalProxy()) { |
| 2690 Object* proto = GetPrototype(); | 2752 Object* proto = GetPrototype(); |
| 2691 if (proto->IsNull()) return Heap::false_value(); | 2753 if (proto->IsNull()) return isolate->heap()->false_value(); |
| 2692 ASSERT(proto->IsJSGlobalObject()); | 2754 ASSERT(proto->IsJSGlobalObject()); |
| 2693 return JSGlobalObject::cast(proto)->DeleteProperty(name, mode); | 2755 return JSGlobalObject::cast(proto)->DeleteProperty(name, mode); |
| 2694 } | 2756 } |
| 2695 | 2757 |
| 2696 uint32_t index = 0; | 2758 uint32_t index = 0; |
| 2697 if (name->AsArrayIndex(&index)) { | 2759 if (name->AsArrayIndex(&index)) { |
| 2698 return DeleteElement(index, mode); | 2760 return DeleteElement(index, mode); |
| 2699 } else { | 2761 } else { |
| 2700 LookupResult result; | 2762 LookupResult result; |
| 2701 LocalLookup(name, &result); | 2763 LocalLookup(name, &result); |
| 2702 if (!result.IsProperty()) return Heap::true_value(); | 2764 if (!result.IsProperty()) return isolate->heap()->true_value(); |
| 2703 // Ignore attributes if forcing a deletion. | 2765 // Ignore attributes if forcing a deletion. |
| 2704 if (result.IsDontDelete() && mode != FORCE_DELETION) { | 2766 if (result.IsDontDelete() && mode != FORCE_DELETION) { |
| 2705 if (mode == STRICT_DELETION) { | 2767 if (mode == STRICT_DELETION) { |
| 2706 // Deleting a non-configurable property in strict mode. | 2768 // Deleting a non-configurable property in strict mode. |
| 2707 HandleScope scope; | 2769 HandleScope scope(isolate); |
| 2708 Handle<Object> args[2] = { Handle<Object>(name), Handle<Object>(this) }; | 2770 Handle<Object> args[2] = { Handle<Object>(name), Handle<Object>(this) }; |
| 2709 return Top::Throw(*Factory::NewTypeError("strict_delete_property", | 2771 return isolate->Throw(*isolate->factory()->NewTypeError( |
| 2710 HandleVector(args, 2))); | 2772 "strict_delete_property", HandleVector(args, 2))); |
| 2711 } | 2773 } |
| 2712 return Heap::false_value(); | 2774 return isolate->heap()->false_value(); |
| 2713 } | 2775 } |
| 2714 // Check for interceptor. | 2776 // Check for interceptor. |
| 2715 if (result.type() == INTERCEPTOR) { | 2777 if (result.type() == INTERCEPTOR) { |
| 2716 // Skip interceptor if forcing a deletion. | 2778 // Skip interceptor if forcing a deletion. |
| 2717 if (mode == FORCE_DELETION) { | 2779 if (mode == FORCE_DELETION) { |
| 2718 return DeletePropertyPostInterceptor(name, mode); | 2780 return DeletePropertyPostInterceptor(name, mode); |
| 2719 } | 2781 } |
| 2720 return DeletePropertyWithInterceptor(name); | 2782 return DeletePropertyWithInterceptor(name); |
| 2721 } | 2783 } |
| 2722 // Normalize object if needed. | 2784 // Normalize object if needed. |
| 2723 Object* obj; | 2785 Object* obj; |
| 2724 { MaybeObject* maybe_obj = | 2786 { MaybeObject* maybe_obj = |
| 2725 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 2787 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
| 2726 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 2788 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 2727 } | 2789 } |
| 2728 // Make sure the properties are normalized before removing the entry. | 2790 // Make sure the properties are normalized before removing the entry. |
| 2729 return DeleteNormalizedProperty(name, mode); | 2791 return DeleteNormalizedProperty(name, mode); |
| 2730 } | 2792 } |
| 2731 } | 2793 } |
| 2732 | 2794 |
| 2733 | 2795 |
| 2734 // Check whether this object references another object. | 2796 // Check whether this object references another object. |
| 2735 bool JSObject::ReferencesObject(Object* obj) { | 2797 bool JSObject::ReferencesObject(Object* obj) { |
| 2798 Heap* heap = GetHeap(); |
| 2736 AssertNoAllocation no_alloc; | 2799 AssertNoAllocation no_alloc; |
| 2737 | 2800 |
| 2738 // Is the object the constructor for this object? | 2801 // Is the object the constructor for this object? |
| 2739 if (map()->constructor() == obj) { | 2802 if (map()->constructor() == obj) { |
| 2740 return true; | 2803 return true; |
| 2741 } | 2804 } |
| 2742 | 2805 |
| 2743 // Is the object the prototype for this object? | 2806 // Is the object the prototype for this object? |
| 2744 if (map()->prototype() == obj) { | 2807 if (map()->prototype() == obj) { |
| 2745 return true; | 2808 return true; |
| 2746 } | 2809 } |
| 2747 | 2810 |
| 2748 // Check if the object is among the named properties. | 2811 // Check if the object is among the named properties. |
| 2749 Object* key = SlowReverseLookup(obj); | 2812 Object* key = SlowReverseLookup(obj); |
| 2750 if (key != Heap::undefined_value()) { | 2813 if (!key->IsUndefined()) { |
| 2751 return true; | 2814 return true; |
| 2752 } | 2815 } |
| 2753 | 2816 |
| 2754 // Check if the object is among the indexed properties. | 2817 // Check if the object is among the indexed properties. |
| 2755 switch (GetElementsKind()) { | 2818 switch (GetElementsKind()) { |
| 2756 case EXTERNAL_PIXEL_ELEMENTS: | 2819 case EXTERNAL_PIXEL_ELEMENTS: |
| 2757 case EXTERNAL_BYTE_ELEMENTS: | 2820 case EXTERNAL_BYTE_ELEMENTS: |
| 2758 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 2821 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 2759 case EXTERNAL_SHORT_ELEMENTS: | 2822 case EXTERNAL_SHORT_ELEMENTS: |
| 2760 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 2823 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2771 for (int i = 0; i < length; i++) { | 2834 for (int i = 0; i < length; i++) { |
| 2772 Object* element = FixedArray::cast(elements())->get(i); | 2835 Object* element = FixedArray::cast(elements())->get(i); |
| 2773 if (!element->IsTheHole() && element == obj) { | 2836 if (!element->IsTheHole() && element == obj) { |
| 2774 return true; | 2837 return true; |
| 2775 } | 2838 } |
| 2776 } | 2839 } |
| 2777 break; | 2840 break; |
| 2778 } | 2841 } |
| 2779 case DICTIONARY_ELEMENTS: { | 2842 case DICTIONARY_ELEMENTS: { |
| 2780 key = element_dictionary()->SlowReverseLookup(obj); | 2843 key = element_dictionary()->SlowReverseLookup(obj); |
| 2781 if (key != Heap::undefined_value()) { | 2844 if (!key->IsUndefined()) { |
| 2782 return true; | 2845 return true; |
| 2783 } | 2846 } |
| 2784 break; | 2847 break; |
| 2785 } | 2848 } |
| 2786 default: | 2849 default: |
| 2787 UNREACHABLE(); | 2850 UNREACHABLE(); |
| 2788 break; | 2851 break; |
| 2789 } | 2852 } |
| 2790 | 2853 |
| 2791 // For functions check the context. | 2854 // For functions check the context. |
| 2792 if (IsJSFunction()) { | 2855 if (IsJSFunction()) { |
| 2793 // Get the constructor function for arguments array. | 2856 // Get the constructor function for arguments array. |
| 2794 JSObject* arguments_boilerplate = | 2857 JSObject* arguments_boilerplate = |
| 2795 Top::context()->global_context()->arguments_boilerplate(); | 2858 heap->isolate()->context()->global_context()-> |
| 2859 arguments_boilerplate(); |
| 2796 JSFunction* arguments_function = | 2860 JSFunction* arguments_function = |
| 2797 JSFunction::cast(arguments_boilerplate->map()->constructor()); | 2861 JSFunction::cast(arguments_boilerplate->map()->constructor()); |
| 2798 | 2862 |
| 2799 // Get the context and don't check if it is the global context. | 2863 // Get the context and don't check if it is the global context. |
| 2800 JSFunction* f = JSFunction::cast(this); | 2864 JSFunction* f = JSFunction::cast(this); |
| 2801 Context* context = f->context(); | 2865 Context* context = f->context(); |
| 2802 if (context->IsGlobalContext()) { | 2866 if (context->IsGlobalContext()) { |
| 2803 return false; | 2867 return false; |
| 2804 } | 2868 } |
| 2805 | 2869 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2824 return context->extension()->ReferencesObject(obj); | 2888 return context->extension()->ReferencesObject(obj); |
| 2825 } | 2889 } |
| 2826 } | 2890 } |
| 2827 | 2891 |
| 2828 // No references to object. | 2892 // No references to object. |
| 2829 return false; | 2893 return false; |
| 2830 } | 2894 } |
| 2831 | 2895 |
| 2832 | 2896 |
| 2833 MaybeObject* JSObject::PreventExtensions() { | 2897 MaybeObject* JSObject::PreventExtensions() { |
| 2898 Isolate* isolate = GetIsolate(); |
| 2834 if (IsAccessCheckNeeded() && | 2899 if (IsAccessCheckNeeded() && |
| 2835 !Top::MayNamedAccess(this, Heap::undefined_value(), v8::ACCESS_KEYS)) { | 2900 !isolate->MayNamedAccess(this, |
| 2836 Top::ReportFailedAccessCheck(this, v8::ACCESS_KEYS); | 2901 isolate->heap()->undefined_value(), |
| 2837 return Heap::false_value(); | 2902 v8::ACCESS_KEYS)) { |
| 2903 isolate->ReportFailedAccessCheck(this, v8::ACCESS_KEYS); |
| 2904 return isolate->heap()->false_value(); |
| 2838 } | 2905 } |
| 2839 | 2906 |
| 2840 if (IsJSGlobalProxy()) { | 2907 if (IsJSGlobalProxy()) { |
| 2841 Object* proto = GetPrototype(); | 2908 Object* proto = GetPrototype(); |
| 2842 if (proto->IsNull()) return this; | 2909 if (proto->IsNull()) return this; |
| 2843 ASSERT(proto->IsJSGlobalObject()); | 2910 ASSERT(proto->IsJSGlobalObject()); |
| 2844 return JSObject::cast(proto)->PreventExtensions(); | 2911 return JSObject::cast(proto)->PreventExtensions(); |
| 2845 } | 2912 } |
| 2846 | 2913 |
| 2847 // If there are fast elements we normalize. | 2914 // If there are fast elements we normalize. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2866 return new_map; | 2933 return new_map; |
| 2867 } | 2934 } |
| 2868 | 2935 |
| 2869 | 2936 |
| 2870 // Tests for the fast common case for property enumeration: | 2937 // Tests for the fast common case for property enumeration: |
| 2871 // - This object and all prototypes has an enum cache (which means that it has | 2938 // - This object and all prototypes has an enum cache (which means that it has |
| 2872 // no interceptors and needs no access checks). | 2939 // no interceptors and needs no access checks). |
| 2873 // - This object has no elements. | 2940 // - This object has no elements. |
| 2874 // - No prototype has enumerable properties/elements. | 2941 // - No prototype has enumerable properties/elements. |
| 2875 bool JSObject::IsSimpleEnum() { | 2942 bool JSObject::IsSimpleEnum() { |
| 2943 Heap* heap = GetHeap(); |
| 2876 for (Object* o = this; | 2944 for (Object* o = this; |
| 2877 o != Heap::null_value(); | 2945 o != heap->null_value(); |
| 2878 o = JSObject::cast(o)->GetPrototype()) { | 2946 o = JSObject::cast(o)->GetPrototype()) { |
| 2879 JSObject* curr = JSObject::cast(o); | 2947 JSObject* curr = JSObject::cast(o); |
| 2880 if (!curr->map()->instance_descriptors()->HasEnumCache()) return false; | 2948 if (!curr->map()->instance_descriptors()->HasEnumCache()) return false; |
| 2881 ASSERT(!curr->HasNamedInterceptor()); | 2949 ASSERT(!curr->HasNamedInterceptor()); |
| 2882 ASSERT(!curr->HasIndexedInterceptor()); | 2950 ASSERT(!curr->HasIndexedInterceptor()); |
| 2883 ASSERT(!curr->IsAccessCheckNeeded()); | 2951 ASSERT(!curr->IsAccessCheckNeeded()); |
| 2884 if (curr->NumberOfEnumElements() > 0) return false; | 2952 if (curr->NumberOfEnumElements() > 0) return false; |
| 2885 if (curr != this) { | 2953 if (curr != this) { |
| 2886 FixedArray* curr_fixed_array = | 2954 FixedArray* curr_fixed_array = |
| 2887 FixedArray::cast(curr->map()->instance_descriptors()->GetEnumCache()); | 2955 FixedArray::cast(curr->map()->instance_descriptors()->GetEnumCache()); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2933 return descs->GetCallbacks(i); | 3001 return descs->GetCallbacks(i); |
| 2934 } | 3002 } |
| 2935 } | 3003 } |
| 2936 return NULL; | 3004 return NULL; |
| 2937 } | 3005 } |
| 2938 | 3006 |
| 2939 | 3007 |
| 2940 void JSObject::LocalLookup(String* name, LookupResult* result) { | 3008 void JSObject::LocalLookup(String* name, LookupResult* result) { |
| 2941 ASSERT(name->IsString()); | 3009 ASSERT(name->IsString()); |
| 2942 | 3010 |
| 3011 Heap* heap = GetHeap(); |
| 3012 |
| 2943 if (IsJSGlobalProxy()) { | 3013 if (IsJSGlobalProxy()) { |
| 2944 Object* proto = GetPrototype(); | 3014 Object* proto = GetPrototype(); |
| 2945 if (proto->IsNull()) return result->NotFound(); | 3015 if (proto->IsNull()) return result->NotFound(); |
| 2946 ASSERT(proto->IsJSGlobalObject()); | 3016 ASSERT(proto->IsJSGlobalObject()); |
| 2947 return JSObject::cast(proto)->LocalLookup(name, result); | 3017 return JSObject::cast(proto)->LocalLookup(name, result); |
| 2948 } | 3018 } |
| 2949 | 3019 |
| 2950 // Do not use inline caching if the object is a non-global object | 3020 // Do not use inline caching if the object is a non-global object |
| 2951 // that requires access checks. | 3021 // that requires access checks. |
| 2952 if (!IsJSGlobalProxy() && IsAccessCheckNeeded()) { | 3022 if (!IsJSGlobalProxy() && IsAccessCheckNeeded()) { |
| 2953 result->DisallowCaching(); | 3023 result->DisallowCaching(); |
| 2954 } | 3024 } |
| 2955 | 3025 |
| 2956 // Check __proto__ before interceptor. | 3026 // Check __proto__ before interceptor. |
| 2957 if (name->Equals(Heap::Proto_symbol()) && !IsJSContextExtensionObject()) { | 3027 if (name->Equals(heap->Proto_symbol()) && |
| 3028 !IsJSContextExtensionObject()) { |
| 2958 result->ConstantResult(this); | 3029 result->ConstantResult(this); |
| 2959 return; | 3030 return; |
| 2960 } | 3031 } |
| 2961 | 3032 |
| 2962 // Check for lookup interceptor except when bootstrapping. | 3033 // Check for lookup interceptor except when bootstrapping. |
| 2963 if (HasNamedInterceptor() && !Bootstrapper::IsActive()) { | 3034 if (HasNamedInterceptor() && !heap->isolate()->bootstrapper()->IsActive()) { |
| 2964 result->InterceptorResult(this); | 3035 result->InterceptorResult(this); |
| 2965 return; | 3036 return; |
| 2966 } | 3037 } |
| 2967 | 3038 |
| 2968 LocalLookupRealNamedProperty(name, result); | 3039 LocalLookupRealNamedProperty(name, result); |
| 2969 } | 3040 } |
| 2970 | 3041 |
| 2971 | 3042 |
| 2972 void JSObject::Lookup(String* name, LookupResult* result) { | 3043 void JSObject::Lookup(String* name, LookupResult* result) { |
| 2973 // Ecma-262 3rd 8.6.2.4 | 3044 // Ecma-262 3rd 8.6.2.4 |
| 3045 Heap* heap = GetHeap(); |
| 2974 for (Object* current = this; | 3046 for (Object* current = this; |
| 2975 current != Heap::null_value(); | 3047 current != heap->null_value(); |
| 2976 current = JSObject::cast(current)->GetPrototype()) { | 3048 current = JSObject::cast(current)->GetPrototype()) { |
| 2977 JSObject::cast(current)->LocalLookup(name, result); | 3049 JSObject::cast(current)->LocalLookup(name, result); |
| 2978 if (result->IsProperty()) return; | 3050 if (result->IsProperty()) return; |
| 2979 } | 3051 } |
| 2980 result->NotFound(); | 3052 result->NotFound(); |
| 2981 } | 3053 } |
| 2982 | 3054 |
| 2983 | 3055 |
| 2984 // Search object and it's prototype chain for callback properties. | 3056 // Search object and it's prototype chain for callback properties. |
| 2985 void JSObject::LookupCallback(String* name, LookupResult* result) { | 3057 void JSObject::LookupCallback(String* name, LookupResult* result) { |
| 3058 Heap* heap = GetHeap(); |
| 2986 for (Object* current = this; | 3059 for (Object* current = this; |
| 2987 current != Heap::null_value(); | 3060 current != heap->null_value(); |
| 2988 current = JSObject::cast(current)->GetPrototype()) { | 3061 current = JSObject::cast(current)->GetPrototype()) { |
| 2989 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result); | 3062 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result); |
| 2990 if (result->IsProperty() && result->type() == CALLBACKS) return; | 3063 if (result->IsProperty() && result->type() == CALLBACKS) return; |
| 2991 } | 3064 } |
| 2992 result->NotFound(); | 3065 result->NotFound(); |
| 2993 } | 3066 } |
| 2994 | 3067 |
| 2995 | 3068 |
| 2996 MaybeObject* JSObject::DefineGetterSetter(String* name, | 3069 MaybeObject* JSObject::DefineGetterSetter(String* name, |
| 2997 PropertyAttributes attributes) { | 3070 PropertyAttributes attributes) { |
| 3071 Heap* heap = GetHeap(); |
| 2998 // Make sure that the top context does not change when doing callbacks or | 3072 // Make sure that the top context does not change when doing callbacks or |
| 2999 // interceptor calls. | 3073 // interceptor calls. |
| 3000 AssertNoContextChange ncc; | 3074 AssertNoContextChange ncc; |
| 3001 | 3075 |
| 3002 // Try to flatten before operating on the string. | 3076 // Try to flatten before operating on the string. |
| 3003 name->TryFlatten(); | 3077 name->TryFlatten(); |
| 3004 | 3078 |
| 3005 if (!CanSetCallback(name)) { | 3079 if (!CanSetCallback(name)) { |
| 3006 return Heap::undefined_value(); | 3080 return heap->undefined_value(); |
| 3007 } | 3081 } |
| 3008 | 3082 |
| 3009 uint32_t index = 0; | 3083 uint32_t index = 0; |
| 3010 bool is_element = name->AsArrayIndex(&index); | 3084 bool is_element = name->AsArrayIndex(&index); |
| 3011 | 3085 |
| 3012 if (is_element) { | 3086 if (is_element) { |
| 3013 switch (GetElementsKind()) { | 3087 switch (GetElementsKind()) { |
| 3014 case FAST_ELEMENTS: | 3088 case FAST_ELEMENTS: |
| 3015 break; | 3089 break; |
| 3016 case EXTERNAL_PIXEL_ELEMENTS: | 3090 case EXTERNAL_PIXEL_ELEMENTS: |
| 3017 case EXTERNAL_BYTE_ELEMENTS: | 3091 case EXTERNAL_BYTE_ELEMENTS: |
| 3018 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 3092 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3019 case EXTERNAL_SHORT_ELEMENTS: | 3093 case EXTERNAL_SHORT_ELEMENTS: |
| 3020 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3094 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3021 case EXTERNAL_INT_ELEMENTS: | 3095 case EXTERNAL_INT_ELEMENTS: |
| 3022 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3096 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 3023 case EXTERNAL_FLOAT_ELEMENTS: | 3097 case EXTERNAL_FLOAT_ELEMENTS: |
| 3024 // Ignore getters and setters on pixel and external array | 3098 // Ignore getters and setters on pixel and external array |
| 3025 // elements. | 3099 // elements. |
| 3026 return Heap::undefined_value(); | 3100 return heap->undefined_value(); |
| 3027 case DICTIONARY_ELEMENTS: { | 3101 case DICTIONARY_ELEMENTS: { |
| 3028 // Lookup the index. | 3102 // Lookup the index. |
| 3029 NumberDictionary* dictionary = element_dictionary(); | 3103 NumberDictionary* dictionary = element_dictionary(); |
| 3030 int entry = dictionary->FindEntry(index); | 3104 int entry = dictionary->FindEntry(index); |
| 3031 if (entry != NumberDictionary::kNotFound) { | 3105 if (entry != NumberDictionary::kNotFound) { |
| 3032 Object* result = dictionary->ValueAt(entry); | 3106 Object* result = dictionary->ValueAt(entry); |
| 3033 PropertyDetails details = dictionary->DetailsAt(entry); | 3107 PropertyDetails details = dictionary->DetailsAt(entry); |
| 3034 if (details.IsReadOnly()) return Heap::undefined_value(); | 3108 if (details.IsReadOnly()) return heap->undefined_value(); |
| 3035 if (details.type() == CALLBACKS) { | 3109 if (details.type() == CALLBACKS) { |
| 3036 if (result->IsFixedArray()) { | 3110 if (result->IsFixedArray()) { |
| 3037 return result; | 3111 return result; |
| 3038 } | 3112 } |
| 3039 // Otherwise allow to override it. | 3113 // Otherwise allow to override it. |
| 3040 } | 3114 } |
| 3041 } | 3115 } |
| 3042 break; | 3116 break; |
| 3043 } | 3117 } |
| 3044 default: | 3118 default: |
| 3045 UNREACHABLE(); | 3119 UNREACHABLE(); |
| 3046 break; | 3120 break; |
| 3047 } | 3121 } |
| 3048 } else { | 3122 } else { |
| 3049 // Lookup the name. | 3123 // Lookup the name. |
| 3050 LookupResult result; | 3124 LookupResult result; |
| 3051 LocalLookup(name, &result); | 3125 LocalLookup(name, &result); |
| 3052 if (result.IsProperty()) { | 3126 if (result.IsProperty()) { |
| 3053 if (result.IsReadOnly()) return Heap::undefined_value(); | 3127 if (result.IsReadOnly()) return heap->undefined_value(); |
| 3054 if (result.type() == CALLBACKS) { | 3128 if (result.type() == CALLBACKS) { |
| 3055 Object* obj = result.GetCallbackObject(); | 3129 Object* obj = result.GetCallbackObject(); |
| 3056 // Need to preserve old getters/setters. | 3130 // Need to preserve old getters/setters. |
| 3057 if (obj->IsFixedArray()) { | 3131 if (obj->IsFixedArray()) { |
| 3058 // Use set to update attributes. | 3132 // Use set to update attributes. |
| 3059 return SetPropertyCallback(name, obj, attributes); | 3133 return SetPropertyCallback(name, obj, attributes); |
| 3060 } | 3134 } |
| 3061 } | 3135 } |
| 3062 } | 3136 } |
| 3063 } | 3137 } |
| 3064 | 3138 |
| 3065 // Allocate the fixed array to hold getter and setter. | 3139 // Allocate the fixed array to hold getter and setter. |
| 3066 Object* structure; | 3140 Object* structure; |
| 3067 { MaybeObject* maybe_structure = Heap::AllocateFixedArray(2, TENURED); | 3141 { MaybeObject* maybe_structure = heap->AllocateFixedArray(2, TENURED); |
| 3068 if (!maybe_structure->ToObject(&structure)) return maybe_structure; | 3142 if (!maybe_structure->ToObject(&structure)) return maybe_structure; |
| 3069 } | 3143 } |
| 3070 | 3144 |
| 3071 if (is_element) { | 3145 if (is_element) { |
| 3072 return SetElementCallback(index, structure, attributes); | 3146 return SetElementCallback(index, structure, attributes); |
| 3073 } else { | 3147 } else { |
| 3074 return SetPropertyCallback(name, structure, attributes); | 3148 return SetPropertyCallback(name, structure, attributes); |
| 3075 } | 3149 } |
| 3076 } | 3150 } |
| 3077 | 3151 |
| 3078 | 3152 |
| 3079 bool JSObject::CanSetCallback(String* name) { | 3153 bool JSObject::CanSetCallback(String* name) { |
| 3080 ASSERT(!IsAccessCheckNeeded() | 3154 ASSERT(!IsAccessCheckNeeded() |
| 3081 || Top::MayNamedAccess(this, name, v8::ACCESS_SET)); | 3155 || Isolate::Current()->MayNamedAccess(this, name, v8::ACCESS_SET)); |
| 3082 | 3156 |
| 3083 // Check if there is an API defined callback object which prohibits | 3157 // Check if there is an API defined callback object which prohibits |
| 3084 // callback overwriting in this object or it's prototype chain. | 3158 // callback overwriting in this object or it's prototype chain. |
| 3085 // This mechanism is needed for instance in a browser setting, where | 3159 // This mechanism is needed for instance in a browser setting, where |
| 3086 // certain accessors such as window.location should not be allowed | 3160 // certain accessors such as window.location should not be allowed |
| 3087 // to be overwritten because allowing overwriting could potentially | 3161 // to be overwritten because allowing overwriting could potentially |
| 3088 // cause security problems. | 3162 // cause security problems. |
| 3089 LookupResult callback_result; | 3163 LookupResult callback_result; |
| 3090 LookupCallback(name, &callback_result); | 3164 LookupCallback(name, &callback_result); |
| 3091 if (callback_result.IsProperty()) { | 3165 if (callback_result.IsProperty()) { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3168 } | 3242 } |
| 3169 } | 3243 } |
| 3170 return result; | 3244 return result; |
| 3171 } | 3245 } |
| 3172 | 3246 |
| 3173 MaybeObject* JSObject::DefineAccessor(String* name, | 3247 MaybeObject* JSObject::DefineAccessor(String* name, |
| 3174 bool is_getter, | 3248 bool is_getter, |
| 3175 Object* fun, | 3249 Object* fun, |
| 3176 PropertyAttributes attributes) { | 3250 PropertyAttributes attributes) { |
| 3177 ASSERT(fun->IsJSFunction() || fun->IsUndefined()); | 3251 ASSERT(fun->IsJSFunction() || fun->IsUndefined()); |
| 3252 Isolate* isolate = GetIsolate(); |
| 3178 // Check access rights if needed. | 3253 // Check access rights if needed. |
| 3179 if (IsAccessCheckNeeded() && | 3254 if (IsAccessCheckNeeded() && |
| 3180 !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { | 3255 !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) { |
| 3181 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); | 3256 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); |
| 3182 return Heap::undefined_value(); | 3257 return isolate->heap()->undefined_value(); |
| 3183 } | 3258 } |
| 3184 | 3259 |
| 3185 if (IsJSGlobalProxy()) { | 3260 if (IsJSGlobalProxy()) { |
| 3186 Object* proto = GetPrototype(); | 3261 Object* proto = GetPrototype(); |
| 3187 if (proto->IsNull()) return this; | 3262 if (proto->IsNull()) return this; |
| 3188 ASSERT(proto->IsJSGlobalObject()); | 3263 ASSERT(proto->IsJSGlobalObject()); |
| 3189 return JSObject::cast(proto)->DefineAccessor(name, is_getter, | 3264 return JSObject::cast(proto)->DefineAccessor(name, is_getter, |
| 3190 fun, attributes); | 3265 fun, attributes); |
| 3191 } | 3266 } |
| 3192 | 3267 |
| 3193 Object* array; | 3268 Object* array; |
| 3194 { MaybeObject* maybe_array = DefineGetterSetter(name, attributes); | 3269 { MaybeObject* maybe_array = DefineGetterSetter(name, attributes); |
| 3195 if (!maybe_array->ToObject(&array)) return maybe_array; | 3270 if (!maybe_array->ToObject(&array)) return maybe_array; |
| 3196 } | 3271 } |
| 3197 if (array->IsUndefined()) return array; | 3272 if (array->IsUndefined()) return array; |
| 3198 FixedArray::cast(array)->set(is_getter ? 0 : 1, fun); | 3273 FixedArray::cast(array)->set(is_getter ? 0 : 1, fun); |
| 3199 return this; | 3274 return this; |
| 3200 } | 3275 } |
| 3201 | 3276 |
| 3202 | 3277 |
| 3203 MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) { | 3278 MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) { |
| 3279 Isolate* isolate = GetIsolate(); |
| 3204 String* name = String::cast(info->name()); | 3280 String* name = String::cast(info->name()); |
| 3205 // Check access rights if needed. | 3281 // Check access rights if needed. |
| 3206 if (IsAccessCheckNeeded() && | 3282 if (IsAccessCheckNeeded() && |
| 3207 !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { | 3283 !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) { |
| 3208 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); | 3284 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); |
| 3209 return Heap::undefined_value(); | 3285 return isolate->heap()->undefined_value(); |
| 3210 } | 3286 } |
| 3211 | 3287 |
| 3212 if (IsJSGlobalProxy()) { | 3288 if (IsJSGlobalProxy()) { |
| 3213 Object* proto = GetPrototype(); | 3289 Object* proto = GetPrototype(); |
| 3214 if (proto->IsNull()) return this; | 3290 if (proto->IsNull()) return this; |
| 3215 ASSERT(proto->IsJSGlobalObject()); | 3291 ASSERT(proto->IsJSGlobalObject()); |
| 3216 return JSObject::cast(proto)->DefineAccessor(info); | 3292 return JSObject::cast(proto)->DefineAccessor(info); |
| 3217 } | 3293 } |
| 3218 | 3294 |
| 3219 // Make sure that the top context does not change when doing callbacks or | 3295 // Make sure that the top context does not change when doing callbacks or |
| 3220 // interceptor calls. | 3296 // interceptor calls. |
| 3221 AssertNoContextChange ncc; | 3297 AssertNoContextChange ncc; |
| 3222 | 3298 |
| 3223 // Try to flatten before operating on the string. | 3299 // Try to flatten before operating on the string. |
| 3224 name->TryFlatten(); | 3300 name->TryFlatten(); |
| 3225 | 3301 |
| 3226 if (!CanSetCallback(name)) { | 3302 if (!CanSetCallback(name)) { |
| 3227 return Heap::undefined_value(); | 3303 return isolate->heap()->undefined_value(); |
| 3228 } | 3304 } |
| 3229 | 3305 |
| 3230 uint32_t index = 0; | 3306 uint32_t index = 0; |
| 3231 bool is_element = name->AsArrayIndex(&index); | 3307 bool is_element = name->AsArrayIndex(&index); |
| 3232 | 3308 |
| 3233 if (is_element) { | 3309 if (is_element) { |
| 3234 if (IsJSArray()) return Heap::undefined_value(); | 3310 if (IsJSArray()) return isolate->heap()->undefined_value(); |
| 3235 | 3311 |
| 3236 // Accessors overwrite previous callbacks (cf. with getters/setters). | 3312 // Accessors overwrite previous callbacks (cf. with getters/setters). |
| 3237 switch (GetElementsKind()) { | 3313 switch (GetElementsKind()) { |
| 3238 case FAST_ELEMENTS: | 3314 case FAST_ELEMENTS: |
| 3239 break; | 3315 break; |
| 3240 case EXTERNAL_PIXEL_ELEMENTS: | 3316 case EXTERNAL_PIXEL_ELEMENTS: |
| 3241 case EXTERNAL_BYTE_ELEMENTS: | 3317 case EXTERNAL_BYTE_ELEMENTS: |
| 3242 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 3318 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3243 case EXTERNAL_SHORT_ELEMENTS: | 3319 case EXTERNAL_SHORT_ELEMENTS: |
| 3244 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3320 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3245 case EXTERNAL_INT_ELEMENTS: | 3321 case EXTERNAL_INT_ELEMENTS: |
| 3246 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3322 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 3247 case EXTERNAL_FLOAT_ELEMENTS: | 3323 case EXTERNAL_FLOAT_ELEMENTS: |
| 3248 // Ignore getters and setters on pixel and external array | 3324 // Ignore getters and setters on pixel and external array |
| 3249 // elements. | 3325 // elements. |
| 3250 return Heap::undefined_value(); | 3326 return isolate->heap()->undefined_value(); |
| 3251 case DICTIONARY_ELEMENTS: | 3327 case DICTIONARY_ELEMENTS: |
| 3252 break; | 3328 break; |
| 3253 default: | 3329 default: |
| 3254 UNREACHABLE(); | 3330 UNREACHABLE(); |
| 3255 break; | 3331 break; |
| 3256 } | 3332 } |
| 3257 | 3333 |
| 3258 Object* ok; | 3334 Object* ok; |
| 3259 { MaybeObject* maybe_ok = | 3335 { MaybeObject* maybe_ok = |
| 3260 SetElementCallback(index, info, info->property_attributes()); | 3336 SetElementCallback(index, info, info->property_attributes()); |
| 3261 if (!maybe_ok->ToObject(&ok)) return maybe_ok; | 3337 if (!maybe_ok->ToObject(&ok)) return maybe_ok; |
| 3262 } | 3338 } |
| 3263 } else { | 3339 } else { |
| 3264 // Lookup the name. | 3340 // Lookup the name. |
| 3265 LookupResult result; | 3341 LookupResult result; |
| 3266 LocalLookup(name, &result); | 3342 LocalLookup(name, &result); |
| 3267 // ES5 forbids turning a property into an accessor if it's not | 3343 // ES5 forbids turning a property into an accessor if it's not |
| 3268 // configurable (that is IsDontDelete in ES3 and v8), see 8.6.1 (Table 5). | 3344 // configurable (that is IsDontDelete in ES3 and v8), see 8.6.1 (Table 5). |
| 3269 if (result.IsProperty() && (result.IsReadOnly() || result.IsDontDelete())) { | 3345 if (result.IsProperty() && (result.IsReadOnly() || result.IsDontDelete())) { |
| 3270 return Heap::undefined_value(); | 3346 return isolate->heap()->undefined_value(); |
| 3271 } | 3347 } |
| 3272 Object* ok; | 3348 Object* ok; |
| 3273 { MaybeObject* maybe_ok = | 3349 { MaybeObject* maybe_ok = |
| 3274 SetPropertyCallback(name, info, info->property_attributes()); | 3350 SetPropertyCallback(name, info, info->property_attributes()); |
| 3275 if (!maybe_ok->ToObject(&ok)) return maybe_ok; | 3351 if (!maybe_ok->ToObject(&ok)) return maybe_ok; |
| 3276 } | 3352 } |
| 3277 } | 3353 } |
| 3278 | 3354 |
| 3279 return this; | 3355 return this; |
| 3280 } | 3356 } |
| 3281 | 3357 |
| 3282 | 3358 |
| 3283 Object* JSObject::LookupAccessor(String* name, bool is_getter) { | 3359 Object* JSObject::LookupAccessor(String* name, bool is_getter) { |
| 3360 Heap* heap = GetHeap(); |
| 3361 |
| 3284 // Make sure that the top context does not change when doing callbacks or | 3362 // Make sure that the top context does not change when doing callbacks or |
| 3285 // interceptor calls. | 3363 // interceptor calls. |
| 3286 AssertNoContextChange ncc; | 3364 AssertNoContextChange ncc; |
| 3287 | 3365 |
| 3288 // Check access rights if needed. | 3366 // Check access rights if needed. |
| 3289 if (IsAccessCheckNeeded() && | 3367 if (IsAccessCheckNeeded() && |
| 3290 !Top::MayNamedAccess(this, name, v8::ACCESS_HAS)) { | 3368 !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_HAS)) { |
| 3291 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 3369 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 3292 return Heap::undefined_value(); | 3370 return heap->undefined_value(); |
| 3293 } | 3371 } |
| 3294 | 3372 |
| 3295 // Make the lookup and include prototypes. | 3373 // Make the lookup and include prototypes. |
| 3296 int accessor_index = is_getter ? kGetterIndex : kSetterIndex; | 3374 int accessor_index = is_getter ? kGetterIndex : kSetterIndex; |
| 3297 uint32_t index = 0; | 3375 uint32_t index = 0; |
| 3298 if (name->AsArrayIndex(&index)) { | 3376 if (name->AsArrayIndex(&index)) { |
| 3299 for (Object* obj = this; | 3377 for (Object* obj = this; |
| 3300 obj != Heap::null_value(); | 3378 obj != heap->null_value(); |
| 3301 obj = JSObject::cast(obj)->GetPrototype()) { | 3379 obj = JSObject::cast(obj)->GetPrototype()) { |
| 3302 JSObject* js_object = JSObject::cast(obj); | 3380 JSObject* js_object = JSObject::cast(obj); |
| 3303 if (js_object->HasDictionaryElements()) { | 3381 if (js_object->HasDictionaryElements()) { |
| 3304 NumberDictionary* dictionary = js_object->element_dictionary(); | 3382 NumberDictionary* dictionary = js_object->element_dictionary(); |
| 3305 int entry = dictionary->FindEntry(index); | 3383 int entry = dictionary->FindEntry(index); |
| 3306 if (entry != NumberDictionary::kNotFound) { | 3384 if (entry != NumberDictionary::kNotFound) { |
| 3307 Object* element = dictionary->ValueAt(entry); | 3385 Object* element = dictionary->ValueAt(entry); |
| 3308 PropertyDetails details = dictionary->DetailsAt(entry); | 3386 PropertyDetails details = dictionary->DetailsAt(entry); |
| 3309 if (details.type() == CALLBACKS) { | 3387 if (details.type() == CALLBACKS) { |
| 3310 if (element->IsFixedArray()) { | 3388 if (element->IsFixedArray()) { |
| 3311 return FixedArray::cast(element)->get(accessor_index); | 3389 return FixedArray::cast(element)->get(accessor_index); |
| 3312 } | 3390 } |
| 3313 } | 3391 } |
| 3314 } | 3392 } |
| 3315 } | 3393 } |
| 3316 } | 3394 } |
| 3317 } else { | 3395 } else { |
| 3318 for (Object* obj = this; | 3396 for (Object* obj = this; |
| 3319 obj != Heap::null_value(); | 3397 obj != heap->null_value(); |
| 3320 obj = JSObject::cast(obj)->GetPrototype()) { | 3398 obj = JSObject::cast(obj)->GetPrototype()) { |
| 3321 LookupResult result; | 3399 LookupResult result; |
| 3322 JSObject::cast(obj)->LocalLookup(name, &result); | 3400 JSObject::cast(obj)->LocalLookup(name, &result); |
| 3323 if (result.IsProperty()) { | 3401 if (result.IsProperty()) { |
| 3324 if (result.IsReadOnly()) return Heap::undefined_value(); | 3402 if (result.IsReadOnly()) return heap->undefined_value(); |
| 3325 if (result.type() == CALLBACKS) { | 3403 if (result.type() == CALLBACKS) { |
| 3326 Object* obj = result.GetCallbackObject(); | 3404 Object* obj = result.GetCallbackObject(); |
| 3327 if (obj->IsFixedArray()) { | 3405 if (obj->IsFixedArray()) { |
| 3328 return FixedArray::cast(obj)->get(accessor_index); | 3406 return FixedArray::cast(obj)->get(accessor_index); |
| 3329 } | 3407 } |
| 3330 } | 3408 } |
| 3331 } | 3409 } |
| 3332 } | 3410 } |
| 3333 } | 3411 } |
| 3334 return Heap::undefined_value(); | 3412 return heap->undefined_value(); |
| 3335 } | 3413 } |
| 3336 | 3414 |
| 3337 | 3415 |
| 3338 Object* JSObject::SlowReverseLookup(Object* value) { | 3416 Object* JSObject::SlowReverseLookup(Object* value) { |
| 3417 Heap* heap = GetHeap(); |
| 3339 if (HasFastProperties()) { | 3418 if (HasFastProperties()) { |
| 3340 DescriptorArray* descs = map()->instance_descriptors(); | 3419 DescriptorArray* descs = map()->instance_descriptors(); |
| 3341 for (int i = 0; i < descs->number_of_descriptors(); i++) { | 3420 for (int i = 0; i < descs->number_of_descriptors(); i++) { |
| 3342 if (descs->GetType(i) == FIELD) { | 3421 if (descs->GetType(i) == FIELD) { |
| 3343 if (FastPropertyAt(descs->GetFieldIndex(i)) == value) { | 3422 if (FastPropertyAt(descs->GetFieldIndex(i)) == value) { |
| 3344 return descs->GetKey(i); | 3423 return descs->GetKey(i); |
| 3345 } | 3424 } |
| 3346 } else if (descs->GetType(i) == CONSTANT_FUNCTION) { | 3425 } else if (descs->GetType(i) == CONSTANT_FUNCTION) { |
| 3347 if (descs->GetConstantFunction(i) == value) { | 3426 if (descs->GetConstantFunction(i) == value) { |
| 3348 return descs->GetKey(i); | 3427 return descs->GetKey(i); |
| 3349 } | 3428 } |
| 3350 } | 3429 } |
| 3351 } | 3430 } |
| 3352 return Heap::undefined_value(); | 3431 return heap->undefined_value(); |
| 3353 } else { | 3432 } else { |
| 3354 return property_dictionary()->SlowReverseLookup(value); | 3433 return property_dictionary()->SlowReverseLookup(value); |
| 3355 } | 3434 } |
| 3356 } | 3435 } |
| 3357 | 3436 |
| 3358 | 3437 |
| 3359 MaybeObject* Map::CopyDropDescriptors() { | 3438 MaybeObject* Map::CopyDropDescriptors() { |
| 3439 Heap* heap = GetHeap(); |
| 3360 Object* result; | 3440 Object* result; |
| 3361 { MaybeObject* maybe_result = | 3441 { MaybeObject* maybe_result = |
| 3362 Heap::AllocateMap(instance_type(), instance_size()); | 3442 heap->AllocateMap(instance_type(), instance_size()); |
| 3363 if (!maybe_result->ToObject(&result)) return maybe_result; | 3443 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 3364 } | 3444 } |
| 3365 Map::cast(result)->set_prototype(prototype()); | 3445 Map::cast(result)->set_prototype(prototype()); |
| 3366 Map::cast(result)->set_constructor(constructor()); | 3446 Map::cast(result)->set_constructor(constructor()); |
| 3367 // Don't copy descriptors, so map transitions always remain a forest. | 3447 // Don't copy descriptors, so map transitions always remain a forest. |
| 3368 // If we retained the same descriptors we would have two maps | 3448 // If we retained the same descriptors we would have two maps |
| 3369 // pointing to the same transition which is bad because the garbage | 3449 // pointing to the same transition which is bad because the garbage |
| 3370 // collector relies on being able to reverse pointers from transitions | 3450 // collector relies on being able to reverse pointers from transitions |
| 3371 // to maps. If properties need to be retained use CopyDropTransitions. | 3451 // to maps. If properties need to be retained use CopyDropTransitions. |
| 3372 Map::cast(result)->set_instance_descriptors(Heap::empty_descriptor_array()); | 3452 Map::cast(result)->set_instance_descriptors( |
| 3453 heap->empty_descriptor_array()); |
| 3373 // Please note instance_type and instance_size are set when allocated. | 3454 // Please note instance_type and instance_size are set when allocated. |
| 3374 Map::cast(result)->set_inobject_properties(inobject_properties()); | 3455 Map::cast(result)->set_inobject_properties(inobject_properties()); |
| 3375 Map::cast(result)->set_unused_property_fields(unused_property_fields()); | 3456 Map::cast(result)->set_unused_property_fields(unused_property_fields()); |
| 3376 | 3457 |
| 3377 // If the map has pre-allocated properties always start out with a descriptor | 3458 // If the map has pre-allocated properties always start out with a descriptor |
| 3378 // array describing these properties. | 3459 // array describing these properties. |
| 3379 if (pre_allocated_property_fields() > 0) { | 3460 if (pre_allocated_property_fields() > 0) { |
| 3380 ASSERT(constructor()->IsJSFunction()); | 3461 ASSERT(constructor()->IsJSFunction()); |
| 3381 JSFunction* ctor = JSFunction::cast(constructor()); | 3462 JSFunction* ctor = JSFunction::cast(constructor()); |
| 3382 Object* descriptors; | 3463 Object* descriptors; |
| 3383 { MaybeObject* maybe_descriptors = | 3464 { MaybeObject* maybe_descriptors = |
| 3384 ctor->initial_map()->instance_descriptors()->RemoveTransitions(); | 3465 ctor->initial_map()->instance_descriptors()->RemoveTransitions(); |
| 3385 if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors; | 3466 if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors; |
| 3386 } | 3467 } |
| 3387 Map::cast(result)->set_instance_descriptors( | 3468 Map::cast(result)->set_instance_descriptors( |
| 3388 DescriptorArray::cast(descriptors)); | 3469 DescriptorArray::cast(descriptors)); |
| 3389 Map::cast(result)->set_pre_allocated_property_fields( | 3470 Map::cast(result)->set_pre_allocated_property_fields( |
| 3390 pre_allocated_property_fields()); | 3471 pre_allocated_property_fields()); |
| 3391 } | 3472 } |
| 3392 Map::cast(result)->set_bit_field(bit_field()); | 3473 Map::cast(result)->set_bit_field(bit_field()); |
| 3393 Map::cast(result)->set_bit_field2(bit_field2()); | 3474 Map::cast(result)->set_bit_field2(bit_field2()); |
| 3394 Map::cast(result)->set_is_shared(false); | 3475 Map::cast(result)->set_is_shared(false); |
| 3395 Map::cast(result)->ClearCodeCache(); | 3476 Map::cast(result)->ClearCodeCache(heap); |
| 3396 return result; | 3477 return result; |
| 3397 } | 3478 } |
| 3398 | 3479 |
| 3399 | 3480 |
| 3400 MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode, | 3481 MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode, |
| 3401 NormalizedMapSharingMode sharing) { | 3482 NormalizedMapSharingMode sharing) { |
| 3402 int new_instance_size = instance_size(); | 3483 int new_instance_size = instance_size(); |
| 3403 if (mode == CLEAR_INOBJECT_PROPERTIES) { | 3484 if (mode == CLEAR_INOBJECT_PROPERTIES) { |
| 3404 new_instance_size -= inobject_properties() * kPointerSize; | 3485 new_instance_size -= inobject_properties() * kPointerSize; |
| 3405 } | 3486 } |
| 3406 | 3487 |
| 3407 Object* result; | 3488 Object* result; |
| 3408 { MaybeObject* maybe_result = | 3489 { MaybeObject* maybe_result = |
| 3409 Heap::AllocateMap(instance_type(), new_instance_size); | 3490 GetHeap()->AllocateMap(instance_type(), new_instance_size); |
| 3410 if (!maybe_result->ToObject(&result)) return maybe_result; | 3491 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 3411 } | 3492 } |
| 3412 | 3493 |
| 3413 if (mode != CLEAR_INOBJECT_PROPERTIES) { | 3494 if (mode != CLEAR_INOBJECT_PROPERTIES) { |
| 3414 Map::cast(result)->set_inobject_properties(inobject_properties()); | 3495 Map::cast(result)->set_inobject_properties(inobject_properties()); |
| 3415 } | 3496 } |
| 3416 | 3497 |
| 3417 Map::cast(result)->set_prototype(prototype()); | 3498 Map::cast(result)->set_prototype(prototype()); |
| 3418 Map::cast(result)->set_constructor(constructor()); | 3499 Map::cast(result)->set_constructor(constructor()); |
| 3419 | 3500 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 3444 } | 3525 } |
| 3445 cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors)); | 3526 cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors)); |
| 3446 return new_map; | 3527 return new_map; |
| 3447 } | 3528 } |
| 3448 | 3529 |
| 3449 | 3530 |
| 3450 MaybeObject* Map::UpdateCodeCache(String* name, Code* code) { | 3531 MaybeObject* Map::UpdateCodeCache(String* name, Code* code) { |
| 3451 // Allocate the code cache if not present. | 3532 // Allocate the code cache if not present. |
| 3452 if (code_cache()->IsFixedArray()) { | 3533 if (code_cache()->IsFixedArray()) { |
| 3453 Object* result; | 3534 Object* result; |
| 3454 { MaybeObject* maybe_result = Heap::AllocateCodeCache(); | 3535 { MaybeObject* maybe_result = GetHeap()->AllocateCodeCache(); |
| 3455 if (!maybe_result->ToObject(&result)) return maybe_result; | 3536 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 3456 } | 3537 } |
| 3457 set_code_cache(result); | 3538 set_code_cache(result); |
| 3458 } | 3539 } |
| 3459 | 3540 |
| 3460 // Update the code cache. | 3541 // Update the code cache. |
| 3461 return CodeCache::cast(code_cache())->Update(name, code); | 3542 return CodeCache::cast(code_cache())->Update(name, code); |
| 3462 } | 3543 } |
| 3463 | 3544 |
| 3464 | 3545 |
| 3465 Object* Map::FindInCodeCache(String* name, Code::Flags flags) { | 3546 Object* Map::FindInCodeCache(String* name, Code::Flags flags) { |
| 3466 // Do a lookup if a code cache exists. | 3547 // Do a lookup if a code cache exists. |
| 3467 if (!code_cache()->IsFixedArray()) { | 3548 if (!code_cache()->IsFixedArray()) { |
| 3468 return CodeCache::cast(code_cache())->Lookup(name, flags); | 3549 return CodeCache::cast(code_cache())->Lookup(name, flags); |
| 3469 } else { | 3550 } else { |
| 3470 return Heap::undefined_value(); | 3551 return GetHeap()->undefined_value(); |
| 3471 } | 3552 } |
| 3472 } | 3553 } |
| 3473 | 3554 |
| 3474 | 3555 |
| 3475 int Map::IndexInCodeCache(Object* name, Code* code) { | 3556 int Map::IndexInCodeCache(Object* name, Code* code) { |
| 3476 // Get the internal index if a code cache exists. | 3557 // Get the internal index if a code cache exists. |
| 3477 if (!code_cache()->IsFixedArray()) { | 3558 if (!code_cache()->IsFixedArray()) { |
| 3478 return CodeCache::cast(code_cache())->GetIndex(name, code); | 3559 return CodeCache::cast(code_cache())->GetIndex(name, code); |
| 3479 } | 3560 } |
| 3480 return -1; | 3561 return -1; |
| 3481 } | 3562 } |
| 3482 | 3563 |
| 3483 | 3564 |
| 3484 void Map::RemoveFromCodeCache(String* name, Code* code, int index) { | 3565 void Map::RemoveFromCodeCache(String* name, Code* code, int index) { |
| 3485 // No GC is supposed to happen between a call to IndexInCodeCache and | 3566 // No GC is supposed to happen between a call to IndexInCodeCache and |
| 3486 // RemoveFromCodeCache so the code cache must be there. | 3567 // RemoveFromCodeCache so the code cache must be there. |
| 3487 ASSERT(!code_cache()->IsFixedArray()); | 3568 ASSERT(!code_cache()->IsFixedArray()); |
| 3488 CodeCache::cast(code_cache())->RemoveByIndex(name, code, index); | 3569 CodeCache::cast(code_cache())->RemoveByIndex(name, code, index); |
| 3489 } | 3570 } |
| 3490 | 3571 |
| 3491 | 3572 |
| 3492 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) { | 3573 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) { |
| 3493 Map* current = this; | 3574 Map* current = this; |
| 3494 while (current != Heap::meta_map()) { | 3575 Map* meta_map = heap()->meta_map(); |
| 3576 while (current != meta_map) { |
| 3495 DescriptorArray* d = reinterpret_cast<DescriptorArray*>( | 3577 DescriptorArray* d = reinterpret_cast<DescriptorArray*>( |
| 3496 *RawField(current, Map::kInstanceDescriptorsOffset)); | 3578 *RawField(current, Map::kInstanceDescriptorsOffset)); |
| 3497 if (d == Heap::empty_descriptor_array()) { | 3579 if (d == heap()->empty_descriptor_array()) { |
| 3498 Map* prev = current->map(); | 3580 Map* prev = current->map(); |
| 3499 current->set_map(Heap::meta_map()); | 3581 current->set_map(meta_map); |
| 3500 callback(current, data); | 3582 callback(current, data); |
| 3501 current = prev; | 3583 current = prev; |
| 3502 continue; | 3584 continue; |
| 3503 } | 3585 } |
| 3504 | 3586 |
| 3505 FixedArray* contents = reinterpret_cast<FixedArray*>( | 3587 FixedArray* contents = reinterpret_cast<FixedArray*>( |
| 3506 d->get(DescriptorArray::kContentArrayIndex)); | 3588 d->get(DescriptorArray::kContentArrayIndex)); |
| 3507 Object** map_or_index_field = RawField(contents, HeapObject::kMapOffset); | 3589 Object** map_or_index_field = RawField(contents, HeapObject::kMapOffset); |
| 3508 Object* map_or_index = *map_or_index_field; | 3590 Object* map_or_index = *map_or_index_field; |
| 3509 bool map_done = true; | 3591 bool map_done = true; |
| 3510 for (int i = map_or_index->IsSmi() ? Smi::cast(map_or_index)->value() : 0; | 3592 for (int i = map_or_index->IsSmi() ? Smi::cast(map_or_index)->value() : 0; |
| 3511 i < contents->length(); | 3593 i < contents->length(); |
| 3512 i += 2) { | 3594 i += 2) { |
| 3513 PropertyDetails details(Smi::cast(contents->get(i + 1))); | 3595 PropertyDetails details(Smi::cast(contents->get(i + 1))); |
| 3514 if (details.IsTransition()) { | 3596 if (details.IsTransition()) { |
| 3515 Map* next = reinterpret_cast<Map*>(contents->get(i)); | 3597 Map* next = reinterpret_cast<Map*>(contents->get(i)); |
| 3516 next->set_map(current); | 3598 next->set_map(current); |
| 3517 *map_or_index_field = Smi::FromInt(i + 2); | 3599 *map_or_index_field = Smi::FromInt(i + 2); |
| 3518 current = next; | 3600 current = next; |
| 3519 map_done = false; | 3601 map_done = false; |
| 3520 break; | 3602 break; |
| 3521 } | 3603 } |
| 3522 } | 3604 } |
| 3523 if (!map_done) continue; | 3605 if (!map_done) continue; |
| 3524 *map_or_index_field = Heap::fixed_array_map(); | 3606 *map_or_index_field = heap()->fixed_array_map(); |
| 3525 Map* prev = current->map(); | 3607 Map* prev = current->map(); |
| 3526 current->set_map(Heap::meta_map()); | 3608 current->set_map(meta_map); |
| 3527 callback(current, data); | 3609 callback(current, data); |
| 3528 current = prev; | 3610 current = prev; |
| 3529 } | 3611 } |
| 3530 } | 3612 } |
| 3531 | 3613 |
| 3532 | 3614 |
| 3533 MaybeObject* CodeCache::Update(String* name, Code* code) { | 3615 MaybeObject* CodeCache::Update(String* name, Code* code) { |
| 3534 ASSERT(code->ic_state() == MONOMORPHIC); | 3616 ASSERT(code->ic_state() == MONOMORPHIC); |
| 3535 | 3617 |
| 3536 // The number of monomorphic stubs for normal load/store/call IC's can grow to | 3618 // The number of monomorphic stubs for normal load/store/call IC's can grow to |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3629 Object* CodeCache::Lookup(String* name, Code::Flags flags) { | 3711 Object* CodeCache::Lookup(String* name, Code::Flags flags) { |
| 3630 if (Code::ExtractTypeFromFlags(flags) == NORMAL) { | 3712 if (Code::ExtractTypeFromFlags(flags) == NORMAL) { |
| 3631 return LookupNormalTypeCache(name, flags); | 3713 return LookupNormalTypeCache(name, flags); |
| 3632 } else { | 3714 } else { |
| 3633 return LookupDefaultCache(name, flags); | 3715 return LookupDefaultCache(name, flags); |
| 3634 } | 3716 } |
| 3635 } | 3717 } |
| 3636 | 3718 |
| 3637 | 3719 |
| 3638 Object* CodeCache::LookupDefaultCache(String* name, Code::Flags flags) { | 3720 Object* CodeCache::LookupDefaultCache(String* name, Code::Flags flags) { |
| 3721 Heap* heap = GetHeap(); |
| 3639 FixedArray* cache = default_cache(); | 3722 FixedArray* cache = default_cache(); |
| 3640 int length = cache->length(); | 3723 int length = cache->length(); |
| 3641 for (int i = 0; i < length; i += kCodeCacheEntrySize) { | 3724 for (int i = 0; i < length; i += kCodeCacheEntrySize) { |
| 3642 Object* key = cache->get(i + kCodeCacheEntryNameOffset); | 3725 Object* key = cache->get(i + kCodeCacheEntryNameOffset); |
| 3643 // Skip deleted elements. | 3726 // Skip deleted elements. |
| 3644 if (key->IsNull()) continue; | 3727 if (key->IsNull()) continue; |
| 3645 if (key->IsUndefined()) return key; | 3728 if (key->IsUndefined()) return key; |
| 3646 if (name->Equals(String::cast(key))) { | 3729 if (name->Equals(String::cast(key))) { |
| 3647 Code* code = Code::cast(cache->get(i + kCodeCacheEntryCodeOffset)); | 3730 Code* code = Code::cast(cache->get(i + kCodeCacheEntryCodeOffset)); |
| 3648 if (code->flags() == flags) { | 3731 if (code->flags() == flags) { |
| 3649 return code; | 3732 return code; |
| 3650 } | 3733 } |
| 3651 } | 3734 } |
| 3652 } | 3735 } |
| 3653 return Heap::undefined_value(); | 3736 return heap->undefined_value(); |
| 3654 } | 3737 } |
| 3655 | 3738 |
| 3656 | 3739 |
| 3657 Object* CodeCache::LookupNormalTypeCache(String* name, Code::Flags flags) { | 3740 Object* CodeCache::LookupNormalTypeCache(String* name, Code::Flags flags) { |
| 3658 if (!normal_type_cache()->IsUndefined()) { | 3741 if (!normal_type_cache()->IsUndefined()) { |
| 3659 CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache()); | 3742 CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache()); |
| 3660 return cache->Lookup(name, flags); | 3743 return cache->Lookup(name, flags); |
| 3661 } else { | 3744 } else { |
| 3662 return Heap::undefined_value(); | 3745 return GetHeap()->undefined_value(); |
| 3663 } | 3746 } |
| 3664 } | 3747 } |
| 3665 | 3748 |
| 3666 | 3749 |
| 3667 int CodeCache::GetIndex(Object* name, Code* code) { | 3750 int CodeCache::GetIndex(Object* name, Code* code) { |
| 3668 if (code->type() == NORMAL) { | 3751 if (code->type() == NORMAL) { |
| 3669 if (normal_type_cache()->IsUndefined()) return -1; | 3752 if (normal_type_cache()->IsUndefined()) return -1; |
| 3670 CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache()); | 3753 CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache()); |
| 3671 return cache->GetIndex(String::cast(name), code->flags()); | 3754 return cache->GetIndex(String::cast(name), code->flags()); |
| 3672 } | 3755 } |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3734 uint32_t HashForObject(Object* obj) { | 3817 uint32_t HashForObject(Object* obj) { |
| 3735 FixedArray* pair = FixedArray::cast(obj); | 3818 FixedArray* pair = FixedArray::cast(obj); |
| 3736 String* name = String::cast(pair->get(0)); | 3819 String* name = String::cast(pair->get(0)); |
| 3737 Code* code = Code::cast(pair->get(1)); | 3820 Code* code = Code::cast(pair->get(1)); |
| 3738 return NameFlagsHashHelper(name, code->flags()); | 3821 return NameFlagsHashHelper(name, code->flags()); |
| 3739 } | 3822 } |
| 3740 | 3823 |
| 3741 MUST_USE_RESULT MaybeObject* AsObject() { | 3824 MUST_USE_RESULT MaybeObject* AsObject() { |
| 3742 ASSERT(code_ != NULL); | 3825 ASSERT(code_ != NULL); |
| 3743 Object* obj; | 3826 Object* obj; |
| 3744 { MaybeObject* maybe_obj = Heap::AllocateFixedArray(2); | 3827 { MaybeObject* maybe_obj = code_->GetHeap()->AllocateFixedArray(2); |
| 3745 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 3828 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 3746 } | 3829 } |
| 3747 FixedArray* pair = FixedArray::cast(obj); | 3830 FixedArray* pair = FixedArray::cast(obj); |
| 3748 pair->set(0, name_); | 3831 pair->set(0, name_); |
| 3749 pair->set(1, code_); | 3832 pair->set(1, code_); |
| 3750 return pair; | 3833 return pair; |
| 3751 } | 3834 } |
| 3752 | 3835 |
| 3753 private: | 3836 private: |
| 3754 String* name_; | 3837 String* name_; |
| 3755 Code::Flags flags_; | 3838 Code::Flags flags_; |
| 3756 Code* code_; | 3839 Code* code_; |
| 3757 }; | 3840 }; |
| 3758 | 3841 |
| 3759 | 3842 |
| 3760 Object* CodeCacheHashTable::Lookup(String* name, Code::Flags flags) { | 3843 Object* CodeCacheHashTable::Lookup(String* name, Code::Flags flags) { |
| 3761 CodeCacheHashTableKey key(name, flags); | 3844 CodeCacheHashTableKey key(name, flags); |
| 3762 int entry = FindEntry(&key); | 3845 int entry = FindEntry(&key); |
| 3763 if (entry == kNotFound) return Heap::undefined_value(); | 3846 if (entry == kNotFound) return GetHeap()->undefined_value(); |
| 3764 return get(EntryToIndex(entry) + 1); | 3847 return get(EntryToIndex(entry) + 1); |
| 3765 } | 3848 } |
| 3766 | 3849 |
| 3767 | 3850 |
| 3768 MaybeObject* CodeCacheHashTable::Put(String* name, Code* code) { | 3851 MaybeObject* CodeCacheHashTable::Put(String* name, Code* code) { |
| 3769 CodeCacheHashTableKey key(name, code); | 3852 CodeCacheHashTableKey key(name, code); |
| 3770 Object* obj; | 3853 Object* obj; |
| 3771 { MaybeObject* maybe_obj = EnsureCapacity(1, &key); | 3854 { MaybeObject* maybe_obj = EnsureCapacity(1, &key); |
| 3772 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 3855 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 3773 } | 3856 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 3790 | 3873 |
| 3791 int CodeCacheHashTable::GetIndex(String* name, Code::Flags flags) { | 3874 int CodeCacheHashTable::GetIndex(String* name, Code::Flags flags) { |
| 3792 CodeCacheHashTableKey key(name, flags); | 3875 CodeCacheHashTableKey key(name, flags); |
| 3793 int entry = FindEntry(&key); | 3876 int entry = FindEntry(&key); |
| 3794 return (entry == kNotFound) ? -1 : entry; | 3877 return (entry == kNotFound) ? -1 : entry; |
| 3795 } | 3878 } |
| 3796 | 3879 |
| 3797 | 3880 |
| 3798 void CodeCacheHashTable::RemoveByIndex(int index) { | 3881 void CodeCacheHashTable::RemoveByIndex(int index) { |
| 3799 ASSERT(index >= 0); | 3882 ASSERT(index >= 0); |
| 3800 set(EntryToIndex(index), Heap::null_value()); | 3883 Heap* heap = GetHeap(); |
| 3801 set(EntryToIndex(index) + 1, Heap::null_value()); | 3884 set(EntryToIndex(index), heap->null_value()); |
| 3885 set(EntryToIndex(index) + 1, heap->null_value()); |
| 3802 ElementRemoved(); | 3886 ElementRemoved(); |
| 3803 } | 3887 } |
| 3804 | 3888 |
| 3805 | 3889 |
| 3806 static bool HasKey(FixedArray* array, Object* key) { | 3890 static bool HasKey(FixedArray* array, Object* key) { |
| 3807 int len0 = array->length(); | 3891 int len0 = array->length(); |
| 3808 for (int i = 0; i < len0; i++) { | 3892 for (int i = 0; i < len0; i++) { |
| 3809 Object* element = array->get(i); | 3893 Object* element = array->get(i); |
| 3810 if (element->IsSmi() && key->IsSmi() && (element == key)) return true; | 3894 if (element->IsSmi() && key->IsSmi() && (element == key)) return true; |
| 3811 if (element->IsString() && | 3895 if (element->IsString() && |
| 3812 key->IsString() && String::cast(element)->Equals(String::cast(key))) { | 3896 key->IsString() && String::cast(element)->Equals(String::cast(key))) { |
| 3813 return true; | 3897 return true; |
| 3814 } | 3898 } |
| 3815 } | 3899 } |
| 3816 return false; | 3900 return false; |
| 3817 } | 3901 } |
| 3818 | 3902 |
| 3819 | 3903 |
| 3820 MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) { | 3904 MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) { |
| 3905 Heap* heap = GetHeap(); |
| 3821 ASSERT(!array->HasExternalArrayElements()); | 3906 ASSERT(!array->HasExternalArrayElements()); |
| 3822 switch (array->GetElementsKind()) { | 3907 switch (array->GetElementsKind()) { |
| 3823 case JSObject::FAST_ELEMENTS: | 3908 case JSObject::FAST_ELEMENTS: |
| 3824 return UnionOfKeys(FixedArray::cast(array->elements())); | 3909 return UnionOfKeys(FixedArray::cast(array->elements())); |
| 3825 case JSObject::DICTIONARY_ELEMENTS: { | 3910 case JSObject::DICTIONARY_ELEMENTS: { |
| 3826 NumberDictionary* dict = array->element_dictionary(); | 3911 NumberDictionary* dict = array->element_dictionary(); |
| 3827 int size = dict->NumberOfElements(); | 3912 int size = dict->NumberOfElements(); |
| 3828 | 3913 |
| 3829 // Allocate a temporary fixed array. | 3914 // Allocate a temporary fixed array. |
| 3830 Object* object; | 3915 Object* object; |
| 3831 { MaybeObject* maybe_object = Heap::AllocateFixedArray(size); | 3916 { MaybeObject* maybe_object = heap->AllocateFixedArray(size); |
| 3832 if (!maybe_object->ToObject(&object)) return maybe_object; | 3917 if (!maybe_object->ToObject(&object)) return maybe_object; |
| 3833 } | 3918 } |
| 3834 FixedArray* key_array = FixedArray::cast(object); | 3919 FixedArray* key_array = FixedArray::cast(object); |
| 3835 | 3920 |
| 3836 int capacity = dict->Capacity(); | 3921 int capacity = dict->Capacity(); |
| 3837 int pos = 0; | 3922 int pos = 0; |
| 3838 // Copy the elements from the JSArray to the temporary fixed array. | 3923 // Copy the elements from the JSArray to the temporary fixed array. |
| 3839 for (int i = 0; i < capacity; i++) { | 3924 for (int i = 0; i < capacity; i++) { |
| 3840 if (dict->IsKey(dict->KeyAt(i))) { | 3925 if (dict->IsKey(dict->KeyAt(i))) { |
| 3841 key_array->set(pos++, dict->ValueAt(i)); | 3926 key_array->set(pos++, dict->ValueAt(i)); |
| 3842 } | 3927 } |
| 3843 } | 3928 } |
| 3844 // Compute the union of this and the temporary fixed array. | 3929 // Compute the union of this and the temporary fixed array. |
| 3845 return UnionOfKeys(key_array); | 3930 return UnionOfKeys(key_array); |
| 3846 } | 3931 } |
| 3847 default: | 3932 default: |
| 3848 UNREACHABLE(); | 3933 UNREACHABLE(); |
| 3849 } | 3934 } |
| 3850 UNREACHABLE(); | 3935 UNREACHABLE(); |
| 3851 return Heap::null_value(); // Failure case needs to "return" a value. | 3936 return heap->null_value(); // Failure case needs to "return" a value. |
| 3852 } | 3937 } |
| 3853 | 3938 |
| 3854 | 3939 |
| 3855 MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) { | 3940 MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) { |
| 3941 Heap* heap = GetHeap(); |
| 3856 int len0 = length(); | 3942 int len0 = length(); |
| 3857 #ifdef DEBUG | 3943 #ifdef DEBUG |
| 3858 if (FLAG_enable_slow_asserts) { | 3944 if (FLAG_enable_slow_asserts) { |
| 3859 for (int i = 0; i < len0; i++) { | 3945 for (int i = 0; i < len0; i++) { |
| 3860 ASSERT(get(i)->IsString() || get(i)->IsNumber()); | 3946 ASSERT(get(i)->IsString() || get(i)->IsNumber()); |
| 3861 } | 3947 } |
| 3862 } | 3948 } |
| 3863 #endif | 3949 #endif |
| 3864 int len1 = other->length(); | 3950 int len1 = other->length(); |
| 3865 // Optimize if 'other' is empty. | 3951 // Optimize if 'other' is empty. |
| 3866 // We cannot optimize if 'this' is empty, as other may have holes | 3952 // We cannot optimize if 'this' is empty, as other may have holes |
| 3867 // or non keys. | 3953 // or non keys. |
| 3868 if (len1 == 0) return this; | 3954 if (len1 == 0) return this; |
| 3869 | 3955 |
| 3870 // Compute how many elements are not in this. | 3956 // Compute how many elements are not in this. |
| 3871 int extra = 0; | 3957 int extra = 0; |
| 3872 for (int y = 0; y < len1; y++) { | 3958 for (int y = 0; y < len1; y++) { |
| 3873 Object* value = other->get(y); | 3959 Object* value = other->get(y); |
| 3874 if (!value->IsTheHole() && !HasKey(this, value)) extra++; | 3960 if (!value->IsTheHole() && !HasKey(this, value)) extra++; |
| 3875 } | 3961 } |
| 3876 | 3962 |
| 3877 if (extra == 0) return this; | 3963 if (extra == 0) return this; |
| 3878 | 3964 |
| 3879 // Allocate the result | 3965 // Allocate the result |
| 3880 Object* obj; | 3966 Object* obj; |
| 3881 { MaybeObject* maybe_obj = Heap::AllocateFixedArray(len0 + extra); | 3967 { MaybeObject* maybe_obj = heap->AllocateFixedArray(len0 + extra); |
| 3882 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 3968 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 3883 } | 3969 } |
| 3884 // Fill in the content | 3970 // Fill in the content |
| 3885 AssertNoAllocation no_gc; | 3971 AssertNoAllocation no_gc; |
| 3886 FixedArray* result = FixedArray::cast(obj); | 3972 FixedArray* result = FixedArray::cast(obj); |
| 3887 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); | 3973 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); |
| 3888 for (int i = 0; i < len0; i++) { | 3974 for (int i = 0; i < len0; i++) { |
| 3889 Object* e = get(i); | 3975 Object* e = get(i); |
| 3890 ASSERT(e->IsString() || e->IsNumber()); | 3976 ASSERT(e->IsString() || e->IsNumber()); |
| 3891 result->set(i, e, mode); | 3977 result->set(i, e, mode); |
| 3892 } | 3978 } |
| 3893 // Fill in the extra keys. | 3979 // Fill in the extra keys. |
| 3894 int index = 0; | 3980 int index = 0; |
| 3895 for (int y = 0; y < len1; y++) { | 3981 for (int y = 0; y < len1; y++) { |
| 3896 Object* value = other->get(y); | 3982 Object* value = other->get(y); |
| 3897 if (!value->IsTheHole() && !HasKey(this, value)) { | 3983 if (!value->IsTheHole() && !HasKey(this, value)) { |
| 3898 Object* e = other->get(y); | 3984 Object* e = other->get(y); |
| 3899 ASSERT(e->IsString() || e->IsNumber()); | 3985 ASSERT(e->IsString() || e->IsNumber()); |
| 3900 result->set(len0 + index, e, mode); | 3986 result->set(len0 + index, e, mode); |
| 3901 index++; | 3987 index++; |
| 3902 } | 3988 } |
| 3903 } | 3989 } |
| 3904 ASSERT(extra == index); | 3990 ASSERT(extra == index); |
| 3905 return result; | 3991 return result; |
| 3906 } | 3992 } |
| 3907 | 3993 |
| 3908 | 3994 |
| 3909 MaybeObject* FixedArray::CopySize(int new_length) { | 3995 MaybeObject* FixedArray::CopySize(int new_length) { |
| 3910 if (new_length == 0) return Heap::empty_fixed_array(); | 3996 Heap* heap = GetHeap(); |
| 3997 if (new_length == 0) return heap->empty_fixed_array(); |
| 3911 Object* obj; | 3998 Object* obj; |
| 3912 { MaybeObject* maybe_obj = Heap::AllocateFixedArray(new_length); | 3999 { MaybeObject* maybe_obj = heap->AllocateFixedArray(new_length); |
| 3913 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 4000 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 3914 } | 4001 } |
| 3915 FixedArray* result = FixedArray::cast(obj); | 4002 FixedArray* result = FixedArray::cast(obj); |
| 3916 // Copy the content | 4003 // Copy the content |
| 3917 AssertNoAllocation no_gc; | 4004 AssertNoAllocation no_gc; |
| 3918 int len = length(); | 4005 int len = length(); |
| 3919 if (new_length < len) len = new_length; | 4006 if (new_length < len) len = new_length; |
| 3920 result->set_map(map()); | 4007 result->set_map(map()); |
| 3921 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); | 4008 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); |
| 3922 for (int i = 0; i < len; i++) { | 4009 for (int i = 0; i < len; i++) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 3940 if (length() != other->length()) return false; | 4027 if (length() != other->length()) return false; |
| 3941 for (int i = 0 ; i < length(); ++i) { | 4028 for (int i = 0 ; i < length(); ++i) { |
| 3942 if (get(i) != other->get(i)) return false; | 4029 if (get(i) != other->get(i)) return false; |
| 3943 } | 4030 } |
| 3944 return true; | 4031 return true; |
| 3945 } | 4032 } |
| 3946 #endif | 4033 #endif |
| 3947 | 4034 |
| 3948 | 4035 |
| 3949 MaybeObject* DescriptorArray::Allocate(int number_of_descriptors) { | 4036 MaybeObject* DescriptorArray::Allocate(int number_of_descriptors) { |
| 4037 Heap* heap = Isolate::Current()->heap(); |
| 3950 if (number_of_descriptors == 0) { | 4038 if (number_of_descriptors == 0) { |
| 3951 return Heap::empty_descriptor_array(); | 4039 return heap->empty_descriptor_array(); |
| 3952 } | 4040 } |
| 3953 // Allocate the array of keys. | 4041 // Allocate the array of keys. |
| 3954 Object* array; | 4042 Object* array; |
| 3955 { MaybeObject* maybe_array = | 4043 { MaybeObject* maybe_array = |
| 3956 Heap::AllocateFixedArray(ToKeyIndex(number_of_descriptors)); | 4044 heap->AllocateFixedArray(ToKeyIndex(number_of_descriptors)); |
| 3957 if (!maybe_array->ToObject(&array)) return maybe_array; | 4045 if (!maybe_array->ToObject(&array)) return maybe_array; |
| 3958 } | 4046 } |
| 3959 // Do not use DescriptorArray::cast on incomplete object. | 4047 // Do not use DescriptorArray::cast on incomplete object. |
| 3960 FixedArray* result = FixedArray::cast(array); | 4048 FixedArray* result = FixedArray::cast(array); |
| 3961 | 4049 |
| 3962 // Allocate the content array and set it in the descriptor array. | 4050 // Allocate the content array and set it in the descriptor array. |
| 3963 { MaybeObject* maybe_array = | 4051 { MaybeObject* maybe_array = |
| 3964 Heap::AllocateFixedArray(number_of_descriptors << 1); | 4052 heap->AllocateFixedArray(number_of_descriptors << 1); |
| 3965 if (!maybe_array->ToObject(&array)) return maybe_array; | 4053 if (!maybe_array->ToObject(&array)) return maybe_array; |
| 3966 } | 4054 } |
| 3967 result->set(kContentArrayIndex, array); | 4055 result->set(kContentArrayIndex, array); |
| 3968 result->set(kEnumerationIndexIndex, | 4056 result->set(kEnumerationIndexIndex, |
| 3969 Smi::FromInt(PropertyDetails::kInitialIndex)); | 4057 Smi::FromInt(PropertyDetails::kInitialIndex)); |
| 3970 return result; | 4058 return result; |
| 3971 } | 4059 } |
| 3972 | 4060 |
| 3973 | 4061 |
| 3974 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, | 4062 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4223 return number; | 4311 return number; |
| 4224 } | 4312 } |
| 4225 } | 4313 } |
| 4226 return kNotFound; | 4314 return kNotFound; |
| 4227 } | 4315 } |
| 4228 | 4316 |
| 4229 | 4317 |
| 4230 MaybeObject* DeoptimizationInputData::Allocate(int deopt_entry_count, | 4318 MaybeObject* DeoptimizationInputData::Allocate(int deopt_entry_count, |
| 4231 PretenureFlag pretenure) { | 4319 PretenureFlag pretenure) { |
| 4232 ASSERT(deopt_entry_count > 0); | 4320 ASSERT(deopt_entry_count > 0); |
| 4233 return Heap::AllocateFixedArray(LengthFor(deopt_entry_count), | 4321 return HEAP->AllocateFixedArray(LengthFor(deopt_entry_count), |
| 4234 pretenure); | 4322 pretenure); |
| 4235 } | 4323 } |
| 4236 | 4324 |
| 4237 | 4325 |
| 4238 MaybeObject* DeoptimizationOutputData::Allocate(int number_of_deopt_points, | 4326 MaybeObject* DeoptimizationOutputData::Allocate(int number_of_deopt_points, |
| 4239 PretenureFlag pretenure) { | 4327 PretenureFlag pretenure) { |
| 4240 if (number_of_deopt_points == 0) return Heap::empty_fixed_array(); | 4328 if (number_of_deopt_points == 0) return HEAP->empty_fixed_array(); |
| 4241 return Heap::AllocateFixedArray(LengthOfFixedArray(number_of_deopt_points), | 4329 return HEAP->AllocateFixedArray(LengthOfFixedArray(number_of_deopt_points), |
| 4242 pretenure); | 4330 pretenure); |
| 4243 } | 4331 } |
| 4244 | 4332 |
| 4245 | 4333 |
| 4246 #ifdef DEBUG | 4334 #ifdef DEBUG |
| 4247 bool DescriptorArray::IsEqualTo(DescriptorArray* other) { | 4335 bool DescriptorArray::IsEqualTo(DescriptorArray* other) { |
| 4248 if (IsEmpty()) return other->IsEmpty(); | 4336 if (IsEmpty()) return other->IsEmpty(); |
| 4249 if (other->IsEmpty()) return false; | 4337 if (other->IsEmpty()) return false; |
| 4250 if (length() != other->length()) return false; | 4338 if (length() != other->length()) return false; |
| 4251 for (int i = 0; i < length(); ++i) { | 4339 for (int i = 0; i < length(); ++i) { |
| 4252 if (get(i) != other->get(i) && i != kContentArrayIndex) return false; | 4340 if (get(i) != other->get(i) && i != kContentArrayIndex) return false; |
| 4253 } | 4341 } |
| 4254 return GetContentArray()->IsEqualTo(other->GetContentArray()); | 4342 return GetContentArray()->IsEqualTo(other->GetContentArray()); |
| 4255 } | 4343 } |
| 4256 #endif | 4344 #endif |
| 4257 | 4345 |
| 4258 | 4346 |
| 4259 static StaticResource<StringInputBuffer> string_input_buffer; | |
| 4260 | |
| 4261 | |
| 4262 bool String::LooksValid() { | 4347 bool String::LooksValid() { |
| 4263 if (!Heap::Contains(this)) return false; | 4348 if (!Isolate::Current()->heap()->Contains(this)) return false; |
| 4264 return true; | 4349 return true; |
| 4265 } | 4350 } |
| 4266 | 4351 |
| 4267 | 4352 |
| 4268 int String::Utf8Length() { | 4353 int String::Utf8Length() { |
| 4269 if (IsAsciiRepresentation()) return length(); | 4354 if (IsAsciiRepresentation()) return length(); |
| 4270 // Attempt to flatten before accessing the string. It probably | 4355 // Attempt to flatten before accessing the string. It probably |
| 4271 // doesn't make Utf8Length faster, but it is very likely that | 4356 // doesn't make Utf8Length faster, but it is very likely that |
| 4272 // the string will be accessed later (for example by WriteUtf8) | 4357 // the string will be accessed later (for example by WriteUtf8) |
| 4273 // so it's still a good idea. | 4358 // so it's still a good idea. |
| 4359 Heap* heap = GetHeap(); |
| 4274 TryFlatten(); | 4360 TryFlatten(); |
| 4275 Access<StringInputBuffer> buffer(&string_input_buffer); | 4361 Access<StringInputBuffer> buffer( |
| 4362 heap->isolate()->objects_string_input_buffer()); |
| 4276 buffer->Reset(0, this); | 4363 buffer->Reset(0, this); |
| 4277 int result = 0; | 4364 int result = 0; |
| 4278 while (buffer->has_more()) | 4365 while (buffer->has_more()) |
| 4279 result += unibrow::Utf8::Length(buffer->GetNext()); | 4366 result += unibrow::Utf8::Length(buffer->GetNext()); |
| 4280 return result; | 4367 return result; |
| 4281 } | 4368 } |
| 4282 | 4369 |
| 4283 | 4370 |
| 4284 Vector<const char> String::ToAsciiVector() { | 4371 Vector<const char> String::ToAsciiVector() { |
| 4285 ASSERT(IsAsciiRepresentation()); | 4372 ASSERT(IsAsciiRepresentation()); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4335 | 4422 |
| 4336 SmartPointer<char> String::ToCString(AllowNullsFlag allow_nulls, | 4423 SmartPointer<char> String::ToCString(AllowNullsFlag allow_nulls, |
| 4337 RobustnessFlag robust_flag, | 4424 RobustnessFlag robust_flag, |
| 4338 int offset, | 4425 int offset, |
| 4339 int length, | 4426 int length, |
| 4340 int* length_return) { | 4427 int* length_return) { |
| 4341 ASSERT(NativeAllocationChecker::allocation_allowed()); | 4428 ASSERT(NativeAllocationChecker::allocation_allowed()); |
| 4342 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { | 4429 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { |
| 4343 return SmartPointer<char>(NULL); | 4430 return SmartPointer<char>(NULL); |
| 4344 } | 4431 } |
| 4432 Heap* heap = GetHeap(); |
| 4345 | 4433 |
| 4346 // Negative length means the to the end of the string. | 4434 // Negative length means the to the end of the string. |
| 4347 if (length < 0) length = kMaxInt - offset; | 4435 if (length < 0) length = kMaxInt - offset; |
| 4348 | 4436 |
| 4349 // Compute the size of the UTF-8 string. Start at the specified offset. | 4437 // Compute the size of the UTF-8 string. Start at the specified offset. |
| 4350 Access<StringInputBuffer> buffer(&string_input_buffer); | 4438 Access<StringInputBuffer> buffer( |
| 4439 heap->isolate()->objects_string_input_buffer()); |
| 4351 buffer->Reset(offset, this); | 4440 buffer->Reset(offset, this); |
| 4352 int character_position = offset; | 4441 int character_position = offset; |
| 4353 int utf8_bytes = 0; | 4442 int utf8_bytes = 0; |
| 4354 while (buffer->has_more()) { | 4443 while (buffer->has_more()) { |
| 4355 uint16_t character = buffer->GetNext(); | 4444 uint16_t character = buffer->GetNext(); |
| 4356 if (character_position < offset + length) { | 4445 if (character_position < offset + length) { |
| 4357 utf8_bytes += unibrow::Utf8::Length(character); | 4446 utf8_bytes += unibrow::Utf8::Length(character); |
| 4358 } | 4447 } |
| 4359 character_position++; | 4448 character_position++; |
| 4360 } | 4449 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4410 UNREACHABLE(); | 4499 UNREACHABLE(); |
| 4411 return NULL; | 4500 return NULL; |
| 4412 } | 4501 } |
| 4413 UNREACHABLE(); | 4502 UNREACHABLE(); |
| 4414 return NULL; | 4503 return NULL; |
| 4415 } | 4504 } |
| 4416 | 4505 |
| 4417 | 4506 |
| 4418 SmartPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) { | 4507 SmartPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) { |
| 4419 ASSERT(NativeAllocationChecker::allocation_allowed()); | 4508 ASSERT(NativeAllocationChecker::allocation_allowed()); |
| 4420 | |
| 4421 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { | 4509 if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) { |
| 4422 return SmartPointer<uc16>(); | 4510 return SmartPointer<uc16>(); |
| 4423 } | 4511 } |
| 4512 Heap* heap = GetHeap(); |
| 4424 | 4513 |
| 4425 Access<StringInputBuffer> buffer(&string_input_buffer); | 4514 Access<StringInputBuffer> buffer( |
| 4515 heap->isolate()->objects_string_input_buffer()); |
| 4426 buffer->Reset(this); | 4516 buffer->Reset(this); |
| 4427 | 4517 |
| 4428 uc16* result = NewArray<uc16>(length() + 1); | 4518 uc16* result = NewArray<uc16>(length() + 1); |
| 4429 | 4519 |
| 4430 int i = 0; | 4520 int i = 0; |
| 4431 while (buffer->has_more()) { | 4521 while (buffer->has_more()) { |
| 4432 uint16_t character = buffer->GetNext(); | 4522 uint16_t character = buffer->GetNext(); |
| 4433 result[i++] = character; | 4523 result[i++] = character; |
| 4434 } | 4524 } |
| 4435 result[i] = 0; | 4525 result[i] = 0; |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4698 } | 4788 } |
| 4699 default: | 4789 default: |
| 4700 break; | 4790 break; |
| 4701 } | 4791 } |
| 4702 | 4792 |
| 4703 UNREACHABLE(); | 4793 UNREACHABLE(); |
| 4704 return 0; | 4794 return 0; |
| 4705 } | 4795 } |
| 4706 | 4796 |
| 4707 | 4797 |
| 4708 Relocatable* Relocatable::top_ = NULL; | |
| 4709 | |
| 4710 | |
| 4711 void Relocatable::PostGarbageCollectionProcessing() { | 4798 void Relocatable::PostGarbageCollectionProcessing() { |
| 4712 Relocatable* current = top_; | 4799 Isolate* isolate = Isolate::Current(); |
| 4800 Relocatable* current = isolate->relocatable_top(); |
| 4713 while (current != NULL) { | 4801 while (current != NULL) { |
| 4714 current->PostGarbageCollection(); | 4802 current->PostGarbageCollection(); |
| 4715 current = current->prev_; | 4803 current = current->prev_; |
| 4716 } | 4804 } |
| 4717 } | 4805 } |
| 4718 | 4806 |
| 4719 | 4807 |
| 4720 // Reserve space for statics needing saving and restoring. | 4808 // Reserve space for statics needing saving and restoring. |
| 4721 int Relocatable::ArchiveSpacePerThread() { | 4809 int Relocatable::ArchiveSpacePerThread() { |
| 4722 return sizeof(top_); | 4810 return sizeof(Isolate::Current()->relocatable_top()); |
| 4723 } | 4811 } |
| 4724 | 4812 |
| 4725 | 4813 |
| 4726 // Archive statics that are thread local. | 4814 // Archive statics that are thread local. |
| 4727 char* Relocatable::ArchiveState(char* to) { | 4815 char* Relocatable::ArchiveState(char* to) { |
| 4728 *reinterpret_cast<Relocatable**>(to) = top_; | 4816 Isolate* isolate = Isolate::Current(); |
| 4729 top_ = NULL; | 4817 *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top(); |
| 4818 isolate->set_relocatable_top(NULL); |
| 4730 return to + ArchiveSpacePerThread(); | 4819 return to + ArchiveSpacePerThread(); |
| 4731 } | 4820 } |
| 4732 | 4821 |
| 4733 | 4822 |
| 4734 // Restore statics that are thread local. | 4823 // Restore statics that are thread local. |
| 4735 char* Relocatable::RestoreState(char* from) { | 4824 char* Relocatable::RestoreState(char* from) { |
| 4736 top_ = *reinterpret_cast<Relocatable**>(from); | 4825 Isolate* isolate = Isolate::Current(); |
| 4826 isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from)); |
| 4737 return from + ArchiveSpacePerThread(); | 4827 return from + ArchiveSpacePerThread(); |
| 4738 } | 4828 } |
| 4739 | 4829 |
| 4740 | 4830 |
| 4741 char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) { | 4831 char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) { |
| 4742 Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage); | 4832 Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage); |
| 4743 Iterate(v, top); | 4833 Iterate(v, top); |
| 4744 return thread_storage + ArchiveSpacePerThread(); | 4834 return thread_storage + ArchiveSpacePerThread(); |
| 4745 } | 4835 } |
| 4746 | 4836 |
| 4747 | 4837 |
| 4748 void Relocatable::Iterate(ObjectVisitor* v) { | 4838 void Relocatable::Iterate(ObjectVisitor* v) { |
| 4749 Iterate(v, top_); | 4839 Isolate* isolate = Isolate::Current(); |
| 4840 Iterate(v, isolate->relocatable_top()); |
| 4750 } | 4841 } |
| 4751 | 4842 |
| 4752 | 4843 |
| 4753 void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) { | 4844 void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) { |
| 4754 Relocatable* current = top; | 4845 Relocatable* current = top; |
| 4755 while (current != NULL) { | 4846 while (current != NULL) { |
| 4756 current->IterateInstance(v); | 4847 current->IterateInstance(v); |
| 4757 current = current->prev_; | 4848 current = current->prev_; |
| 4758 } | 4849 } |
| 4759 } | 4850 } |
| 4760 | 4851 |
| 4761 | 4852 |
| 4762 FlatStringReader::FlatStringReader(Handle<String> str) | 4853 FlatStringReader::FlatStringReader(Isolate* isolate, Handle<String> str) |
| 4763 : str_(str.location()), | 4854 : Relocatable(isolate), |
| 4855 str_(str.location()), |
| 4764 length_(str->length()) { | 4856 length_(str->length()) { |
| 4765 PostGarbageCollection(); | 4857 PostGarbageCollection(); |
| 4766 } | 4858 } |
| 4767 | 4859 |
| 4768 | 4860 |
| 4769 FlatStringReader::FlatStringReader(Vector<const char> input) | 4861 FlatStringReader::FlatStringReader(Isolate* isolate, Vector<const char> input) |
| 4770 : str_(0), | 4862 : Relocatable(isolate), |
| 4863 str_(0), |
| 4771 is_ascii_(true), | 4864 is_ascii_(true), |
| 4772 length_(input.length()), | 4865 length_(input.length()), |
| 4773 start_(input.start()) { } | 4866 start_(input.start()) { } |
| 4774 | 4867 |
| 4775 | 4868 |
| 4776 void FlatStringReader::PostGarbageCollection() { | 4869 void FlatStringReader::PostGarbageCollection() { |
| 4777 if (str_ == NULL) return; | 4870 if (str_ == NULL) return; |
| 4778 Handle<String> str(str_); | 4871 Handle<String> str(str_); |
| 4779 ASSERT(str->IsFlat()); | 4872 ASSERT(str->IsFlat()); |
| 4780 is_ascii_ = str->IsAsciiRepresentation(); | 4873 is_ascii_ = str->IsAsciiRepresentation(); |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5090 // Compare the remaining characters that didn't fit into a block. | 5183 // Compare the remaining characters that didn't fit into a block. |
| 5091 for (; i < length; i++) { | 5184 for (; i < length; i++) { |
| 5092 if (a[i] != b[i]) { | 5185 if (a[i] != b[i]) { |
| 5093 return false; | 5186 return false; |
| 5094 } | 5187 } |
| 5095 } | 5188 } |
| 5096 return true; | 5189 return true; |
| 5097 } | 5190 } |
| 5098 | 5191 |
| 5099 | 5192 |
| 5100 static StringInputBuffer string_compare_buffer_b; | |
| 5101 | |
| 5102 | |
| 5103 template <typename IteratorA> | 5193 template <typename IteratorA> |
| 5104 static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) { | 5194 static inline bool CompareStringContentsPartial(Isolate* isolate, |
| 5195 IteratorA* ia, |
| 5196 String* b) { |
| 5105 if (b->IsFlat()) { | 5197 if (b->IsFlat()) { |
| 5106 if (b->IsAsciiRepresentation()) { | 5198 if (b->IsAsciiRepresentation()) { |
| 5107 VectorIterator<char> ib(b->ToAsciiVector()); | 5199 VectorIterator<char> ib(b->ToAsciiVector()); |
| 5108 return CompareStringContents(ia, &ib); | 5200 return CompareStringContents(ia, &ib); |
| 5109 } else { | 5201 } else { |
| 5110 VectorIterator<uc16> ib(b->ToUC16Vector()); | 5202 VectorIterator<uc16> ib(b->ToUC16Vector()); |
| 5111 return CompareStringContents(ia, &ib); | 5203 return CompareStringContents(ia, &ib); |
| 5112 } | 5204 } |
| 5113 } else { | 5205 } else { |
| 5114 string_compare_buffer_b.Reset(0, b); | 5206 isolate->objects_string_compare_buffer_b()->Reset(0, b); |
| 5115 return CompareStringContents(ia, &string_compare_buffer_b); | 5207 return CompareStringContents(ia, |
| 5208 isolate->objects_string_compare_buffer_b()); |
| 5116 } | 5209 } |
| 5117 } | 5210 } |
| 5118 | 5211 |
| 5119 | 5212 |
| 5120 static StringInputBuffer string_compare_buffer_a; | 5213 bool String::SlowEquals(String* other) { |
| 5214 Heap* heap = GetHeap(); |
| 5121 | 5215 |
| 5122 | |
| 5123 bool String::SlowEquals(String* other) { | |
| 5124 // Fast check: negative check with lengths. | 5216 // Fast check: negative check with lengths. |
| 5125 int len = length(); | 5217 int len = length(); |
| 5126 if (len != other->length()) return false; | 5218 if (len != other->length()) return false; |
| 5127 if (len == 0) return true; | 5219 if (len == 0) return true; |
| 5128 | 5220 |
| 5129 // Fast check: if hash code is computed for both strings | 5221 // Fast check: if hash code is computed for both strings |
| 5130 // a fast negative check can be performed. | 5222 // a fast negative check can be performed. |
| 5131 if (HasHashCode() && other->HasHashCode()) { | 5223 if (HasHashCode() && other->HasHashCode()) { |
| 5132 if (Hash() != other->Hash()) return false; | 5224 if (Hash() != other->Hash()) return false; |
| 5133 } | 5225 } |
| 5134 | 5226 |
| 5135 // We know the strings are both non-empty. Compare the first chars | 5227 // We know the strings are both non-empty. Compare the first chars |
| 5136 // before we try to flatten the strings. | 5228 // before we try to flatten the strings. |
| 5137 if (this->Get(0) != other->Get(0)) return false; | 5229 if (this->Get(0) != other->Get(0)) return false; |
| 5138 | 5230 |
| 5139 String* lhs = this->TryFlattenGetString(); | 5231 String* lhs = this->TryFlattenGetString(); |
| 5140 String* rhs = other->TryFlattenGetString(); | 5232 String* rhs = other->TryFlattenGetString(); |
| 5141 | 5233 |
| 5142 if (StringShape(lhs).IsSequentialAscii() && | 5234 if (StringShape(lhs).IsSequentialAscii() && |
| 5143 StringShape(rhs).IsSequentialAscii()) { | 5235 StringShape(rhs).IsSequentialAscii()) { |
| 5144 const char* str1 = SeqAsciiString::cast(lhs)->GetChars(); | 5236 const char* str1 = SeqAsciiString::cast(lhs)->GetChars(); |
| 5145 const char* str2 = SeqAsciiString::cast(rhs)->GetChars(); | 5237 const char* str2 = SeqAsciiString::cast(rhs)->GetChars(); |
| 5146 return CompareRawStringContents(Vector<const char>(str1, len), | 5238 return CompareRawStringContents(Vector<const char>(str1, len), |
| 5147 Vector<const char>(str2, len)); | 5239 Vector<const char>(str2, len)); |
| 5148 } | 5240 } |
| 5149 | 5241 |
| 5242 Isolate* isolate = heap->isolate(); |
| 5150 if (lhs->IsFlat()) { | 5243 if (lhs->IsFlat()) { |
| 5151 if (lhs->IsAsciiRepresentation()) { | 5244 if (lhs->IsAsciiRepresentation()) { |
| 5152 Vector<const char> vec1 = lhs->ToAsciiVector(); | 5245 Vector<const char> vec1 = lhs->ToAsciiVector(); |
| 5153 if (rhs->IsFlat()) { | 5246 if (rhs->IsFlat()) { |
| 5154 if (rhs->IsAsciiRepresentation()) { | 5247 if (rhs->IsAsciiRepresentation()) { |
| 5155 Vector<const char> vec2 = rhs->ToAsciiVector(); | 5248 Vector<const char> vec2 = rhs->ToAsciiVector(); |
| 5156 return CompareRawStringContents(vec1, vec2); | 5249 return CompareRawStringContents(vec1, vec2); |
| 5157 } else { | 5250 } else { |
| 5158 VectorIterator<char> buf1(vec1); | 5251 VectorIterator<char> buf1(vec1); |
| 5159 VectorIterator<uc16> ib(rhs->ToUC16Vector()); | 5252 VectorIterator<uc16> ib(rhs->ToUC16Vector()); |
| 5160 return CompareStringContents(&buf1, &ib); | 5253 return CompareStringContents(&buf1, &ib); |
| 5161 } | 5254 } |
| 5162 } else { | 5255 } else { |
| 5163 VectorIterator<char> buf1(vec1); | 5256 VectorIterator<char> buf1(vec1); |
| 5164 string_compare_buffer_b.Reset(0, rhs); | 5257 isolate->objects_string_compare_buffer_b()->Reset(0, rhs); |
| 5165 return CompareStringContents(&buf1, &string_compare_buffer_b); | 5258 return CompareStringContents(&buf1, |
| 5259 isolate->objects_string_compare_buffer_b()); |
| 5166 } | 5260 } |
| 5167 } else { | 5261 } else { |
| 5168 Vector<const uc16> vec1 = lhs->ToUC16Vector(); | 5262 Vector<const uc16> vec1 = lhs->ToUC16Vector(); |
| 5169 if (rhs->IsFlat()) { | 5263 if (rhs->IsFlat()) { |
| 5170 if (rhs->IsAsciiRepresentation()) { | 5264 if (rhs->IsAsciiRepresentation()) { |
| 5171 VectorIterator<uc16> buf1(vec1); | 5265 VectorIterator<uc16> buf1(vec1); |
| 5172 VectorIterator<char> ib(rhs->ToAsciiVector()); | 5266 VectorIterator<char> ib(rhs->ToAsciiVector()); |
| 5173 return CompareStringContents(&buf1, &ib); | 5267 return CompareStringContents(&buf1, &ib); |
| 5174 } else { | 5268 } else { |
| 5175 Vector<const uc16> vec2(rhs->ToUC16Vector()); | 5269 Vector<const uc16> vec2(rhs->ToUC16Vector()); |
| 5176 return CompareRawStringContents(vec1, vec2); | 5270 return CompareRawStringContents(vec1, vec2); |
| 5177 } | 5271 } |
| 5178 } else { | 5272 } else { |
| 5179 VectorIterator<uc16> buf1(vec1); | 5273 VectorIterator<uc16> buf1(vec1); |
| 5180 string_compare_buffer_b.Reset(0, rhs); | 5274 isolate->objects_string_compare_buffer_b()->Reset(0, rhs); |
| 5181 return CompareStringContents(&buf1, &string_compare_buffer_b); | 5275 return CompareStringContents(&buf1, |
| 5276 isolate->objects_string_compare_buffer_b()); |
| 5182 } | 5277 } |
| 5183 } | 5278 } |
| 5184 } else { | 5279 } else { |
| 5185 string_compare_buffer_a.Reset(0, lhs); | 5280 isolate->objects_string_compare_buffer_a()->Reset(0, lhs); |
| 5186 return CompareStringContentsPartial(&string_compare_buffer_a, rhs); | 5281 return CompareStringContentsPartial(isolate, |
| 5282 isolate->objects_string_compare_buffer_a(), rhs); |
| 5187 } | 5283 } |
| 5188 } | 5284 } |
| 5189 | 5285 |
| 5190 | 5286 |
| 5191 bool String::MarkAsUndetectable() { | 5287 bool String::MarkAsUndetectable() { |
| 5192 if (StringShape(this).IsSymbol()) return false; | 5288 if (StringShape(this).IsSymbol()) return false; |
| 5193 | 5289 |
| 5194 Map* map = this->map(); | 5290 Map* map = this->map(); |
| 5195 if (map == Heap::string_map()) { | 5291 Heap* heap = map->GetHeap(); |
| 5196 this->set_map(Heap::undetectable_string_map()); | 5292 if (map == heap->string_map()) { |
| 5293 this->set_map(heap->undetectable_string_map()); |
| 5197 return true; | 5294 return true; |
| 5198 } else if (map == Heap::ascii_string_map()) { | 5295 } else if (map == heap->ascii_string_map()) { |
| 5199 this->set_map(Heap::undetectable_ascii_string_map()); | 5296 this->set_map(heap->undetectable_ascii_string_map()); |
| 5200 return true; | 5297 return true; |
| 5201 } | 5298 } |
| 5202 // Rest cannot be marked as undetectable | 5299 // Rest cannot be marked as undetectable |
| 5203 return false; | 5300 return false; |
| 5204 } | 5301 } |
| 5205 | 5302 |
| 5206 | 5303 |
| 5207 bool String::IsEqualTo(Vector<const char> str) { | 5304 bool String::IsEqualTo(Vector<const char> str) { |
| 5305 Isolate* isolate = GetIsolate(); |
| 5208 int slen = length(); | 5306 int slen = length(); |
| 5209 Access<ScannerConstants::Utf8Decoder> | 5307 Access<ScannerConstants::Utf8Decoder> |
| 5210 decoder(ScannerConstants::utf8_decoder()); | 5308 decoder(isolate->scanner_constants()->utf8_decoder()); |
| 5211 decoder->Reset(str.start(), str.length()); | 5309 decoder->Reset(str.start(), str.length()); |
| 5212 int i; | 5310 int i; |
| 5213 for (i = 0; i < slen && decoder->has_more(); i++) { | 5311 for (i = 0; i < slen && decoder->has_more(); i++) { |
| 5214 uc32 r = decoder->GetNext(); | 5312 uc32 r = decoder->GetNext(); |
| 5215 if (Get(i) != r) return false; | 5313 if (Get(i) != r) return false; |
| 5216 } | 5314 } |
| 5217 return i == slen && !decoder->has_more(); | 5315 return i == slen && !decoder->has_more(); |
| 5218 } | 5316 } |
| 5219 | 5317 |
| 5220 | 5318 |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5362 // index. | 5460 // index. |
| 5363 while (buffer->has_more()) { | 5461 while (buffer->has_more()) { |
| 5364 hasher.AddCharacterNoIndex(buffer->GetNext()); | 5462 hasher.AddCharacterNoIndex(buffer->GetNext()); |
| 5365 } | 5463 } |
| 5366 | 5464 |
| 5367 return hasher.GetHashField(); | 5465 return hasher.GetHashField(); |
| 5368 } | 5466 } |
| 5369 | 5467 |
| 5370 | 5468 |
| 5371 MaybeObject* String::SubString(int start, int end, PretenureFlag pretenure) { | 5469 MaybeObject* String::SubString(int start, int end, PretenureFlag pretenure) { |
| 5470 Heap* heap = GetHeap(); |
| 5372 if (start == 0 && end == length()) return this; | 5471 if (start == 0 && end == length()) return this; |
| 5373 MaybeObject* result = Heap::AllocateSubString(this, start, end, pretenure); | 5472 MaybeObject* result = heap->AllocateSubString(this, start, end, pretenure); |
| 5374 return result; | 5473 return result; |
| 5375 } | 5474 } |
| 5376 | 5475 |
| 5377 | 5476 |
| 5378 void String::PrintOn(FILE* file) { | 5477 void String::PrintOn(FILE* file) { |
| 5379 int length = this->length(); | 5478 int length = this->length(); |
| 5380 for (int i = 0; i < length; i++) { | 5479 for (int i = 0; i < length; i++) { |
| 5381 fprintf(file, "%c", Get(i)); | 5480 fprintf(file, "%c", Get(i)); |
| 5382 } | 5481 } |
| 5383 } | 5482 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 5403 source_prototype == target_prototype); | 5502 source_prototype == target_prototype); |
| 5404 #endif | 5503 #endif |
| 5405 // Point target back to source. set_prototype() will not let us set | 5504 // Point target back to source. set_prototype() will not let us set |
| 5406 // the prototype to a map, as we do here. | 5505 // the prototype to a map, as we do here. |
| 5407 *RawField(target, kPrototypeOffset) = this; | 5506 *RawField(target, kPrototypeOffset) = this; |
| 5408 } | 5507 } |
| 5409 } | 5508 } |
| 5410 } | 5509 } |
| 5411 | 5510 |
| 5412 | 5511 |
| 5413 void Map::ClearNonLiveTransitions(Object* real_prototype) { | 5512 void Map::ClearNonLiveTransitions(Heap* heap, Object* real_prototype) { |
| 5414 // Live DescriptorArray objects will be marked, so we must use | 5513 // Live DescriptorArray objects will be marked, so we must use |
| 5415 // low-level accessors to get and modify their data. | 5514 // low-level accessors to get and modify their data. |
| 5416 DescriptorArray* d = reinterpret_cast<DescriptorArray*>( | 5515 DescriptorArray* d = reinterpret_cast<DescriptorArray*>( |
| 5417 *RawField(this, Map::kInstanceDescriptorsOffset)); | 5516 *RawField(this, Map::kInstanceDescriptorsOffset)); |
| 5418 if (d == Heap::raw_unchecked_empty_descriptor_array()) return; | 5517 if (d == heap->raw_unchecked_empty_descriptor_array()) return; |
| 5419 Smi* NullDescriptorDetails = | 5518 Smi* NullDescriptorDetails = |
| 5420 PropertyDetails(NONE, NULL_DESCRIPTOR).AsSmi(); | 5519 PropertyDetails(NONE, NULL_DESCRIPTOR).AsSmi(); |
| 5421 FixedArray* contents = reinterpret_cast<FixedArray*>( | 5520 FixedArray* contents = reinterpret_cast<FixedArray*>( |
| 5422 d->get(DescriptorArray::kContentArrayIndex)); | 5521 d->get(DescriptorArray::kContentArrayIndex)); |
| 5423 ASSERT(contents->length() >= 2); | 5522 ASSERT(contents->length() >= 2); |
| 5424 for (int i = 0; i < contents->length(); i += 2) { | 5523 for (int i = 0; i < contents->length(); i += 2) { |
| 5425 // If the pair (value, details) is a map transition, | 5524 // If the pair (value, details) is a map transition, |
| 5426 // check if the target is live. If not, null the descriptor. | 5525 // check if the target is live. If not, null the descriptor. |
| 5427 // Also drop the back pointer for that map transition, so that this | 5526 // Also drop the back pointer for that map transition, so that this |
| 5428 // map is not reached again by following a back pointer from a | 5527 // map is not reached again by following a back pointer from a |
| 5429 // non-live object. | 5528 // non-live object. |
| 5430 PropertyDetails details(Smi::cast(contents->get(i + 1))); | 5529 PropertyDetails details(Smi::cast(contents->get(i + 1))); |
| 5431 if (details.type() == MAP_TRANSITION || | 5530 if (details.type() == MAP_TRANSITION || |
| 5432 details.type() == CONSTANT_TRANSITION) { | 5531 details.type() == CONSTANT_TRANSITION) { |
| 5433 Map* target = reinterpret_cast<Map*>(contents->get(i)); | 5532 Map* target = reinterpret_cast<Map*>(contents->get(i)); |
| 5434 ASSERT(target->IsHeapObject()); | 5533 ASSERT(target->IsHeapObject()); |
| 5435 if (!target->IsMarked()) { | 5534 if (!target->IsMarked()) { |
| 5436 ASSERT(target->IsMap()); | 5535 ASSERT(target->IsMap()); |
| 5437 contents->set_unchecked(i + 1, NullDescriptorDetails); | 5536 contents->set_unchecked(i + 1, NullDescriptorDetails); |
| 5438 contents->set_null_unchecked(i); | 5537 contents->set_null_unchecked(heap, i); |
| 5439 ASSERT(target->prototype() == this || | 5538 ASSERT(target->prototype() == this || |
| 5440 target->prototype() == real_prototype); | 5539 target->prototype() == real_prototype); |
| 5441 // Getter prototype() is read-only, set_prototype() has side effects. | 5540 // Getter prototype() is read-only, set_prototype() has side effects. |
| 5442 *RawField(target, Map::kPrototypeOffset) = real_prototype; | 5541 *RawField(target, Map::kPrototypeOffset) = real_prototype; |
| 5443 } | 5542 } |
| 5444 } | 5543 } |
| 5445 } | 5544 } |
| 5446 } | 5545 } |
| 5447 | 5546 |
| 5448 | 5547 |
| 5449 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) { | 5548 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) { |
| 5450 // Iterate over all fields in the body but take care in dealing with | 5549 // Iterate over all fields in the body but take care in dealing with |
| 5451 // the code entry. | 5550 // the code entry. |
| 5452 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset); | 5551 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset); |
| 5453 v->VisitCodeEntry(this->address() + kCodeEntryOffset); | 5552 v->VisitCodeEntry(this->address() + kCodeEntryOffset); |
| 5454 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size); | 5553 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size); |
| 5455 } | 5554 } |
| 5456 | 5555 |
| 5457 | 5556 |
| 5458 void JSFunction::MarkForLazyRecompilation() { | 5557 void JSFunction::MarkForLazyRecompilation() { |
| 5459 ASSERT(is_compiled() && !IsOptimized()); | 5558 ASSERT(is_compiled() && !IsOptimized()); |
| 5460 ASSERT(shared()->allows_lazy_compilation() || | 5559 ASSERT(shared()->allows_lazy_compilation() || |
| 5461 code()->optimizable()); | 5560 code()->optimizable()); |
| 5462 ReplaceCode(Builtins::builtin(Builtins::LazyRecompile)); | 5561 Builtins* builtins = GetIsolate()->builtins(); |
| 5562 ReplaceCode(builtins->builtin(Builtins::LazyRecompile)); |
| 5463 } | 5563 } |
| 5464 | 5564 |
| 5465 | 5565 |
| 5466 uint32_t JSFunction::SourceHash() { | 5566 uint32_t JSFunction::SourceHash() { |
| 5467 uint32_t hash = 0; | 5567 uint32_t hash = 0; |
| 5468 Object* script = shared()->script(); | 5568 Object* script = shared()->script(); |
| 5469 if (!script->IsUndefined()) { | 5569 if (!script->IsUndefined()) { |
| 5470 Object* source = Script::cast(script)->source(); | 5570 Object* source = Script::cast(script)->source(); |
| 5471 if (source->IsUndefined()) hash = String::cast(source)->Hash(); | 5571 if (source->IsUndefined()) hash = String::cast(source)->Hash(); |
| 5472 } | 5572 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 5485 Code* code = shared_info->code(); | 5585 Code* code = shared_info->code(); |
| 5486 if (code->kind() == Code::OPTIMIZED_FUNCTION) return true; | 5586 if (code->kind() == Code::OPTIMIZED_FUNCTION) return true; |
| 5487 // If we never ran this (unlikely) then lets try to optimize it. | 5587 // If we never ran this (unlikely) then lets try to optimize it. |
| 5488 if (code->kind() != Code::FUNCTION) return true; | 5588 if (code->kind() != Code::FUNCTION) return true; |
| 5489 return code->optimizable(); | 5589 return code->optimizable(); |
| 5490 } | 5590 } |
| 5491 | 5591 |
| 5492 | 5592 |
| 5493 Object* JSFunction::SetInstancePrototype(Object* value) { | 5593 Object* JSFunction::SetInstancePrototype(Object* value) { |
| 5494 ASSERT(value->IsJSObject()); | 5594 ASSERT(value->IsJSObject()); |
| 5495 | 5595 Heap* heap = GetHeap(); |
| 5496 if (has_initial_map()) { | 5596 if (has_initial_map()) { |
| 5497 initial_map()->set_prototype(value); | 5597 initial_map()->set_prototype(value); |
| 5498 } else { | 5598 } else { |
| 5499 // Put the value in the initial map field until an initial map is | 5599 // Put the value in the initial map field until an initial map is |
| 5500 // needed. At that point, a new initial map is created and the | 5600 // needed. At that point, a new initial map is created and the |
| 5501 // prototype is put into the initial map where it belongs. | 5601 // prototype is put into the initial map where it belongs. |
| 5502 set_prototype_or_initial_map(value); | 5602 set_prototype_or_initial_map(value); |
| 5503 } | 5603 } |
| 5504 Heap::ClearInstanceofCache(); | 5604 heap->ClearInstanceofCache(); |
| 5505 return value; | 5605 return value; |
| 5506 } | 5606 } |
| 5507 | 5607 |
| 5508 | 5608 |
| 5509 MaybeObject* JSFunction::SetPrototype(Object* value) { | 5609 MaybeObject* JSFunction::SetPrototype(Object* value) { |
| 5510 ASSERT(should_have_prototype()); | 5610 ASSERT(should_have_prototype()); |
| 5511 Object* construct_prototype = value; | 5611 Object* construct_prototype = value; |
| 5512 | 5612 |
| 5513 // If the value is not a JSObject, store the value in the map's | 5613 // If the value is not a JSObject, store the value in the map's |
| 5514 // constructor field so it can be accessed. Also, set the prototype | 5614 // constructor field so it can be accessed. Also, set the prototype |
| 5515 // used for constructing objects to the original object prototype. | 5615 // used for constructing objects to the original object prototype. |
| 5516 // See ECMA-262 13.2.2. | 5616 // See ECMA-262 13.2.2. |
| 5517 if (!value->IsJSObject()) { | 5617 if (!value->IsJSObject()) { |
| 5618 Heap* heap = GetHeap(); |
| 5518 // Copy the map so this does not affect unrelated functions. | 5619 // Copy the map so this does not affect unrelated functions. |
| 5519 // Remove map transitions because they point to maps with a | 5620 // Remove map transitions because they point to maps with a |
| 5520 // different prototype. | 5621 // different prototype. |
| 5521 Object* new_map; | 5622 Object* new_map; |
| 5522 { MaybeObject* maybe_new_map = map()->CopyDropTransitions(); | 5623 { MaybeObject* maybe_new_map = map()->CopyDropTransitions(); |
| 5523 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; | 5624 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; |
| 5524 } | 5625 } |
| 5525 set_map(Map::cast(new_map)); | 5626 set_map(Map::cast(new_map)); |
| 5526 map()->set_constructor(value); | 5627 map()->set_constructor(value); |
| 5527 map()->set_non_instance_prototype(true); | 5628 map()->set_non_instance_prototype(true); |
| 5528 construct_prototype = | 5629 construct_prototype = |
| 5529 Top::context()->global_context()->initial_object_prototype(); | 5630 heap->isolate()->context()->global_context()-> |
| 5631 initial_object_prototype(); |
| 5530 } else { | 5632 } else { |
| 5531 map()->set_non_instance_prototype(false); | 5633 map()->set_non_instance_prototype(false); |
| 5532 } | 5634 } |
| 5533 | 5635 |
| 5534 return SetInstancePrototype(construct_prototype); | 5636 return SetInstancePrototype(construct_prototype); |
| 5535 } | 5637 } |
| 5536 | 5638 |
| 5537 | 5639 |
| 5538 Object* JSFunction::RemovePrototype() { | 5640 Object* JSFunction::RemovePrototype() { |
| 5539 Context* global_context = context()->global_context(); | 5641 Context* global_context = context()->global_context(); |
| 5540 Map* no_prototype_map = shared()->strict_mode() | 5642 Map* no_prototype_map = shared()->strict_mode() |
| 5541 ? global_context->strict_mode_function_without_prototype_map() | 5643 ? global_context->strict_mode_function_without_prototype_map() |
| 5542 : global_context->function_without_prototype_map(); | 5644 : global_context->function_without_prototype_map(); |
| 5543 | 5645 |
| 5544 if (map() == no_prototype_map) { | 5646 if (map() == no_prototype_map) { |
| 5545 // Be idempotent. | 5647 // Be idempotent. |
| 5546 return this; | 5648 return this; |
| 5547 } | 5649 } |
| 5548 | 5650 |
| 5549 ASSERT(!shared()->strict_mode() || | 5651 ASSERT(!shared()->strict_mode() || |
| 5550 map() == global_context->strict_mode_function_map()); | 5652 map() == global_context->strict_mode_function_map()); |
| 5551 ASSERT(shared()->strict_mode() || map() == global_context->function_map()); | 5653 ASSERT(shared()->strict_mode() || map() == global_context->function_map()); |
| 5552 | 5654 |
| 5553 set_map(no_prototype_map); | 5655 set_map(no_prototype_map); |
| 5554 set_prototype_or_initial_map(Heap::the_hole_value()); | 5656 set_prototype_or_initial_map(GetHeap()->the_hole_value()); |
| 5555 return this; | 5657 return this; |
| 5556 } | 5658 } |
| 5557 | 5659 |
| 5558 | 5660 |
| 5559 Object* JSFunction::SetInstanceClassName(String* name) { | 5661 Object* JSFunction::SetInstanceClassName(String* name) { |
| 5560 shared()->set_instance_class_name(name); | 5662 shared()->set_instance_class_name(name); |
| 5561 return this; | 5663 return this; |
| 5562 } | 5664 } |
| 5563 | 5665 |
| 5564 | 5666 |
| 5565 void JSFunction::PrintName(FILE* out) { | 5667 void JSFunction::PrintName(FILE* out) { |
| 5566 SmartPointer<char> name = shared()->DebugName()->ToCString(); | 5668 SmartPointer<char> name = shared()->DebugName()->ToCString(); |
| 5567 PrintF(out, "%s", *name); | 5669 PrintF(out, "%s", *name); |
| 5568 } | 5670 } |
| 5569 | 5671 |
| 5570 | 5672 |
| 5571 Context* JSFunction::GlobalContextFromLiterals(FixedArray* literals) { | 5673 Context* JSFunction::GlobalContextFromLiterals(FixedArray* literals) { |
| 5572 return Context::cast(literals->get(JSFunction::kLiteralGlobalContextIndex)); | 5674 return Context::cast(literals->get(JSFunction::kLiteralGlobalContextIndex)); |
| 5573 } | 5675 } |
| 5574 | 5676 |
| 5575 | 5677 |
| 5576 MaybeObject* Oddball::Initialize(const char* to_string, Object* to_number) { | 5678 MaybeObject* Oddball::Initialize(const char* to_string, |
| 5679 Object* to_number, |
| 5680 byte kind) { |
| 5577 Object* symbol; | 5681 Object* symbol; |
| 5578 { MaybeObject* maybe_symbol = Heap::LookupAsciiSymbol(to_string); | 5682 { MaybeObject* maybe_symbol = |
| 5683 Isolate::Current()->heap()->LookupAsciiSymbol(to_string); |
| 5579 if (!maybe_symbol->ToObject(&symbol)) return maybe_symbol; | 5684 if (!maybe_symbol->ToObject(&symbol)) return maybe_symbol; |
| 5580 } | 5685 } |
| 5581 set_to_string(String::cast(symbol)); | 5686 set_to_string(String::cast(symbol)); |
| 5582 set_to_number(to_number); | 5687 set_to_number(to_number); |
| 5688 set_kind(kind); |
| 5583 return this; | 5689 return this; |
| 5584 } | 5690 } |
| 5585 | 5691 |
| 5586 | 5692 |
| 5587 String* SharedFunctionInfo::DebugName() { | 5693 String* SharedFunctionInfo::DebugName() { |
| 5588 Object* n = name(); | 5694 Object* n = name(); |
| 5589 if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name(); | 5695 if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name(); |
| 5590 return String::cast(n); | 5696 return String::cast(n); |
| 5591 } | 5697 } |
| 5592 | 5698 |
| 5593 | 5699 |
| 5594 bool SharedFunctionInfo::HasSourceCode() { | 5700 bool SharedFunctionInfo::HasSourceCode() { |
| 5595 return !script()->IsUndefined() && | 5701 return !script()->IsUndefined() && |
| 5596 !reinterpret_cast<Script*>(script())->source()->IsUndefined(); | 5702 !reinterpret_cast<Script*>(script())->source()->IsUndefined(); |
| 5597 } | 5703 } |
| 5598 | 5704 |
| 5599 | 5705 |
| 5600 Object* SharedFunctionInfo::GetSourceCode() { | 5706 Object* SharedFunctionInfo::GetSourceCode() { |
| 5601 if (!HasSourceCode()) return Heap::undefined_value(); | 5707 Isolate* isolate = GetIsolate(); |
| 5602 HandleScope scope; | 5708 if (!HasSourceCode()) return isolate->heap()->undefined_value(); |
| 5709 HandleScope scope(isolate); |
| 5603 Object* source = Script::cast(script())->source(); | 5710 Object* source = Script::cast(script())->source(); |
| 5604 return *SubString(Handle<String>(String::cast(source)), | 5711 return *SubString(Handle<String>(String::cast(source), isolate), |
| 5605 start_position(), end_position()); | 5712 start_position(), end_position()); |
| 5606 } | 5713 } |
| 5607 | 5714 |
| 5608 | 5715 |
| 5609 int SharedFunctionInfo::SourceSize() { | 5716 int SharedFunctionInfo::SourceSize() { |
| 5610 return end_position() - start_position(); | 5717 return end_position() - start_position(); |
| 5611 } | 5718 } |
| 5612 | 5719 |
| 5613 | 5720 |
| 5614 int SharedFunctionInfo::CalculateInstanceSize() { | 5721 int SharedFunctionInfo::CalculateInstanceSize() { |
| 5615 int instance_size = | 5722 int instance_size = |
| 5616 JSObject::kHeaderSize + | 5723 JSObject::kHeaderSize + |
| 5617 expected_nof_properties() * kPointerSize; | 5724 expected_nof_properties() * kPointerSize; |
| 5618 if (instance_size > JSObject::kMaxInstanceSize) { | 5725 if (instance_size > JSObject::kMaxInstanceSize) { |
| 5619 instance_size = JSObject::kMaxInstanceSize; | 5726 instance_size = JSObject::kMaxInstanceSize; |
| 5620 } | 5727 } |
| 5621 return instance_size; | 5728 return instance_size; |
| 5622 } | 5729 } |
| 5623 | 5730 |
| 5624 | 5731 |
| 5625 int SharedFunctionInfo::CalculateInObjectProperties() { | 5732 int SharedFunctionInfo::CalculateInObjectProperties() { |
| 5626 return (CalculateInstanceSize() - JSObject::kHeaderSize) / kPointerSize; | 5733 return (CalculateInstanceSize() - JSObject::kHeaderSize) / kPointerSize; |
| 5627 } | 5734 } |
| 5628 | 5735 |
| 5629 | 5736 |
| 5630 bool SharedFunctionInfo::CanGenerateInlineConstructor(Object* prototype) { | 5737 bool SharedFunctionInfo::CanGenerateInlineConstructor(Object* prototype) { |
| 5738 Heap* heap = GetHeap(); |
| 5739 |
| 5631 // Check the basic conditions for generating inline constructor code. | 5740 // Check the basic conditions for generating inline constructor code. |
| 5632 if (!FLAG_inline_new | 5741 if (!FLAG_inline_new |
| 5633 || !has_only_simple_this_property_assignments() | 5742 || !has_only_simple_this_property_assignments() |
| 5634 || this_property_assignments_count() == 0) { | 5743 || this_property_assignments_count() == 0) { |
| 5635 return false; | 5744 return false; |
| 5636 } | 5745 } |
| 5637 | 5746 |
| 5638 // If the prototype is null inline constructors cause no problems. | 5747 // If the prototype is null inline constructors cause no problems. |
| 5639 if (!prototype->IsJSObject()) { | 5748 if (!prototype->IsJSObject()) { |
| 5640 ASSERT(prototype->IsNull()); | 5749 ASSERT(prototype->IsNull()); |
| 5641 return true; | 5750 return true; |
| 5642 } | 5751 } |
| 5643 | 5752 |
| 5644 // Traverse the proposed prototype chain looking for setters for properties of | 5753 // Traverse the proposed prototype chain looking for setters for properties of |
| 5645 // the same names as are set by the inline constructor. | 5754 // the same names as are set by the inline constructor. |
| 5646 for (Object* obj = prototype; | 5755 for (Object* obj = prototype; |
| 5647 obj != Heap::null_value(); | 5756 obj != heap->null_value(); |
| 5648 obj = obj->GetPrototype()) { | 5757 obj = obj->GetPrototype()) { |
| 5649 JSObject* js_object = JSObject::cast(obj); | 5758 JSObject* js_object = JSObject::cast(obj); |
| 5650 for (int i = 0; i < this_property_assignments_count(); i++) { | 5759 for (int i = 0; i < this_property_assignments_count(); i++) { |
| 5651 LookupResult result; | 5760 LookupResult result; |
| 5652 String* name = GetThisPropertyAssignmentName(i); | 5761 String* name = GetThisPropertyAssignmentName(i); |
| 5653 js_object->LocalLookupRealNamedProperty(name, &result); | 5762 js_object->LocalLookupRealNamedProperty(name, &result); |
| 5654 if (result.IsProperty() && result.type() == CALLBACKS) { | 5763 if (result.IsProperty() && result.type() == CALLBACKS) { |
| 5655 return false; | 5764 return false; |
| 5656 } | 5765 } |
| 5657 } | 5766 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 5673 FixedArray* assignments) { | 5782 FixedArray* assignments) { |
| 5674 set_compiler_hints(BooleanBit::set(compiler_hints(), | 5783 set_compiler_hints(BooleanBit::set(compiler_hints(), |
| 5675 kHasOnlySimpleThisPropertyAssignments, | 5784 kHasOnlySimpleThisPropertyAssignments, |
| 5676 only_simple_this_property_assignments)); | 5785 only_simple_this_property_assignments)); |
| 5677 set_this_property_assignments(assignments); | 5786 set_this_property_assignments(assignments); |
| 5678 set_this_property_assignments_count(assignments->length() / 3); | 5787 set_this_property_assignments_count(assignments->length() / 3); |
| 5679 } | 5788 } |
| 5680 | 5789 |
| 5681 | 5790 |
| 5682 void SharedFunctionInfo::ClearThisPropertyAssignmentsInfo() { | 5791 void SharedFunctionInfo::ClearThisPropertyAssignmentsInfo() { |
| 5792 Heap* heap = GetHeap(); |
| 5683 set_compiler_hints(BooleanBit::set(compiler_hints(), | 5793 set_compiler_hints(BooleanBit::set(compiler_hints(), |
| 5684 kHasOnlySimpleThisPropertyAssignments, | 5794 kHasOnlySimpleThisPropertyAssignments, |
| 5685 false)); | 5795 false)); |
| 5686 set_this_property_assignments(Heap::undefined_value()); | 5796 set_this_property_assignments(heap->undefined_value()); |
| 5687 set_this_property_assignments_count(0); | 5797 set_this_property_assignments_count(0); |
| 5688 } | 5798 } |
| 5689 | 5799 |
| 5690 | 5800 |
| 5691 String* SharedFunctionInfo::GetThisPropertyAssignmentName(int index) { | 5801 String* SharedFunctionInfo::GetThisPropertyAssignmentName(int index) { |
| 5692 Object* obj = this_property_assignments(); | 5802 Object* obj = this_property_assignments(); |
| 5693 ASSERT(obj->IsFixedArray()); | 5803 ASSERT(obj->IsFixedArray()); |
| 5694 ASSERT(index < this_property_assignments_count()); | 5804 ASSERT(index < this_property_assignments_count()); |
| 5695 obj = FixedArray::cast(obj)->get(index * 3); | 5805 obj = FixedArray::cast(obj)->get(index * 3); |
| 5696 ASSERT(obj->IsString()); | 5806 ASSERT(obj->IsString()); |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5821 if (Serializer::enabled()) return; | 5931 if (Serializer::enabled()) return; |
| 5822 | 5932 |
| 5823 if (map->unused_property_fields() == 0) return; | 5933 if (map->unused_property_fields() == 0) return; |
| 5824 | 5934 |
| 5825 // Nonzero counter is a leftover from the previous attempt interrupted | 5935 // Nonzero counter is a leftover from the previous attempt interrupted |
| 5826 // by GC, keep it. | 5936 // by GC, keep it. |
| 5827 if (construction_count() == 0) { | 5937 if (construction_count() == 0) { |
| 5828 set_construction_count(kGenerousAllocationCount); | 5938 set_construction_count(kGenerousAllocationCount); |
| 5829 } | 5939 } |
| 5830 set_initial_map(map); | 5940 set_initial_map(map); |
| 5831 ASSERT_EQ(Builtins::builtin(Builtins::JSConstructStubGeneric), | 5941 Builtins* builtins = map->heap()->isolate()->builtins(); |
| 5942 ASSERT_EQ(builtins->builtin(Builtins::JSConstructStubGeneric), |
| 5832 construct_stub()); | 5943 construct_stub()); |
| 5833 set_construct_stub(Builtins::builtin(Builtins::JSConstructStubCountdown)); | 5944 set_construct_stub(builtins->builtin(Builtins::JSConstructStubCountdown)); |
| 5834 } | 5945 } |
| 5835 | 5946 |
| 5836 | 5947 |
| 5837 // Called from GC, hence reinterpret_cast and unchecked accessors. | 5948 // Called from GC, hence reinterpret_cast and unchecked accessors. |
| 5838 void SharedFunctionInfo::DetachInitialMap() { | 5949 void SharedFunctionInfo::DetachInitialMap() { |
| 5839 Map* map = reinterpret_cast<Map*>(initial_map()); | 5950 Map* map = reinterpret_cast<Map*>(initial_map()); |
| 5840 | 5951 |
| 5841 // Make the map remember to restore the link if it survives the GC. | 5952 // Make the map remember to restore the link if it survives the GC. |
| 5842 map->set_bit_field2( | 5953 map->set_bit_field2( |
| 5843 map->bit_field2() | (1 << Map::kAttachedToSharedFunctionInfo)); | 5954 map->bit_field2() | (1 << Map::kAttachedToSharedFunctionInfo)); |
| 5844 | 5955 |
| 5845 // Undo state changes made by StartInobjectTracking (except the | 5956 // Undo state changes made by StartInobjectTracking (except the |
| 5846 // construction_count). This way if the initial map does not survive the GC | 5957 // construction_count). This way if the initial map does not survive the GC |
| 5847 // then StartInobjectTracking will be called again the next time the | 5958 // then StartInobjectTracking will be called again the next time the |
| 5848 // constructor is called. The countdown will continue and (possibly after | 5959 // constructor is called. The countdown will continue and (possibly after |
| 5849 // several more GCs) CompleteInobjectSlackTracking will eventually be called. | 5960 // several more GCs) CompleteInobjectSlackTracking will eventually be called. |
| 5850 set_initial_map(Heap::raw_unchecked_undefined_value()); | 5961 set_initial_map(map->heap()->raw_unchecked_undefined_value()); |
| 5851 ASSERT_EQ(Builtins::builtin(Builtins::JSConstructStubCountdown), | 5962 Builtins* builtins = map->heap()->isolate()->builtins(); |
| 5963 ASSERT_EQ(builtins->builtin(Builtins::JSConstructStubCountdown), |
| 5852 *RawField(this, kConstructStubOffset)); | 5964 *RawField(this, kConstructStubOffset)); |
| 5853 set_construct_stub(Builtins::builtin(Builtins::JSConstructStubGeneric)); | 5965 set_construct_stub(builtins->builtin(Builtins::JSConstructStubGeneric)); |
| 5854 // It is safe to clear the flag: it will be set again if the map is live. | 5966 // It is safe to clear the flag: it will be set again if the map is live. |
| 5855 set_live_objects_may_exist(false); | 5967 set_live_objects_may_exist(false); |
| 5856 } | 5968 } |
| 5857 | 5969 |
| 5858 | 5970 |
| 5859 // Called from GC, hence reinterpret_cast and unchecked accessors. | 5971 // Called from GC, hence reinterpret_cast and unchecked accessors. |
| 5860 void SharedFunctionInfo::AttachInitialMap(Map* map) { | 5972 void SharedFunctionInfo::AttachInitialMap(Map* map) { |
| 5861 map->set_bit_field2( | 5973 map->set_bit_field2( |
| 5862 map->bit_field2() & ~(1 << Map::kAttachedToSharedFunctionInfo)); | 5974 map->bit_field2() & ~(1 << Map::kAttachedToSharedFunctionInfo)); |
| 5863 | 5975 |
| 5864 // Resume inobject slack tracking. | 5976 // Resume inobject slack tracking. |
| 5865 set_initial_map(map); | 5977 set_initial_map(map); |
| 5866 ASSERT_EQ(Builtins::builtin(Builtins::JSConstructStubGeneric), | 5978 Builtins* builtins = map->heap()->isolate()->builtins(); |
| 5979 ASSERT_EQ(builtins->builtin(Builtins::JSConstructStubGeneric), |
| 5867 *RawField(this, kConstructStubOffset)); | 5980 *RawField(this, kConstructStubOffset)); |
| 5868 set_construct_stub(Builtins::builtin(Builtins::JSConstructStubCountdown)); | 5981 set_construct_stub(builtins->builtin(Builtins::JSConstructStubCountdown)); |
| 5869 // The map survived the gc, so there may be objects referencing it. | 5982 // The map survived the gc, so there may be objects referencing it. |
| 5870 set_live_objects_may_exist(true); | 5983 set_live_objects_may_exist(true); |
| 5871 } | 5984 } |
| 5872 | 5985 |
| 5873 | 5986 |
| 5874 static void GetMinInobjectSlack(Map* map, void* data) { | 5987 static void GetMinInobjectSlack(Map* map, void* data) { |
| 5875 int slack = map->unused_property_fields(); | 5988 int slack = map->unused_property_fields(); |
| 5876 if (*reinterpret_cast<int*>(data) > slack) { | 5989 if (*reinterpret_cast<int*>(data) > slack) { |
| 5877 *reinterpret_cast<int*>(data) = slack; | 5990 *reinterpret_cast<int*>(data) = slack; |
| 5878 } | 5991 } |
| 5879 } | 5992 } |
| 5880 | 5993 |
| 5881 | 5994 |
| 5882 static void ShrinkInstanceSize(Map* map, void* data) { | 5995 static void ShrinkInstanceSize(Map* map, void* data) { |
| 5883 int slack = *reinterpret_cast<int*>(data); | 5996 int slack = *reinterpret_cast<int*>(data); |
| 5884 map->set_inobject_properties(map->inobject_properties() - slack); | 5997 map->set_inobject_properties(map->inobject_properties() - slack); |
| 5885 map->set_unused_property_fields(map->unused_property_fields() - slack); | 5998 map->set_unused_property_fields(map->unused_property_fields() - slack); |
| 5886 map->set_instance_size(map->instance_size() - slack * kPointerSize); | 5999 map->set_instance_size(map->instance_size() - slack * kPointerSize); |
| 5887 | 6000 |
| 5888 // Visitor id might depend on the instance size, recalculate it. | 6001 // Visitor id might depend on the instance size, recalculate it. |
| 5889 map->set_visitor_id(StaticVisitorBase::GetVisitorId(map)); | 6002 map->set_visitor_id(StaticVisitorBase::GetVisitorId(map)); |
| 5890 } | 6003 } |
| 5891 | 6004 |
| 5892 | 6005 |
| 5893 void SharedFunctionInfo::CompleteInobjectSlackTracking() { | 6006 void SharedFunctionInfo::CompleteInobjectSlackTracking() { |
| 5894 ASSERT(live_objects_may_exist() && IsInobjectSlackTrackingInProgress()); | 6007 ASSERT(live_objects_may_exist() && IsInobjectSlackTrackingInProgress()); |
| 5895 Map* map = Map::cast(initial_map()); | 6008 Map* map = Map::cast(initial_map()); |
| 5896 | 6009 |
| 5897 set_initial_map(Heap::undefined_value()); | 6010 Heap* heap = map->heap(); |
| 5898 ASSERT_EQ(Builtins::builtin(Builtins::JSConstructStubCountdown), | 6011 set_initial_map(heap->undefined_value()); |
| 6012 Builtins* builtins = heap->isolate()->builtins(); |
| 6013 ASSERT_EQ(builtins->builtin(Builtins::JSConstructStubCountdown), |
| 5899 construct_stub()); | 6014 construct_stub()); |
| 5900 set_construct_stub(Builtins::builtin(Builtins::JSConstructStubGeneric)); | 6015 set_construct_stub(builtins->builtin(Builtins::JSConstructStubGeneric)); |
| 5901 | 6016 |
| 5902 int slack = map->unused_property_fields(); | 6017 int slack = map->unused_property_fields(); |
| 5903 map->TraverseTransitionTree(&GetMinInobjectSlack, &slack); | 6018 map->TraverseTransitionTree(&GetMinInobjectSlack, &slack); |
| 5904 if (slack != 0) { | 6019 if (slack != 0) { |
| 5905 // Resize the initial map and all maps in its transition tree. | 6020 // Resize the initial map and all maps in its transition tree. |
| 5906 map->TraverseTransitionTree(&ShrinkInstanceSize, &slack); | 6021 map->TraverseTransitionTree(&ShrinkInstanceSize, &slack); |
| 5907 // Give the correct expected_nof_properties to initial maps created later. | 6022 // Give the correct expected_nof_properties to initial maps created later. |
| 5908 ASSERT(expected_nof_properties() >= slack); | 6023 ASSERT(expected_nof_properties() >= slack); |
| 5909 set_expected_nof_properties(expected_nof_properties() - slack); | 6024 set_expected_nof_properties(expected_nof_properties() - slack); |
| 5910 } | 6025 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5947 (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && | 6062 (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && |
| 5948 rinfo->IsPatchedDebugBreakSlotSequence())); | 6063 rinfo->IsPatchedDebugBreakSlotSequence())); |
| 5949 Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address()); | 6064 Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address()); |
| 5950 Object* old_target = target; | 6065 Object* old_target = target; |
| 5951 VisitPointer(&target); | 6066 VisitPointer(&target); |
| 5952 CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target. | 6067 CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target. |
| 5953 } | 6068 } |
| 5954 | 6069 |
| 5955 | 6070 |
| 5956 void Code::InvalidateRelocation() { | 6071 void Code::InvalidateRelocation() { |
| 5957 HandleScope scope; | 6072 set_relocation_info(GetHeap()->empty_byte_array()); |
| 5958 set_relocation_info(Heap::empty_byte_array()); | |
| 5959 } | 6073 } |
| 5960 | 6074 |
| 5961 | 6075 |
| 5962 void Code::Relocate(intptr_t delta) { | 6076 void Code::Relocate(intptr_t delta) { |
| 5963 for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) { | 6077 for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) { |
| 5964 it.rinfo()->apply(delta); | 6078 it.rinfo()->apply(delta); |
| 5965 } | 6079 } |
| 5966 CPU::FlushICache(instruction_start(), instruction_size()); | 6080 CPU::FlushICache(instruction_start(), instruction_size()); |
| 5967 } | 6081 } |
| 5968 | 6082 |
| (...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6394 | 6508 |
| 6395 PrintF("RelocInfo (size = %d)\n", relocation_size()); | 6509 PrintF("RelocInfo (size = %d)\n", relocation_size()); |
| 6396 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out); | 6510 for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out); |
| 6397 PrintF(out, "\n"); | 6511 PrintF(out, "\n"); |
| 6398 } | 6512 } |
| 6399 #endif // ENABLE_DISASSEMBLER | 6513 #endif // ENABLE_DISASSEMBLER |
| 6400 | 6514 |
| 6401 | 6515 |
| 6402 MaybeObject* JSObject::SetFastElementsCapacityAndLength(int capacity, | 6516 MaybeObject* JSObject::SetFastElementsCapacityAndLength(int capacity, |
| 6403 int length) { | 6517 int length) { |
| 6518 Heap* heap = GetHeap(); |
| 6404 // We should never end in here with a pixel or external array. | 6519 // We should never end in here with a pixel or external array. |
| 6405 ASSERT(!HasExternalArrayElements()); | 6520 ASSERT(!HasExternalArrayElements()); |
| 6406 | 6521 |
| 6407 Object* obj; | 6522 Object* obj; |
| 6408 { MaybeObject* maybe_obj = Heap::AllocateFixedArrayWithHoles(capacity); | 6523 { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(capacity); |
| 6409 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 6524 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 6410 } | 6525 } |
| 6411 FixedArray* elems = FixedArray::cast(obj); | 6526 FixedArray* elems = FixedArray::cast(obj); |
| 6412 | 6527 |
| 6413 { MaybeObject* maybe_obj = map()->GetFastElementsMap(); | 6528 { MaybeObject* maybe_obj = map()->GetFastElementsMap(); |
| 6414 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 6529 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 6415 } | 6530 } |
| 6416 Map* new_map = Map::cast(obj); | 6531 Map* new_map = Map::cast(obj); |
| 6417 | 6532 |
| 6418 AssertNoAllocation no_gc; | 6533 AssertNoAllocation no_gc; |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6485 } | 6600 } |
| 6486 default: | 6601 default: |
| 6487 UNREACHABLE(); | 6602 UNREACHABLE(); |
| 6488 break; | 6603 break; |
| 6489 } | 6604 } |
| 6490 return this; | 6605 return this; |
| 6491 } | 6606 } |
| 6492 | 6607 |
| 6493 | 6608 |
| 6494 MaybeObject* JSArray::Initialize(int capacity) { | 6609 MaybeObject* JSArray::Initialize(int capacity) { |
| 6610 Heap* heap = GetHeap(); |
| 6495 ASSERT(capacity >= 0); | 6611 ASSERT(capacity >= 0); |
| 6496 set_length(Smi::FromInt(0)); | 6612 set_length(Smi::FromInt(0)); |
| 6497 FixedArray* new_elements; | 6613 FixedArray* new_elements; |
| 6498 if (capacity == 0) { | 6614 if (capacity == 0) { |
| 6499 new_elements = Heap::empty_fixed_array(); | 6615 new_elements = heap->empty_fixed_array(); |
| 6500 } else { | 6616 } else { |
| 6501 Object* obj; | 6617 Object* obj; |
| 6502 { MaybeObject* maybe_obj = Heap::AllocateFixedArrayWithHoles(capacity); | 6618 { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(capacity); |
| 6503 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 6619 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 6504 } | 6620 } |
| 6505 new_elements = FixedArray::cast(obj); | 6621 new_elements = FixedArray::cast(obj); |
| 6506 } | 6622 } |
| 6507 set_elements(new_elements); | 6623 set_elements(new_elements); |
| 6508 return this; | 6624 return this; |
| 6509 } | 6625 } |
| 6510 | 6626 |
| 6511 | 6627 |
| 6512 void JSArray::Expand(int required_size) { | 6628 void JSArray::Expand(int required_size) { |
| 6513 Handle<JSArray> self(this); | 6629 Handle<JSArray> self(this); |
| 6514 Handle<FixedArray> old_backing(FixedArray::cast(elements())); | 6630 Handle<FixedArray> old_backing(FixedArray::cast(elements())); |
| 6515 int old_size = old_backing->length(); | 6631 int old_size = old_backing->length(); |
| 6516 int new_size = required_size > old_size ? required_size : old_size; | 6632 int new_size = required_size > old_size ? required_size : old_size; |
| 6517 Handle<FixedArray> new_backing = Factory::NewFixedArray(new_size); | 6633 Handle<FixedArray> new_backing = FACTORY->NewFixedArray(new_size); |
| 6518 // Can't use this any more now because we may have had a GC! | 6634 // Can't use this any more now because we may have had a GC! |
| 6519 for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i)); | 6635 for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i)); |
| 6520 self->SetContent(*new_backing); | 6636 self->SetContent(*new_backing); |
| 6521 } | 6637 } |
| 6522 | 6638 |
| 6523 | 6639 |
| 6524 static Failure* ArrayLengthRangeError() { | 6640 static Failure* ArrayLengthRangeError(Heap* heap) { |
| 6525 HandleScope scope; | 6641 HandleScope scope; |
| 6526 return Top::Throw(*Factory::NewRangeError("invalid_array_length", | 6642 return heap->isolate()->Throw( |
| 6527 HandleVector<Object>(NULL, 0))); | 6643 *FACTORY->NewRangeError("invalid_array_length", |
| 6644 HandleVector<Object>(NULL, 0))); |
| 6528 } | 6645 } |
| 6529 | 6646 |
| 6530 | 6647 |
| 6531 MaybeObject* JSObject::SetElementsLength(Object* len) { | 6648 MaybeObject* JSObject::SetElementsLength(Object* len) { |
| 6649 Heap* heap = GetHeap(); |
| 6532 // We should never end in here with a pixel or external array. | 6650 // We should never end in here with a pixel or external array. |
| 6533 ASSERT(AllowsSetElementsLength()); | 6651 ASSERT(AllowsSetElementsLength()); |
| 6534 | 6652 |
| 6535 MaybeObject* maybe_smi_length = len->ToSmi(); | 6653 MaybeObject* maybe_smi_length = len->ToSmi(); |
| 6536 Object* smi_length = Smi::FromInt(0); | 6654 Object* smi_length = Smi::FromInt(0); |
| 6537 if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) { | 6655 if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) { |
| 6538 const int value = Smi::cast(smi_length)->value(); | 6656 const int value = Smi::cast(smi_length)->value(); |
| 6539 if (value < 0) return ArrayLengthRangeError(); | 6657 if (value < 0) return ArrayLengthRangeError(heap); |
| 6540 switch (GetElementsKind()) { | 6658 switch (GetElementsKind()) { |
| 6541 case FAST_ELEMENTS: { | 6659 case FAST_ELEMENTS: { |
| 6542 int old_capacity = FixedArray::cast(elements())->length(); | 6660 int old_capacity = FixedArray::cast(elements())->length(); |
| 6543 if (value <= old_capacity) { | 6661 if (value <= old_capacity) { |
| 6544 if (IsJSArray()) { | 6662 if (IsJSArray()) { |
| 6545 Object* obj; | 6663 Object* obj; |
| 6546 { MaybeObject* maybe_obj = EnsureWritableFastElements(); | 6664 { MaybeObject* maybe_obj = EnsureWritableFastElements(); |
| 6547 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 6665 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 6548 } | 6666 } |
| 6549 int old_length = FastD2I(JSArray::cast(this)->length()->Number()); | 6667 int old_length = FastD2I(JSArray::cast(this)->length()->Number()); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6595 break; | 6713 break; |
| 6596 } | 6714 } |
| 6597 } | 6715 } |
| 6598 | 6716 |
| 6599 // General slow case. | 6717 // General slow case. |
| 6600 if (len->IsNumber()) { | 6718 if (len->IsNumber()) { |
| 6601 uint32_t length; | 6719 uint32_t length; |
| 6602 if (len->ToArrayIndex(&length)) { | 6720 if (len->ToArrayIndex(&length)) { |
| 6603 return SetSlowElements(len); | 6721 return SetSlowElements(len); |
| 6604 } else { | 6722 } else { |
| 6605 return ArrayLengthRangeError(); | 6723 return ArrayLengthRangeError(heap); |
| 6606 } | 6724 } |
| 6607 } | 6725 } |
| 6608 | 6726 |
| 6609 // len is not a number so make the array size one and | 6727 // len is not a number so make the array size one and |
| 6610 // set only element to len. | 6728 // set only element to len. |
| 6611 Object* obj; | 6729 Object* obj; |
| 6612 { MaybeObject* maybe_obj = Heap::AllocateFixedArray(1); | 6730 { MaybeObject* maybe_obj = heap->AllocateFixedArray(1); |
| 6613 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 6731 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 6614 } | 6732 } |
| 6615 FixedArray::cast(obj)->set(0, len); | 6733 FixedArray::cast(obj)->set(0, len); |
| 6616 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1)); | 6734 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1)); |
| 6617 set_elements(FixedArray::cast(obj)); | 6735 set_elements(FixedArray::cast(obj)); |
| 6618 return this; | 6736 return this; |
| 6619 } | 6737 } |
| 6620 | 6738 |
| 6621 | 6739 |
| 6622 MaybeObject* JSObject::SetPrototype(Object* value, | 6740 MaybeObject* JSObject::SetPrototype(Object* value, |
| 6623 bool skip_hidden_prototypes) { | 6741 bool skip_hidden_prototypes) { |
| 6742 Heap* heap = GetHeap(); |
| 6624 // Silently ignore the change if value is not a JSObject or null. | 6743 // Silently ignore the change if value is not a JSObject or null. |
| 6625 // SpiderMonkey behaves this way. | 6744 // SpiderMonkey behaves this way. |
| 6626 if (!value->IsJSObject() && !value->IsNull()) return value; | 6745 if (!value->IsJSObject() && !value->IsNull()) return value; |
| 6627 | 6746 |
| 6628 // Before we can set the prototype we need to be sure | 6747 // Before we can set the prototype we need to be sure |
| 6629 // prototype cycles are prevented. | 6748 // prototype cycles are prevented. |
| 6630 // It is sufficient to validate that the receiver is not in the new prototype | 6749 // It is sufficient to validate that the receiver is not in the new prototype |
| 6631 // chain. | 6750 // chain. |
| 6632 for (Object* pt = value; pt != Heap::null_value(); pt = pt->GetPrototype()) { | 6751 for (Object* pt = value; pt != heap->null_value(); pt = pt->GetPrototype()) { |
| 6633 if (JSObject::cast(pt) == this) { | 6752 if (JSObject::cast(pt) == this) { |
| 6634 // Cycle detected. | 6753 // Cycle detected. |
| 6635 HandleScope scope; | 6754 HandleScope scope; |
| 6636 return Top::Throw(*Factory::NewError("cyclic_proto", | 6755 return heap->isolate()->Throw( |
| 6637 HandleVector<Object>(NULL, 0))); | 6756 *FACTORY->NewError("cyclic_proto", HandleVector<Object>(NULL, 0))); |
| 6638 } | 6757 } |
| 6639 } | 6758 } |
| 6640 | 6759 |
| 6641 JSObject* real_receiver = this; | 6760 JSObject* real_receiver = this; |
| 6642 | 6761 |
| 6643 if (skip_hidden_prototypes) { | 6762 if (skip_hidden_prototypes) { |
| 6644 // Find the first object in the chain whose prototype object is not | 6763 // Find the first object in the chain whose prototype object is not |
| 6645 // hidden and set the new prototype on that object. | 6764 // hidden and set the new prototype on that object. |
| 6646 Object* current_proto = real_receiver->GetPrototype(); | 6765 Object* current_proto = real_receiver->GetPrototype(); |
| 6647 while (current_proto->IsJSObject() && | 6766 while (current_proto->IsJSObject() && |
| 6648 JSObject::cast(current_proto)->map()->is_hidden_prototype()) { | 6767 JSObject::cast(current_proto)->map()->is_hidden_prototype()) { |
| 6649 real_receiver = JSObject::cast(current_proto); | 6768 real_receiver = JSObject::cast(current_proto); |
| 6650 current_proto = current_proto->GetPrototype(); | 6769 current_proto = current_proto->GetPrototype(); |
| 6651 } | 6770 } |
| 6652 } | 6771 } |
| 6653 | 6772 |
| 6654 // Set the new prototype of the object. | 6773 // Set the new prototype of the object. |
| 6655 Object* new_map; | 6774 Object* new_map; |
| 6656 { MaybeObject* maybe_new_map = real_receiver->map()->CopyDropTransitions(); | 6775 { MaybeObject* maybe_new_map = real_receiver->map()->CopyDropTransitions(); |
| 6657 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; | 6776 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; |
| 6658 } | 6777 } |
| 6659 Map::cast(new_map)->set_prototype(value); | 6778 Map::cast(new_map)->set_prototype(value); |
| 6660 real_receiver->set_map(Map::cast(new_map)); | 6779 real_receiver->set_map(Map::cast(new_map)); |
| 6661 | 6780 |
| 6662 Heap::ClearInstanceofCache(); | 6781 heap->ClearInstanceofCache(); |
| 6663 | 6782 |
| 6664 return value; | 6783 return value; |
| 6665 } | 6784 } |
| 6666 | 6785 |
| 6667 | 6786 |
| 6668 bool JSObject::HasElementPostInterceptor(JSObject* receiver, uint32_t index) { | 6787 bool JSObject::HasElementPostInterceptor(JSObject* receiver, uint32_t index) { |
| 6669 switch (GetElementsKind()) { | 6788 switch (GetElementsKind()) { |
| 6670 case FAST_ELEMENTS: { | 6789 case FAST_ELEMENTS: { |
| 6671 uint32_t length = IsJSArray() ? | 6790 uint32_t length = IsJSArray() ? |
| 6672 static_cast<uint32_t> | 6791 static_cast<uint32_t> |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6707 } | 6826 } |
| 6708 default: | 6827 default: |
| 6709 UNREACHABLE(); | 6828 UNREACHABLE(); |
| 6710 break; | 6829 break; |
| 6711 } | 6830 } |
| 6712 | 6831 |
| 6713 // Handle [] on String objects. | 6832 // Handle [] on String objects. |
| 6714 if (this->IsStringObjectWithCharacterAt(index)) return true; | 6833 if (this->IsStringObjectWithCharacterAt(index)) return true; |
| 6715 | 6834 |
| 6716 Object* pt = GetPrototype(); | 6835 Object* pt = GetPrototype(); |
| 6717 if (pt == Heap::null_value()) return false; | 6836 if (pt->IsNull()) return false; |
| 6718 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); | 6837 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); |
| 6719 } | 6838 } |
| 6720 | 6839 |
| 6721 | 6840 |
| 6722 bool JSObject::HasElementWithInterceptor(JSObject* receiver, uint32_t index) { | 6841 bool JSObject::HasElementWithInterceptor(JSObject* receiver, uint32_t index) { |
| 6842 Isolate* isolate = GetIsolate(); |
| 6723 // Make sure that the top context does not change when doing | 6843 // Make sure that the top context does not change when doing |
| 6724 // callbacks or interceptor calls. | 6844 // callbacks or interceptor calls. |
| 6725 AssertNoContextChange ncc; | 6845 AssertNoContextChange ncc; |
| 6726 HandleScope scope; | 6846 HandleScope scope(isolate); |
| 6727 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); | 6847 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); |
| 6728 Handle<JSObject> receiver_handle(receiver); | 6848 Handle<JSObject> receiver_handle(receiver); |
| 6729 Handle<JSObject> holder_handle(this); | 6849 Handle<JSObject> holder_handle(this); |
| 6730 CustomArguments args(interceptor->data(), receiver, this); | 6850 CustomArguments args(isolate, interceptor->data(), receiver, this); |
| 6731 v8::AccessorInfo info(args.end()); | 6851 v8::AccessorInfo info(args.end()); |
| 6732 if (!interceptor->query()->IsUndefined()) { | 6852 if (!interceptor->query()->IsUndefined()) { |
| 6733 v8::IndexedPropertyQuery query = | 6853 v8::IndexedPropertyQuery query = |
| 6734 v8::ToCData<v8::IndexedPropertyQuery>(interceptor->query()); | 6854 v8::ToCData<v8::IndexedPropertyQuery>(interceptor->query()); |
| 6735 LOG(ApiIndexedPropertyAccess("interceptor-indexed-has", this, index)); | 6855 LOG(isolate, |
| 6856 ApiIndexedPropertyAccess("interceptor-indexed-has", this, index)); |
| 6736 v8::Handle<v8::Integer> result; | 6857 v8::Handle<v8::Integer> result; |
| 6737 { | 6858 { |
| 6738 // Leaving JavaScript. | 6859 // Leaving JavaScript. |
| 6739 VMState state(EXTERNAL); | 6860 VMState state(isolate, EXTERNAL); |
| 6740 result = query(index, info); | 6861 result = query(index, info); |
| 6741 } | 6862 } |
| 6742 if (!result.IsEmpty()) { | 6863 if (!result.IsEmpty()) { |
| 6743 ASSERT(result->IsInt32()); | 6864 ASSERT(result->IsInt32()); |
| 6744 return true; // absence of property is signaled by empty handle. | 6865 return true; // absence of property is signaled by empty handle. |
| 6745 } | 6866 } |
| 6746 } else if (!interceptor->getter()->IsUndefined()) { | 6867 } else if (!interceptor->getter()->IsUndefined()) { |
| 6747 v8::IndexedPropertyGetter getter = | 6868 v8::IndexedPropertyGetter getter = |
| 6748 v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter()); | 6869 v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter()); |
| 6749 LOG(ApiIndexedPropertyAccess("interceptor-indexed-has-get", this, index)); | 6870 LOG(isolate, |
| 6871 ApiIndexedPropertyAccess("interceptor-indexed-has-get", this, index)); |
| 6750 v8::Handle<v8::Value> result; | 6872 v8::Handle<v8::Value> result; |
| 6751 { | 6873 { |
| 6752 // Leaving JavaScript. | 6874 // Leaving JavaScript. |
| 6753 VMState state(EXTERNAL); | 6875 VMState state(isolate, EXTERNAL); |
| 6754 result = getter(index, info); | 6876 result = getter(index, info); |
| 6755 } | 6877 } |
| 6756 if (!result.IsEmpty()) return true; | 6878 if (!result.IsEmpty()) return true; |
| 6757 } | 6879 } |
| 6758 return holder_handle->HasElementPostInterceptor(*receiver_handle, index); | 6880 return holder_handle->HasElementPostInterceptor(*receiver_handle, index); |
| 6759 } | 6881 } |
| 6760 | 6882 |
| 6761 | 6883 |
| 6762 JSObject::LocalElementType JSObject::HasLocalElement(uint32_t index) { | 6884 JSObject::LocalElementType JSObject::HasLocalElement(uint32_t index) { |
| 6885 Heap* heap = GetHeap(); |
| 6886 |
| 6763 // Check access rights if needed. | 6887 // Check access rights if needed. |
| 6764 if (IsAccessCheckNeeded() && | 6888 if (IsAccessCheckNeeded() && |
| 6765 !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 6889 !heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { |
| 6766 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 6890 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 6767 return UNDEFINED_ELEMENT; | 6891 return UNDEFINED_ELEMENT; |
| 6768 } | 6892 } |
| 6769 | 6893 |
| 6770 if (IsJSGlobalProxy()) { | 6894 if (IsJSGlobalProxy()) { |
| 6771 Object* proto = GetPrototype(); | 6895 Object* proto = GetPrototype(); |
| 6772 if (proto->IsNull()) return UNDEFINED_ELEMENT; | 6896 if (proto->IsNull()) return UNDEFINED_ELEMENT; |
| 6773 ASSERT(proto->IsJSGlobalObject()); | 6897 ASSERT(proto->IsJSGlobalObject()); |
| 6774 return JSObject::cast(proto)->HasLocalElement(index); | 6898 return JSObject::cast(proto)->HasLocalElement(index); |
| 6775 } | 6899 } |
| 6776 | 6900 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6823 default: | 6947 default: |
| 6824 UNREACHABLE(); | 6948 UNREACHABLE(); |
| 6825 break; | 6949 break; |
| 6826 } | 6950 } |
| 6827 | 6951 |
| 6828 return UNDEFINED_ELEMENT; | 6952 return UNDEFINED_ELEMENT; |
| 6829 } | 6953 } |
| 6830 | 6954 |
| 6831 | 6955 |
| 6832 bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) { | 6956 bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) { |
| 6957 Heap* heap = GetHeap(); |
| 6958 |
| 6833 // Check access rights if needed. | 6959 // Check access rights if needed. |
| 6834 if (IsAccessCheckNeeded() && | 6960 if (IsAccessCheckNeeded() && |
| 6835 !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 6961 !heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { |
| 6836 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 6962 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 6837 return false; | 6963 return false; |
| 6838 } | 6964 } |
| 6839 | 6965 |
| 6840 // Check for lookup interceptor | 6966 // Check for lookup interceptor |
| 6841 if (HasIndexedInterceptor()) { | 6967 if (HasIndexedInterceptor()) { |
| 6842 return HasElementWithInterceptor(receiver, index); | 6968 return HasElementWithInterceptor(receiver, index); |
| 6843 } | 6969 } |
| 6844 | 6970 |
| 6845 switch (GetElementsKind()) { | 6971 switch (GetElementsKind()) { |
| 6846 case FAST_ELEMENTS: { | 6972 case FAST_ELEMENTS: { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6881 } | 7007 } |
| 6882 default: | 7008 default: |
| 6883 UNREACHABLE(); | 7009 UNREACHABLE(); |
| 6884 break; | 7010 break; |
| 6885 } | 7011 } |
| 6886 | 7012 |
| 6887 // Handle [] on String objects. | 7013 // Handle [] on String objects. |
| 6888 if (this->IsStringObjectWithCharacterAt(index)) return true; | 7014 if (this->IsStringObjectWithCharacterAt(index)) return true; |
| 6889 | 7015 |
| 6890 Object* pt = GetPrototype(); | 7016 Object* pt = GetPrototype(); |
| 6891 if (pt == Heap::null_value()) return false; | 7017 if (pt->IsNull()) return false; |
| 6892 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); | 7018 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); |
| 6893 } | 7019 } |
| 6894 | 7020 |
| 6895 | 7021 |
| 6896 MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index, | 7022 MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index, |
| 6897 Object* value, | 7023 Object* value, |
| 6898 StrictModeFlag strict_mode, | 7024 StrictModeFlag strict_mode, |
| 6899 bool check_prototype) { | 7025 bool check_prototype) { |
| 7026 Isolate* isolate = GetIsolate(); |
| 6900 // Make sure that the top context does not change when doing | 7027 // Make sure that the top context does not change when doing |
| 6901 // callbacks or interceptor calls. | 7028 // callbacks or interceptor calls. |
| 6902 AssertNoContextChange ncc; | 7029 AssertNoContextChange ncc; |
| 6903 HandleScope scope; | 7030 HandleScope scope(isolate); |
| 6904 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); | 7031 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); |
| 6905 Handle<JSObject> this_handle(this); | 7032 Handle<JSObject> this_handle(this); |
| 6906 Handle<Object> value_handle(value); | 7033 Handle<Object> value_handle(value, isolate); |
| 6907 if (!interceptor->setter()->IsUndefined()) { | 7034 if (!interceptor->setter()->IsUndefined()) { |
| 6908 v8::IndexedPropertySetter setter = | 7035 v8::IndexedPropertySetter setter = |
| 6909 v8::ToCData<v8::IndexedPropertySetter>(interceptor->setter()); | 7036 v8::ToCData<v8::IndexedPropertySetter>(interceptor->setter()); |
| 6910 LOG(ApiIndexedPropertyAccess("interceptor-indexed-set", this, index)); | 7037 LOG(isolate, |
| 6911 CustomArguments args(interceptor->data(), this, this); | 7038 ApiIndexedPropertyAccess("interceptor-indexed-set", this, index)); |
| 7039 CustomArguments args(isolate, interceptor->data(), this, this); |
| 6912 v8::AccessorInfo info(args.end()); | 7040 v8::AccessorInfo info(args.end()); |
| 6913 v8::Handle<v8::Value> result; | 7041 v8::Handle<v8::Value> result; |
| 6914 { | 7042 { |
| 6915 // Leaving JavaScript. | 7043 // Leaving JavaScript. |
| 6916 VMState state(EXTERNAL); | 7044 VMState state(isolate, EXTERNAL); |
| 6917 result = setter(index, v8::Utils::ToLocal(value_handle), info); | 7045 result = setter(index, v8::Utils::ToLocal(value_handle), info); |
| 6918 } | 7046 } |
| 6919 RETURN_IF_SCHEDULED_EXCEPTION(); | 7047 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 6920 if (!result.IsEmpty()) return *value_handle; | 7048 if (!result.IsEmpty()) return *value_handle; |
| 6921 } | 7049 } |
| 6922 MaybeObject* raw_result = | 7050 MaybeObject* raw_result = |
| 6923 this_handle->SetElementWithoutInterceptor(index, | 7051 this_handle->SetElementWithoutInterceptor(index, |
| 6924 *value_handle, | 7052 *value_handle, |
| 6925 strict_mode, | 7053 strict_mode, |
| 6926 check_prototype); | 7054 check_prototype); |
| 6927 RETURN_IF_SCHEDULED_EXCEPTION(); | 7055 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 6928 return raw_result; | 7056 return raw_result; |
| 6929 } | 7057 } |
| 6930 | 7058 |
| 6931 | 7059 |
| 6932 MaybeObject* JSObject::GetElementWithCallback(Object* receiver, | 7060 MaybeObject* JSObject::GetElementWithCallback(Object* receiver, |
| 6933 Object* structure, | 7061 Object* structure, |
| 6934 uint32_t index, | 7062 uint32_t index, |
| 6935 Object* holder) { | 7063 Object* holder) { |
| 7064 Isolate* isolate = GetIsolate(); |
| 6936 ASSERT(!structure->IsProxy()); | 7065 ASSERT(!structure->IsProxy()); |
| 6937 | 7066 |
| 6938 // api style callbacks. | 7067 // api style callbacks. |
| 6939 if (structure->IsAccessorInfo()) { | 7068 if (structure->IsAccessorInfo()) { |
| 6940 AccessorInfo* data = AccessorInfo::cast(structure); | 7069 AccessorInfo* data = AccessorInfo::cast(structure); |
| 6941 Object* fun_obj = data->getter(); | 7070 Object* fun_obj = data->getter(); |
| 6942 v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj); | 7071 v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj); |
| 6943 HandleScope scope; | 7072 HandleScope scope(isolate); |
| 6944 Handle<JSObject> self(JSObject::cast(receiver)); | 7073 Handle<JSObject> self(JSObject::cast(receiver)); |
| 6945 Handle<JSObject> holder_handle(JSObject::cast(holder)); | 7074 Handle<JSObject> holder_handle(JSObject::cast(holder)); |
| 6946 Handle<Object> number = Factory::NewNumberFromUint(index); | 7075 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
| 6947 Handle<String> key(Factory::NumberToString(number)); | 7076 Handle<String> key(isolate->factory()->NumberToString(number)); |
| 6948 LOG(ApiNamedPropertyAccess("load", *self, *key)); | 7077 LOG(isolate, ApiNamedPropertyAccess("load", *self, *key)); |
| 6949 CustomArguments args(data->data(), *self, *holder_handle); | 7078 CustomArguments args(isolate, data->data(), *self, *holder_handle); |
| 6950 v8::AccessorInfo info(args.end()); | 7079 v8::AccessorInfo info(args.end()); |
| 6951 v8::Handle<v8::Value> result; | 7080 v8::Handle<v8::Value> result; |
| 6952 { | 7081 { |
| 6953 // Leaving JavaScript. | 7082 // Leaving JavaScript. |
| 6954 VMState state(EXTERNAL); | 7083 VMState state(isolate, EXTERNAL); |
| 6955 result = call_fun(v8::Utils::ToLocal(key), info); | 7084 result = call_fun(v8::Utils::ToLocal(key), info); |
| 6956 } | 7085 } |
| 6957 RETURN_IF_SCHEDULED_EXCEPTION(); | 7086 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 6958 if (result.IsEmpty()) return Heap::undefined_value(); | 7087 if (result.IsEmpty()) return isolate->heap()->undefined_value(); |
| 6959 return *v8::Utils::OpenHandle(*result); | 7088 return *v8::Utils::OpenHandle(*result); |
| 6960 } | 7089 } |
| 6961 | 7090 |
| 6962 // __defineGetter__ callback | 7091 // __defineGetter__ callback |
| 6963 if (structure->IsFixedArray()) { | 7092 if (structure->IsFixedArray()) { |
| 6964 Object* getter = FixedArray::cast(structure)->get(kGetterIndex); | 7093 Object* getter = FixedArray::cast(structure)->get(kGetterIndex); |
| 6965 if (getter->IsJSFunction()) { | 7094 if (getter->IsJSFunction()) { |
| 6966 return Object::GetPropertyWithDefinedGetter(receiver, | 7095 return Object::GetPropertyWithDefinedGetter(receiver, |
| 6967 JSFunction::cast(getter)); | 7096 JSFunction::cast(getter)); |
| 6968 } | 7097 } |
| 6969 // Getter is not a function. | 7098 // Getter is not a function. |
| 6970 return Heap::undefined_value(); | 7099 return isolate->heap()->undefined_value(); |
| 6971 } | 7100 } |
| 6972 | 7101 |
| 6973 UNREACHABLE(); | 7102 UNREACHABLE(); |
| 6974 return NULL; | 7103 return NULL; |
| 6975 } | 7104 } |
| 6976 | 7105 |
| 6977 | 7106 |
| 6978 MaybeObject* JSObject::SetElementWithCallback(Object* structure, | 7107 MaybeObject* JSObject::SetElementWithCallback(Object* structure, |
| 6979 uint32_t index, | 7108 uint32_t index, |
| 6980 Object* value, | 7109 Object* value, |
| 6981 JSObject* holder) { | 7110 JSObject* holder) { |
| 6982 HandleScope scope; | 7111 Isolate* isolate = GetIsolate(); |
| 7112 HandleScope scope(isolate); |
| 6983 | 7113 |
| 6984 // We should never get here to initialize a const with the hole | 7114 // We should never get here to initialize a const with the hole |
| 6985 // value since a const declaration would conflict with the setter. | 7115 // value since a const declaration would conflict with the setter. |
| 6986 ASSERT(!value->IsTheHole()); | 7116 ASSERT(!value->IsTheHole()); |
| 6987 Handle<Object> value_handle(value); | 7117 Handle<Object> value_handle(value, isolate); |
| 6988 | 7118 |
| 6989 // To accommodate both the old and the new api we switch on the | 7119 // To accommodate both the old and the new api we switch on the |
| 6990 // data structure used to store the callbacks. Eventually proxy | 7120 // data structure used to store the callbacks. Eventually proxy |
| 6991 // callbacks should be phased out. | 7121 // callbacks should be phased out. |
| 6992 ASSERT(!structure->IsProxy()); | 7122 ASSERT(!structure->IsProxy()); |
| 6993 | 7123 |
| 6994 if (structure->IsAccessorInfo()) { | 7124 if (structure->IsAccessorInfo()) { |
| 6995 // api style callbacks | 7125 // api style callbacks |
| 6996 AccessorInfo* data = AccessorInfo::cast(structure); | 7126 AccessorInfo* data = AccessorInfo::cast(structure); |
| 6997 Object* call_obj = data->setter(); | 7127 Object* call_obj = data->setter(); |
| 6998 v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj); | 7128 v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj); |
| 6999 if (call_fun == NULL) return value; | 7129 if (call_fun == NULL) return value; |
| 7000 Handle<Object> number = Factory::NewNumberFromUint(index); | 7130 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
| 7001 Handle<String> key(Factory::NumberToString(number)); | 7131 Handle<String> key(isolate->factory()->NumberToString(number)); |
| 7002 LOG(ApiNamedPropertyAccess("store", this, *key)); | 7132 LOG(isolate, ApiNamedPropertyAccess("store", this, *key)); |
| 7003 CustomArguments args(data->data(), this, JSObject::cast(holder)); | 7133 CustomArguments args(isolate, data->data(), this, JSObject::cast(holder)); |
| 7004 v8::AccessorInfo info(args.end()); | 7134 v8::AccessorInfo info(args.end()); |
| 7005 { | 7135 { |
| 7006 // Leaving JavaScript. | 7136 // Leaving JavaScript. |
| 7007 VMState state(EXTERNAL); | 7137 VMState state(isolate, EXTERNAL); |
| 7008 call_fun(v8::Utils::ToLocal(key), | 7138 call_fun(v8::Utils::ToLocal(key), |
| 7009 v8::Utils::ToLocal(value_handle), | 7139 v8::Utils::ToLocal(value_handle), |
| 7010 info); | 7140 info); |
| 7011 } | 7141 } |
| 7012 RETURN_IF_SCHEDULED_EXCEPTION(); | 7142 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 7013 return *value_handle; | 7143 return *value_handle; |
| 7014 } | 7144 } |
| 7015 | 7145 |
| 7016 if (structure->IsFixedArray()) { | 7146 if (structure->IsFixedArray()) { |
| 7017 Object* setter = FixedArray::cast(structure)->get(kSetterIndex); | 7147 Object* setter = FixedArray::cast(structure)->get(kSetterIndex); |
| 7018 if (setter->IsJSFunction()) { | 7148 if (setter->IsJSFunction()) { |
| 7019 return SetPropertyWithDefinedSetter(JSFunction::cast(setter), value); | 7149 return SetPropertyWithDefinedSetter(JSFunction::cast(setter), value); |
| 7020 } else { | 7150 } else { |
| 7021 Handle<Object> holder_handle(holder); | 7151 Handle<Object> holder_handle(holder, isolate); |
| 7022 Handle<Object> key(Factory::NewNumberFromUint(index)); | 7152 Handle<Object> key(isolate->factory()->NewNumberFromUint(index)); |
| 7023 Handle<Object> args[2] = { key, holder_handle }; | 7153 Handle<Object> args[2] = { key, holder_handle }; |
| 7024 return Top::Throw(*Factory::NewTypeError("no_setter_in_callback", | 7154 return isolate->Throw( |
| 7025 HandleVector(args, 2))); | 7155 *isolate->factory()->NewTypeError("no_setter_in_callback", |
| 7156 HandleVector(args, 2))); |
| 7026 } | 7157 } |
| 7027 } | 7158 } |
| 7028 | 7159 |
| 7029 UNREACHABLE(); | 7160 UNREACHABLE(); |
| 7030 return NULL; | 7161 return NULL; |
| 7031 } | 7162 } |
| 7032 | 7163 |
| 7033 | 7164 |
| 7034 // Adding n elements in fast case is O(n*n). | 7165 // Adding n elements in fast case is O(n*n). |
| 7035 // Note: revisit design to have dual undefined values to capture absent | 7166 // Note: revisit design to have dual undefined values to capture absent |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7094 } | 7225 } |
| 7095 ASSERT(HasDictionaryElements()); | 7226 ASSERT(HasDictionaryElements()); |
| 7096 return SetElement(index, value, strict_mode, check_prototype); | 7227 return SetElement(index, value, strict_mode, check_prototype); |
| 7097 } | 7228 } |
| 7098 | 7229 |
| 7099 | 7230 |
| 7100 MaybeObject* JSObject::SetElement(uint32_t index, | 7231 MaybeObject* JSObject::SetElement(uint32_t index, |
| 7101 Object* value, | 7232 Object* value, |
| 7102 StrictModeFlag strict_mode, | 7233 StrictModeFlag strict_mode, |
| 7103 bool check_prototype) { | 7234 bool check_prototype) { |
| 7235 Heap* heap = GetHeap(); |
| 7104 // Check access rights if needed. | 7236 // Check access rights if needed. |
| 7105 if (IsAccessCheckNeeded() && | 7237 if (IsAccessCheckNeeded() && |
| 7106 !Top::MayIndexedAccess(this, index, v8::ACCESS_SET)) { | 7238 !heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_SET)) { |
| 7107 HandleScope scope; | 7239 HandleScope scope; |
| 7108 Handle<Object> value_handle(value); | 7240 Handle<Object> value_handle(value); |
| 7109 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); | 7241 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET); |
| 7110 return *value_handle; | 7242 return *value_handle; |
| 7111 } | 7243 } |
| 7112 | 7244 |
| 7113 if (IsJSGlobalProxy()) { | 7245 if (IsJSGlobalProxy()) { |
| 7114 Object* proto = GetPrototype(); | 7246 Object* proto = GetPrototype(); |
| 7115 if (proto->IsNull()) return value; | 7247 if (proto->IsNull()) return value; |
| 7116 ASSERT(proto->IsJSGlobalObject()); | 7248 ASSERT(proto->IsJSGlobalObject()); |
| 7117 return JSObject::cast(proto)->SetElement(index, | 7249 return JSObject::cast(proto)->SetElement(index, |
| 7118 value, | 7250 value, |
| 7119 strict_mode, | 7251 strict_mode, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 7132 value, | 7264 value, |
| 7133 strict_mode, | 7265 strict_mode, |
| 7134 check_prototype); | 7266 check_prototype); |
| 7135 } | 7267 } |
| 7136 | 7268 |
| 7137 | 7269 |
| 7138 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, | 7270 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, |
| 7139 Object* value, | 7271 Object* value, |
| 7140 StrictModeFlag strict_mode, | 7272 StrictModeFlag strict_mode, |
| 7141 bool check_prototype) { | 7273 bool check_prototype) { |
| 7274 Isolate* isolate = GetIsolate(); |
| 7142 switch (GetElementsKind()) { | 7275 switch (GetElementsKind()) { |
| 7143 case FAST_ELEMENTS: | 7276 case FAST_ELEMENTS: |
| 7144 // Fast case. | 7277 // Fast case. |
| 7145 return SetFastElement(index, value, strict_mode, check_prototype); | 7278 return SetFastElement(index, value, strict_mode, check_prototype); |
| 7146 case EXTERNAL_PIXEL_ELEMENTS: { | 7279 case EXTERNAL_PIXEL_ELEMENTS: { |
| 7147 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); | 7280 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); |
| 7148 return pixels->SetValue(index, value); | 7281 return pixels->SetValue(index, value); |
| 7149 } | 7282 } |
| 7150 case EXTERNAL_BYTE_ELEMENTS: { | 7283 case EXTERNAL_BYTE_ELEMENTS: { |
| 7151 ExternalByteArray* array = ExternalByteArray::cast(elements()); | 7284 ExternalByteArray* array = ExternalByteArray::cast(elements()); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7187 if (entry != NumberDictionary::kNotFound) { | 7320 if (entry != NumberDictionary::kNotFound) { |
| 7188 Object* element = dictionary->ValueAt(entry); | 7321 Object* element = dictionary->ValueAt(entry); |
| 7189 PropertyDetails details = dictionary->DetailsAt(entry); | 7322 PropertyDetails details = dictionary->DetailsAt(entry); |
| 7190 if (details.type() == CALLBACKS) { | 7323 if (details.type() == CALLBACKS) { |
| 7191 return SetElementWithCallback(element, index, value, this); | 7324 return SetElementWithCallback(element, index, value, this); |
| 7192 } else { | 7325 } else { |
| 7193 dictionary->UpdateMaxNumberKey(index); | 7326 dictionary->UpdateMaxNumberKey(index); |
| 7194 // If put fails instrict mode, throw exception. | 7327 // If put fails instrict mode, throw exception. |
| 7195 if (!dictionary->ValueAtPut(entry, value) && | 7328 if (!dictionary->ValueAtPut(entry, value) && |
| 7196 strict_mode == kStrictMode) { | 7329 strict_mode == kStrictMode) { |
| 7197 Handle<Object> number(Factory::NewNumberFromUint(index)); | 7330 Handle<Object> number(isolate->factory()->NewNumberFromUint(index)); |
| 7198 Handle<Object> holder(this); | 7331 Handle<Object> holder(this); |
| 7199 Handle<Object> args[2] = { number, holder }; | 7332 Handle<Object> args[2] = { number, holder }; |
| 7200 return Top::Throw( | 7333 return isolate->Throw( |
| 7201 *Factory::NewTypeError("strict_read_only_property", | 7334 *isolate->factory()->NewTypeError("strict_read_only_property", |
| 7202 HandleVector(args, 2))); | 7335 HandleVector(args, 2))); |
| 7203 } | 7336 } |
| 7204 } | 7337 } |
| 7205 } else { | 7338 } else { |
| 7206 // Index not already used. Look for an accessor in the prototype chain. | 7339 // Index not already used. Look for an accessor in the prototype chain. |
| 7207 if (check_prototype) { | 7340 if (check_prototype) { |
| 7208 bool found; | 7341 bool found; |
| 7209 MaybeObject* result = | 7342 MaybeObject* result = |
| 7210 // Strict mode not needed. No-setter case already handled. | 7343 // Strict mode not needed. No-setter case already handled. |
| 7211 SetElementWithCallbackSetterInPrototypes(index, value, &found); | 7344 SetElementWithCallbackSetterInPrototypes(index, value, &found); |
| 7212 if (found) return result; | 7345 if (found) return result; |
| 7213 } | 7346 } |
| 7214 // When we set the is_extensible flag to false we always force | 7347 // When we set the is_extensible flag to false we always force |
| 7215 // the element into dictionary mode (and force them to stay there). | 7348 // the element into dictionary mode (and force them to stay there). |
| 7216 if (!map()->is_extensible()) { | 7349 if (!map()->is_extensible()) { |
| 7217 Handle<Object> number(Factory::NewNumberFromUint(index)); | 7350 Handle<Object> number(isolate->factory()->NewNumberFromUint(index)); |
| 7218 Handle<String> index_string(Factory::NumberToString(number)); | 7351 Handle<String> index_string( |
| 7352 isolate->factory()->NumberToString(number)); |
| 7219 Handle<Object> args[1] = { index_string }; | 7353 Handle<Object> args[1] = { index_string }; |
| 7220 return Top::Throw(*Factory::NewTypeError("object_not_extensible", | 7354 return isolate->Throw( |
| 7221 HandleVector(args, 1))); | 7355 *isolate->factory()->NewTypeError("object_not_extensible", |
| 7356 HandleVector(args, 1))); |
| 7222 } | 7357 } |
| 7223 Object* result; | 7358 Object* result; |
| 7224 { MaybeObject* maybe_result = dictionary->AtNumberPut(index, value); | 7359 { MaybeObject* maybe_result = dictionary->AtNumberPut(index, value); |
| 7225 if (!maybe_result->ToObject(&result)) return maybe_result; | 7360 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 7226 } | 7361 } |
| 7227 if (elms != FixedArray::cast(result)) { | 7362 if (elms != FixedArray::cast(result)) { |
| 7228 set_elements(FixedArray::cast(result)); | 7363 set_elements(FixedArray::cast(result)); |
| 7229 } | 7364 } |
| 7230 } | 7365 } |
| 7231 | 7366 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7264 | 7399 |
| 7265 return value; | 7400 return value; |
| 7266 } | 7401 } |
| 7267 default: | 7402 default: |
| 7268 UNREACHABLE(); | 7403 UNREACHABLE(); |
| 7269 break; | 7404 break; |
| 7270 } | 7405 } |
| 7271 // All possible cases have been handled above. Add a return to avoid the | 7406 // All possible cases have been handled above. Add a return to avoid the |
| 7272 // complaints from the compiler. | 7407 // complaints from the compiler. |
| 7273 UNREACHABLE(); | 7408 UNREACHABLE(); |
| 7274 return Heap::null_value(); | 7409 return isolate->heap()->null_value(); |
| 7275 } | 7410 } |
| 7276 | 7411 |
| 7277 | 7412 |
| 7278 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, | 7413 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, |
| 7279 Object* value) { | 7414 Object* value) { |
| 7280 uint32_t old_len = 0; | 7415 uint32_t old_len = 0; |
| 7281 CHECK(length()->ToArrayIndex(&old_len)); | 7416 CHECK(length()->ToArrayIndex(&old_len)); |
| 7282 // Check to see if we need to update the length. For now, we make | 7417 // Check to see if we need to update the length. For now, we make |
| 7283 // sure that the length stays within 32-bits (unsigned). | 7418 // sure that the length stays within 32-bits (unsigned). |
| 7284 if (index >= old_len && index != 0xffffffff) { | 7419 if (index >= old_len && index != 0xffffffff) { |
| 7285 Object* len; | 7420 Object* len; |
| 7286 { MaybeObject* maybe_len = | 7421 { MaybeObject* maybe_len = |
| 7287 Heap::NumberFromDouble(static_cast<double>(index) + 1); | 7422 GetHeap()->NumberFromDouble(static_cast<double>(index) + 1); |
| 7288 if (!maybe_len->ToObject(&len)) return maybe_len; | 7423 if (!maybe_len->ToObject(&len)) return maybe_len; |
| 7289 } | 7424 } |
| 7290 set_length(len); | 7425 set_length(len); |
| 7291 } | 7426 } |
| 7292 return value; | 7427 return value; |
| 7293 } | 7428 } |
| 7294 | 7429 |
| 7295 | 7430 |
| 7296 MaybeObject* JSObject::GetElementPostInterceptor(Object* receiver, | 7431 MaybeObject* JSObject::GetElementPostInterceptor(Object* receiver, |
| 7297 uint32_t index) { | 7432 uint32_t index) { |
| 7433 Heap* heap = GetHeap(); |
| 7298 // Get element works for both JSObject and JSArray since | 7434 // Get element works for both JSObject and JSArray since |
| 7299 // JSArray::length cannot change. | 7435 // JSArray::length cannot change. |
| 7300 switch (GetElementsKind()) { | 7436 switch (GetElementsKind()) { |
| 7301 case FAST_ELEMENTS: { | 7437 case FAST_ELEMENTS: { |
| 7302 FixedArray* elms = FixedArray::cast(elements()); | 7438 FixedArray* elms = FixedArray::cast(elements()); |
| 7303 if (index < static_cast<uint32_t>(elms->length())) { | 7439 if (index < static_cast<uint32_t>(elms->length())) { |
| 7304 Object* value = elms->get(index); | 7440 Object* value = elms->get(index); |
| 7305 if (!value->IsTheHole()) return value; | 7441 if (!value->IsTheHole()) return value; |
| 7306 } | 7442 } |
| 7307 break; | 7443 break; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 7336 } | 7472 } |
| 7337 break; | 7473 break; |
| 7338 } | 7474 } |
| 7339 default: | 7475 default: |
| 7340 UNREACHABLE(); | 7476 UNREACHABLE(); |
| 7341 break; | 7477 break; |
| 7342 } | 7478 } |
| 7343 | 7479 |
| 7344 // Continue searching via the prototype chain. | 7480 // Continue searching via the prototype chain. |
| 7345 Object* pt = GetPrototype(); | 7481 Object* pt = GetPrototype(); |
| 7346 if (pt == Heap::null_value()) return Heap::undefined_value(); | 7482 if (pt->IsNull()) return heap->undefined_value(); |
| 7347 return pt->GetElementWithReceiver(receiver, index); | 7483 return pt->GetElementWithReceiver(receiver, index); |
| 7348 } | 7484 } |
| 7349 | 7485 |
| 7350 | 7486 |
| 7351 MaybeObject* JSObject::GetElementWithInterceptor(Object* receiver, | 7487 MaybeObject* JSObject::GetElementWithInterceptor(Object* receiver, |
| 7352 uint32_t index) { | 7488 uint32_t index) { |
| 7489 Isolate* isolate = GetIsolate(); |
| 7353 // Make sure that the top context does not change when doing | 7490 // Make sure that the top context does not change when doing |
| 7354 // callbacks or interceptor calls. | 7491 // callbacks or interceptor calls. |
| 7355 AssertNoContextChange ncc; | 7492 AssertNoContextChange ncc; |
| 7356 HandleScope scope; | 7493 HandleScope scope(isolate); |
| 7357 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); | 7494 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); |
| 7358 Handle<Object> this_handle(receiver); | 7495 Handle<Object> this_handle(receiver); |
| 7359 Handle<JSObject> holder_handle(this); | 7496 Handle<JSObject> holder_handle(this); |
| 7360 | 7497 |
| 7361 if (!interceptor->getter()->IsUndefined()) { | 7498 if (!interceptor->getter()->IsUndefined()) { |
| 7362 v8::IndexedPropertyGetter getter = | 7499 v8::IndexedPropertyGetter getter = |
| 7363 v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter()); | 7500 v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter()); |
| 7364 LOG(ApiIndexedPropertyAccess("interceptor-indexed-get", this, index)); | 7501 LOG(isolate, |
| 7365 CustomArguments args(interceptor->data(), receiver, this); | 7502 ApiIndexedPropertyAccess("interceptor-indexed-get", this, index)); |
| 7503 CustomArguments args(isolate, interceptor->data(), receiver, this); |
| 7366 v8::AccessorInfo info(args.end()); | 7504 v8::AccessorInfo info(args.end()); |
| 7367 v8::Handle<v8::Value> result; | 7505 v8::Handle<v8::Value> result; |
| 7368 { | 7506 { |
| 7369 // Leaving JavaScript. | 7507 // Leaving JavaScript. |
| 7370 VMState state(EXTERNAL); | 7508 VMState state(isolate, EXTERNAL); |
| 7371 result = getter(index, info); | 7509 result = getter(index, info); |
| 7372 } | 7510 } |
| 7373 RETURN_IF_SCHEDULED_EXCEPTION(); | 7511 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 7374 if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result); | 7512 if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result); |
| 7375 } | 7513 } |
| 7376 | 7514 |
| 7377 MaybeObject* raw_result = | 7515 MaybeObject* raw_result = |
| 7378 holder_handle->GetElementPostInterceptor(*this_handle, index); | 7516 holder_handle->GetElementPostInterceptor(*this_handle, index); |
| 7379 RETURN_IF_SCHEDULED_EXCEPTION(); | 7517 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 7380 return raw_result; | 7518 return raw_result; |
| 7381 } | 7519 } |
| 7382 | 7520 |
| 7383 | 7521 |
| 7384 MaybeObject* JSObject::GetElementWithReceiver(Object* receiver, | 7522 MaybeObject* JSObject::GetElementWithReceiver(Object* receiver, |
| 7385 uint32_t index) { | 7523 uint32_t index) { |
| 7524 Heap* heap = GetHeap(); |
| 7386 // Check access rights if needed. | 7525 // Check access rights if needed. |
| 7387 if (IsAccessCheckNeeded() && | 7526 if (IsAccessCheckNeeded() && |
| 7388 !Top::MayIndexedAccess(this, index, v8::ACCESS_GET)) { | 7527 !heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_GET)) { |
| 7389 Top::ReportFailedAccessCheck(this, v8::ACCESS_GET); | 7528 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_GET); |
| 7390 return Heap::undefined_value(); | 7529 return heap->undefined_value(); |
| 7391 } | 7530 } |
| 7392 | 7531 |
| 7393 if (HasIndexedInterceptor()) { | 7532 if (HasIndexedInterceptor()) { |
| 7394 return GetElementWithInterceptor(receiver, index); | 7533 return GetElementWithInterceptor(receiver, index); |
| 7395 } | 7534 } |
| 7396 | 7535 |
| 7397 // Get element works for both JSObject and JSArray since | 7536 // Get element works for both JSObject and JSArray since |
| 7398 // JSArray::length cannot change. | 7537 // JSArray::length cannot change. |
| 7399 switch (GetElementsKind()) { | 7538 switch (GetElementsKind()) { |
| 7400 case FAST_ELEMENTS: { | 7539 case FAST_ELEMENTS: { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 7431 index, | 7570 index, |
| 7432 this); | 7571 this); |
| 7433 } | 7572 } |
| 7434 return element; | 7573 return element; |
| 7435 } | 7574 } |
| 7436 break; | 7575 break; |
| 7437 } | 7576 } |
| 7438 } | 7577 } |
| 7439 | 7578 |
| 7440 Object* pt = GetPrototype(); | 7579 Object* pt = GetPrototype(); |
| 7441 if (pt == Heap::null_value()) return Heap::undefined_value(); | 7580 if (pt == heap->null_value()) return heap->undefined_value(); |
| 7442 return pt->GetElementWithReceiver(receiver, index); | 7581 return pt->GetElementWithReceiver(receiver, index); |
| 7443 } | 7582 } |
| 7444 | 7583 |
| 7445 | 7584 |
| 7446 MaybeObject* JSObject::GetExternalElement(uint32_t index) { | 7585 MaybeObject* JSObject::GetExternalElement(uint32_t index) { |
| 7447 // Get element works for both JSObject and JSArray since | 7586 // Get element works for both JSObject and JSArray since |
| 7448 // JSArray::length cannot change. | 7587 // JSArray::length cannot change. |
| 7449 switch (GetElementsKind()) { | 7588 switch (GetElementsKind()) { |
| 7450 case EXTERNAL_PIXEL_ELEMENTS: { | 7589 case EXTERNAL_PIXEL_ELEMENTS: { |
| 7451 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); | 7590 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7486 if (index < static_cast<uint32_t>(array->length())) { | 7625 if (index < static_cast<uint32_t>(array->length())) { |
| 7487 uint16_t value = array->get(index); | 7626 uint16_t value = array->get(index); |
| 7488 return Smi::FromInt(value); | 7627 return Smi::FromInt(value); |
| 7489 } | 7628 } |
| 7490 break; | 7629 break; |
| 7491 } | 7630 } |
| 7492 case EXTERNAL_INT_ELEMENTS: { | 7631 case EXTERNAL_INT_ELEMENTS: { |
| 7493 ExternalIntArray* array = ExternalIntArray::cast(elements()); | 7632 ExternalIntArray* array = ExternalIntArray::cast(elements()); |
| 7494 if (index < static_cast<uint32_t>(array->length())) { | 7633 if (index < static_cast<uint32_t>(array->length())) { |
| 7495 int32_t value = array->get(index); | 7634 int32_t value = array->get(index); |
| 7496 return Heap::NumberFromInt32(value); | 7635 return GetHeap()->NumberFromInt32(value); |
| 7497 } | 7636 } |
| 7498 break; | 7637 break; |
| 7499 } | 7638 } |
| 7500 case EXTERNAL_UNSIGNED_INT_ELEMENTS: { | 7639 case EXTERNAL_UNSIGNED_INT_ELEMENTS: { |
| 7501 ExternalUnsignedIntArray* array = | 7640 ExternalUnsignedIntArray* array = |
| 7502 ExternalUnsignedIntArray::cast(elements()); | 7641 ExternalUnsignedIntArray::cast(elements()); |
| 7503 if (index < static_cast<uint32_t>(array->length())) { | 7642 if (index < static_cast<uint32_t>(array->length())) { |
| 7504 uint32_t value = array->get(index); | 7643 uint32_t value = array->get(index); |
| 7505 return Heap::NumberFromUint32(value); | 7644 return GetHeap()->NumberFromUint32(value); |
| 7506 } | 7645 } |
| 7507 break; | 7646 break; |
| 7508 } | 7647 } |
| 7509 case EXTERNAL_FLOAT_ELEMENTS: { | 7648 case EXTERNAL_FLOAT_ELEMENTS: { |
| 7510 ExternalFloatArray* array = ExternalFloatArray::cast(elements()); | 7649 ExternalFloatArray* array = ExternalFloatArray::cast(elements()); |
| 7511 if (index < static_cast<uint32_t>(array->length())) { | 7650 if (index < static_cast<uint32_t>(array->length())) { |
| 7512 float value = array->get(index); | 7651 float value = array->get(index); |
| 7513 return Heap::AllocateHeapNumber(value); | 7652 return GetHeap()->AllocateHeapNumber(value); |
| 7514 } | 7653 } |
| 7515 break; | 7654 break; |
| 7516 } | 7655 } |
| 7517 case FAST_ELEMENTS: | 7656 case FAST_ELEMENTS: |
| 7518 case DICTIONARY_ELEMENTS: | 7657 case DICTIONARY_ELEMENTS: |
| 7519 UNREACHABLE(); | 7658 UNREACHABLE(); |
| 7520 break; | 7659 break; |
| 7521 } | 7660 } |
| 7522 return Heap::undefined_value(); | 7661 return GetHeap()->undefined_value(); |
| 7523 } | 7662 } |
| 7524 | 7663 |
| 7525 | 7664 |
| 7526 bool JSObject::HasDenseElements() { | 7665 bool JSObject::HasDenseElements() { |
| 7527 int capacity = 0; | 7666 int capacity = 0; |
| 7528 int number_of_elements = 0; | 7667 int number_of_elements = 0; |
| 7529 | 7668 |
| 7530 switch (GetElementsKind()) { | 7669 switch (GetElementsKind()) { |
| 7531 case FAST_ELEMENTS: { | 7670 case FAST_ELEMENTS: { |
| 7532 FixedArray* elms = FixedArray::cast(elements()); | 7671 FixedArray* elms = FixedArray::cast(elements()); |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7657 Object* result = | 7796 Object* result = |
| 7658 constructor->shared()->get_api_func_data()->indexed_property_handler(); | 7797 constructor->shared()->get_api_func_data()->indexed_property_handler(); |
| 7659 return InterceptorInfo::cast(result); | 7798 return InterceptorInfo::cast(result); |
| 7660 } | 7799 } |
| 7661 | 7800 |
| 7662 | 7801 |
| 7663 MaybeObject* JSObject::GetPropertyPostInterceptor( | 7802 MaybeObject* JSObject::GetPropertyPostInterceptor( |
| 7664 JSObject* receiver, | 7803 JSObject* receiver, |
| 7665 String* name, | 7804 String* name, |
| 7666 PropertyAttributes* attributes) { | 7805 PropertyAttributes* attributes) { |
| 7806 Heap* heap = GetHeap(); |
| 7667 // Check local property in holder, ignore interceptor. | 7807 // Check local property in holder, ignore interceptor. |
| 7668 LookupResult result; | 7808 LookupResult result; |
| 7669 LocalLookupRealNamedProperty(name, &result); | 7809 LocalLookupRealNamedProperty(name, &result); |
| 7670 if (result.IsProperty()) { | 7810 if (result.IsProperty()) { |
| 7671 return GetProperty(receiver, &result, name, attributes); | 7811 return GetProperty(receiver, &result, name, attributes); |
| 7672 } | 7812 } |
| 7673 // Continue searching via the prototype chain. | 7813 // Continue searching via the prototype chain. |
| 7674 Object* pt = GetPrototype(); | 7814 Object* pt = GetPrototype(); |
| 7675 *attributes = ABSENT; | 7815 *attributes = ABSENT; |
| 7676 if (pt == Heap::null_value()) return Heap::undefined_value(); | 7816 if (pt->IsNull()) return heap->undefined_value(); |
| 7677 return pt->GetPropertyWithReceiver(receiver, name, attributes); | 7817 return pt->GetPropertyWithReceiver(receiver, name, attributes); |
| 7678 } | 7818 } |
| 7679 | 7819 |
| 7680 | 7820 |
| 7681 MaybeObject* JSObject::GetLocalPropertyPostInterceptor( | 7821 MaybeObject* JSObject::GetLocalPropertyPostInterceptor( |
| 7682 JSObject* receiver, | 7822 JSObject* receiver, |
| 7683 String* name, | 7823 String* name, |
| 7684 PropertyAttributes* attributes) { | 7824 PropertyAttributes* attributes) { |
| 7825 Heap* heap = GetHeap(); |
| 7685 // Check local property in holder, ignore interceptor. | 7826 // Check local property in holder, ignore interceptor. |
| 7686 LookupResult result; | 7827 LookupResult result; |
| 7687 LocalLookupRealNamedProperty(name, &result); | 7828 LocalLookupRealNamedProperty(name, &result); |
| 7688 if (result.IsProperty()) { | 7829 if (result.IsProperty()) { |
| 7689 return GetProperty(receiver, &result, name, attributes); | 7830 return GetProperty(receiver, &result, name, attributes); |
| 7690 } | 7831 } |
| 7691 return Heap::undefined_value(); | 7832 return heap->undefined_value(); |
| 7692 } | 7833 } |
| 7693 | 7834 |
| 7694 | 7835 |
| 7695 MaybeObject* JSObject::GetPropertyWithInterceptor( | 7836 MaybeObject* JSObject::GetPropertyWithInterceptor( |
| 7696 JSObject* receiver, | 7837 JSObject* receiver, |
| 7697 String* name, | 7838 String* name, |
| 7698 PropertyAttributes* attributes) { | 7839 PropertyAttributes* attributes) { |
| 7840 Isolate* isolate = GetIsolate(); |
| 7699 InterceptorInfo* interceptor = GetNamedInterceptor(); | 7841 InterceptorInfo* interceptor = GetNamedInterceptor(); |
| 7700 HandleScope scope; | 7842 HandleScope scope(isolate); |
| 7701 Handle<JSObject> receiver_handle(receiver); | 7843 Handle<JSObject> receiver_handle(receiver); |
| 7702 Handle<JSObject> holder_handle(this); | 7844 Handle<JSObject> holder_handle(this); |
| 7703 Handle<String> name_handle(name); | 7845 Handle<String> name_handle(name); |
| 7704 | 7846 |
| 7705 if (!interceptor->getter()->IsUndefined()) { | 7847 if (!interceptor->getter()->IsUndefined()) { |
| 7706 v8::NamedPropertyGetter getter = | 7848 v8::NamedPropertyGetter getter = |
| 7707 v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter()); | 7849 v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter()); |
| 7708 LOG(ApiNamedPropertyAccess("interceptor-named-get", *holder_handle, name)); | 7850 LOG(isolate, |
| 7709 CustomArguments args(interceptor->data(), receiver, this); | 7851 ApiNamedPropertyAccess("interceptor-named-get", *holder_handle, name)); |
| 7852 CustomArguments args(isolate, interceptor->data(), receiver, this); |
| 7710 v8::AccessorInfo info(args.end()); | 7853 v8::AccessorInfo info(args.end()); |
| 7711 v8::Handle<v8::Value> result; | 7854 v8::Handle<v8::Value> result; |
| 7712 { | 7855 { |
| 7713 // Leaving JavaScript. | 7856 // Leaving JavaScript. |
| 7714 VMState state(EXTERNAL); | 7857 VMState state(isolate, EXTERNAL); |
| 7715 result = getter(v8::Utils::ToLocal(name_handle), info); | 7858 result = getter(v8::Utils::ToLocal(name_handle), info); |
| 7716 } | 7859 } |
| 7717 RETURN_IF_SCHEDULED_EXCEPTION(); | 7860 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 7718 if (!result.IsEmpty()) { | 7861 if (!result.IsEmpty()) { |
| 7719 *attributes = NONE; | 7862 *attributes = NONE; |
| 7720 return *v8::Utils::OpenHandle(*result); | 7863 return *v8::Utils::OpenHandle(*result); |
| 7721 } | 7864 } |
| 7722 } | 7865 } |
| 7723 | 7866 |
| 7724 MaybeObject* result = holder_handle->GetPropertyPostInterceptor( | 7867 MaybeObject* result = holder_handle->GetPropertyPostInterceptor( |
| 7725 *receiver_handle, | 7868 *receiver_handle, |
| 7726 *name_handle, | 7869 *name_handle, |
| 7727 attributes); | 7870 attributes); |
| 7728 RETURN_IF_SCHEDULED_EXCEPTION(); | 7871 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 7729 return result; | 7872 return result; |
| 7730 } | 7873 } |
| 7731 | 7874 |
| 7732 | 7875 |
| 7733 bool JSObject::HasRealNamedProperty(String* key) { | 7876 bool JSObject::HasRealNamedProperty(String* key) { |
| 7877 Heap* heap = GetHeap(); |
| 7734 // Check access rights if needed. | 7878 // Check access rights if needed. |
| 7735 if (IsAccessCheckNeeded() && | 7879 if (IsAccessCheckNeeded() && |
| 7736 !Top::MayNamedAccess(this, key, v8::ACCESS_HAS)) { | 7880 !heap->isolate()->MayNamedAccess(this, key, v8::ACCESS_HAS)) { |
| 7737 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 7881 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 7738 return false; | 7882 return false; |
| 7739 } | 7883 } |
| 7740 | 7884 |
| 7741 LookupResult result; | 7885 LookupResult result; |
| 7742 LocalLookupRealNamedProperty(key, &result); | 7886 LocalLookupRealNamedProperty(key, &result); |
| 7743 return result.IsProperty() && (result.type() != INTERCEPTOR); | 7887 return result.IsProperty() && (result.type() != INTERCEPTOR); |
| 7744 } | 7888 } |
| 7745 | 7889 |
| 7746 | 7890 |
| 7747 bool JSObject::HasRealElementProperty(uint32_t index) { | 7891 bool JSObject::HasRealElementProperty(uint32_t index) { |
| 7892 Heap* heap = GetHeap(); |
| 7748 // Check access rights if needed. | 7893 // Check access rights if needed. |
| 7749 if (IsAccessCheckNeeded() && | 7894 if (IsAccessCheckNeeded() && |
| 7750 !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 7895 !heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { |
| 7751 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 7896 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 7752 return false; | 7897 return false; |
| 7753 } | 7898 } |
| 7754 | 7899 |
| 7755 // Handle [] on String objects. | 7900 // Handle [] on String objects. |
| 7756 if (this->IsStringObjectWithCharacterAt(index)) return true; | 7901 if (this->IsStringObjectWithCharacterAt(index)) return true; |
| 7757 | 7902 |
| 7758 switch (GetElementsKind()) { | 7903 switch (GetElementsKind()) { |
| 7759 case FAST_ELEMENTS: { | 7904 case FAST_ELEMENTS: { |
| 7760 uint32_t length = IsJSArray() ? | 7905 uint32_t length = IsJSArray() ? |
| 7761 static_cast<uint32_t>( | 7906 static_cast<uint32_t>( |
| (...skipping 19 matching lines...) Expand all Loading... |
| 7781 case DICTIONARY_ELEMENTS: { | 7926 case DICTIONARY_ELEMENTS: { |
| 7782 return element_dictionary()->FindEntry(index) | 7927 return element_dictionary()->FindEntry(index) |
| 7783 != NumberDictionary::kNotFound; | 7928 != NumberDictionary::kNotFound; |
| 7784 } | 7929 } |
| 7785 default: | 7930 default: |
| 7786 UNREACHABLE(); | 7931 UNREACHABLE(); |
| 7787 break; | 7932 break; |
| 7788 } | 7933 } |
| 7789 // All possibilities have been handled above already. | 7934 // All possibilities have been handled above already. |
| 7790 UNREACHABLE(); | 7935 UNREACHABLE(); |
| 7791 return Heap::null_value(); | 7936 return heap->null_value(); |
| 7792 } | 7937 } |
| 7793 | 7938 |
| 7794 | 7939 |
| 7795 bool JSObject::HasRealNamedCallbackProperty(String* key) { | 7940 bool JSObject::HasRealNamedCallbackProperty(String* key) { |
| 7941 Heap* heap = GetHeap(); |
| 7796 // Check access rights if needed. | 7942 // Check access rights if needed. |
| 7797 if (IsAccessCheckNeeded() && | 7943 if (IsAccessCheckNeeded() && |
| 7798 !Top::MayNamedAccess(this, key, v8::ACCESS_HAS)) { | 7944 !heap->isolate()->MayNamedAccess(this, key, v8::ACCESS_HAS)) { |
| 7799 Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 7945 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 7800 return false; | 7946 return false; |
| 7801 } | 7947 } |
| 7802 | 7948 |
| 7803 LookupResult result; | 7949 LookupResult result; |
| 7804 LocalLookupRealNamedProperty(key, &result); | 7950 LocalLookupRealNamedProperty(key, &result); |
| 7805 return result.IsProperty() && (result.type() == CALLBACKS); | 7951 return result.IsProperty() && (result.type() == CALLBACKS); |
| 7806 } | 7952 } |
| 7807 | 7953 |
| 7808 | 7954 |
| 7809 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) { | 7955 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) { |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8052 return counter; | 8198 return counter; |
| 8053 } | 8199 } |
| 8054 | 8200 |
| 8055 | 8201 |
| 8056 int JSObject::GetEnumElementKeys(FixedArray* storage) { | 8202 int JSObject::GetEnumElementKeys(FixedArray* storage) { |
| 8057 return GetLocalElementKeys(storage, | 8203 return GetLocalElementKeys(storage, |
| 8058 static_cast<PropertyAttributes>(DONT_ENUM)); | 8204 static_cast<PropertyAttributes>(DONT_ENUM)); |
| 8059 } | 8205 } |
| 8060 | 8206 |
| 8061 | 8207 |
| 8062 bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) { | |
| 8063 ASSERT(other->IsNumber()); | |
| 8064 return key == static_cast<uint32_t>(other->Number()); | |
| 8065 } | |
| 8066 | |
| 8067 | |
| 8068 uint32_t NumberDictionaryShape::Hash(uint32_t key) { | |
| 8069 return ComputeIntegerHash(key); | |
| 8070 } | |
| 8071 | |
| 8072 | |
| 8073 uint32_t NumberDictionaryShape::HashForObject(uint32_t key, Object* other) { | |
| 8074 ASSERT(other->IsNumber()); | |
| 8075 return ComputeIntegerHash(static_cast<uint32_t>(other->Number())); | |
| 8076 } | |
| 8077 | |
| 8078 | |
| 8079 MaybeObject* NumberDictionaryShape::AsObject(uint32_t key) { | |
| 8080 return Heap::NumberFromUint32(key); | |
| 8081 } | |
| 8082 | |
| 8083 | |
| 8084 bool StringDictionaryShape::IsMatch(String* key, Object* other) { | |
| 8085 // We know that all entries in a hash table had their hash keys created. | |
| 8086 // Use that knowledge to have fast failure. | |
| 8087 if (key->Hash() != String::cast(other)->Hash()) return false; | |
| 8088 return key->Equals(String::cast(other)); | |
| 8089 } | |
| 8090 | |
| 8091 | |
| 8092 uint32_t StringDictionaryShape::Hash(String* key) { | |
| 8093 return key->Hash(); | |
| 8094 } | |
| 8095 | |
| 8096 | |
| 8097 uint32_t StringDictionaryShape::HashForObject(String* key, Object* other) { | |
| 8098 return String::cast(other)->Hash(); | |
| 8099 } | |
| 8100 | |
| 8101 | |
| 8102 MaybeObject* StringDictionaryShape::AsObject(String* key) { | |
| 8103 return key; | |
| 8104 } | |
| 8105 | |
| 8106 | |
| 8107 // StringKey simply carries a string object as key. | 8208 // StringKey simply carries a string object as key. |
| 8108 class StringKey : public HashTableKey { | 8209 class StringKey : public HashTableKey { |
| 8109 public: | 8210 public: |
| 8110 explicit StringKey(String* string) : | 8211 explicit StringKey(String* string) : |
| 8111 string_(string), | 8212 string_(string), |
| 8112 hash_(HashForObject(string)) { } | 8213 hash_(HashForObject(string)) { } |
| 8113 | 8214 |
| 8114 bool IsMatch(Object* string) { | 8215 bool IsMatch(Object* string) { |
| 8115 // We know that all entries in a hash table had their hash keys created. | 8216 // We know that all entries in a hash table had their hash keys created. |
| 8116 // Use that knowledge to have fast failure. | 8217 // Use that knowledge to have fast failure. |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8179 FixedArray* pair = FixedArray::cast(obj); | 8280 FixedArray* pair = FixedArray::cast(obj); |
| 8180 SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0)); | 8281 SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0)); |
| 8181 String* source = String::cast(pair->get(1)); | 8282 String* source = String::cast(pair->get(1)); |
| 8182 StrictModeFlag strict_mode = static_cast<StrictModeFlag>( | 8283 StrictModeFlag strict_mode = static_cast<StrictModeFlag>( |
| 8183 Smi::cast(pair->get(2))->value()); | 8284 Smi::cast(pair->get(2))->value()); |
| 8184 return StringSharedHashHelper(source, shared, strict_mode); | 8285 return StringSharedHashHelper(source, shared, strict_mode); |
| 8185 } | 8286 } |
| 8186 | 8287 |
| 8187 MUST_USE_RESULT MaybeObject* AsObject() { | 8288 MUST_USE_RESULT MaybeObject* AsObject() { |
| 8188 Object* obj; | 8289 Object* obj; |
| 8189 { MaybeObject* maybe_obj = Heap::AllocateFixedArray(3); | 8290 { MaybeObject* maybe_obj = source_->GetHeap()->AllocateFixedArray(3); |
| 8190 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 8291 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 8191 } | 8292 } |
| 8192 FixedArray* pair = FixedArray::cast(obj); | 8293 FixedArray* pair = FixedArray::cast(obj); |
| 8193 pair->set(0, shared_); | 8294 pair->set(0, shared_); |
| 8194 pair->set(1, source_); | 8295 pair->set(1, source_); |
| 8195 pair->set(2, Smi::FromInt(strict_mode_)); | 8296 pair->set(2, Smi::FromInt(strict_mode_)); |
| 8196 return pair; | 8297 return pair; |
| 8197 } | 8298 } |
| 8198 | 8299 |
| 8199 private: | 8300 private: |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8263 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. | 8364 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. |
| 8264 return result; | 8365 return result; |
| 8265 } | 8366 } |
| 8266 | 8367 |
| 8267 uint32_t HashForObject(Object* other) { | 8368 uint32_t HashForObject(Object* other) { |
| 8268 return String::cast(other)->Hash(); | 8369 return String::cast(other)->Hash(); |
| 8269 } | 8370 } |
| 8270 | 8371 |
| 8271 MaybeObject* AsObject() { | 8372 MaybeObject* AsObject() { |
| 8272 if (hash_field_ == 0) Hash(); | 8373 if (hash_field_ == 0) Hash(); |
| 8273 return Heap::AllocateSymbol(string_, chars_, hash_field_); | 8374 return Isolate::Current()->heap()->AllocateSymbol( |
| 8375 string_, chars_, hash_field_); |
| 8274 } | 8376 } |
| 8275 | 8377 |
| 8276 Vector<const char> string_; | 8378 Vector<const char> string_; |
| 8277 uint32_t hash_field_; | 8379 uint32_t hash_field_; |
| 8278 int chars_; // Caches the number of characters when computing the hash code. | 8380 int chars_; // Caches the number of characters when computing the hash code. |
| 8279 }; | 8381 }; |
| 8280 | 8382 |
| 8281 | 8383 |
| 8282 template <typename Char> | 8384 template <typename Char> |
| 8283 class SequentialSymbolKey : public HashTableKey { | 8385 class SequentialSymbolKey : public HashTableKey { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8330 public: | 8432 public: |
| 8331 explicit AsciiSymbolKey(Vector<const char> str) | 8433 explicit AsciiSymbolKey(Vector<const char> str) |
| 8332 : SequentialSymbolKey<char>(str) { } | 8434 : SequentialSymbolKey<char>(str) { } |
| 8333 | 8435 |
| 8334 bool IsMatch(Object* string) { | 8436 bool IsMatch(Object* string) { |
| 8335 return String::cast(string)->IsAsciiEqualTo(string_); | 8437 return String::cast(string)->IsAsciiEqualTo(string_); |
| 8336 } | 8438 } |
| 8337 | 8439 |
| 8338 MaybeObject* AsObject() { | 8440 MaybeObject* AsObject() { |
| 8339 if (hash_field_ == 0) Hash(); | 8441 if (hash_field_ == 0) Hash(); |
| 8340 return Heap::AllocateAsciiSymbol(string_, hash_field_); | 8442 return HEAP->AllocateAsciiSymbol(string_, hash_field_); |
| 8341 } | 8443 } |
| 8342 }; | 8444 }; |
| 8343 | 8445 |
| 8344 | 8446 |
| 8345 class TwoByteSymbolKey : public SequentialSymbolKey<uc16> { | 8447 class TwoByteSymbolKey : public SequentialSymbolKey<uc16> { |
| 8346 public: | 8448 public: |
| 8347 explicit TwoByteSymbolKey(Vector<const uc16> str) | 8449 explicit TwoByteSymbolKey(Vector<const uc16> str) |
| 8348 : SequentialSymbolKey<uc16>(str) { } | 8450 : SequentialSymbolKey<uc16>(str) { } |
| 8349 | 8451 |
| 8350 bool IsMatch(Object* string) { | 8452 bool IsMatch(Object* string) { |
| 8351 return String::cast(string)->IsTwoByteEqualTo(string_); | 8453 return String::cast(string)->IsTwoByteEqualTo(string_); |
| 8352 } | 8454 } |
| 8353 | 8455 |
| 8354 MaybeObject* AsObject() { | 8456 MaybeObject* AsObject() { |
| 8355 if (hash_field_ == 0) Hash(); | 8457 if (hash_field_ == 0) Hash(); |
| 8356 return Heap::AllocateTwoByteSymbol(string_, hash_field_); | 8458 return HEAP->AllocateTwoByteSymbol(string_, hash_field_); |
| 8357 } | 8459 } |
| 8358 }; | 8460 }; |
| 8359 | 8461 |
| 8360 | 8462 |
| 8361 // SymbolKey carries a string/symbol object as key. | 8463 // SymbolKey carries a string/symbol object as key. |
| 8362 class SymbolKey : public HashTableKey { | 8464 class SymbolKey : public HashTableKey { |
| 8363 public: | 8465 public: |
| 8364 explicit SymbolKey(String* string) : string_(string) { } | 8466 explicit SymbolKey(String* string) |
| 8467 : string_(string) { } |
| 8365 | 8468 |
| 8366 bool IsMatch(Object* string) { | 8469 bool IsMatch(Object* string) { |
| 8367 return String::cast(string)->Equals(string_); | 8470 return String::cast(string)->Equals(string_); |
| 8368 } | 8471 } |
| 8369 | 8472 |
| 8370 uint32_t Hash() { return string_->Hash(); } | 8473 uint32_t Hash() { return string_->Hash(); } |
| 8371 | 8474 |
| 8372 uint32_t HashForObject(Object* other) { | 8475 uint32_t HashForObject(Object* other) { |
| 8373 return String::cast(other)->Hash(); | 8476 return String::cast(other)->Hash(); |
| 8374 } | 8477 } |
| 8375 | 8478 |
| 8376 MaybeObject* AsObject() { | 8479 MaybeObject* AsObject() { |
| 8377 // Attempt to flatten the string, so that symbols will most often | 8480 // Attempt to flatten the string, so that symbols will most often |
| 8378 // be flat strings. | 8481 // be flat strings. |
| 8379 string_ = string_->TryFlattenGetString(); | 8482 string_ = string_->TryFlattenGetString(); |
| 8483 Heap* heap = string_->GetHeap(); |
| 8380 // Transform string to symbol if possible. | 8484 // Transform string to symbol if possible. |
| 8381 Map* map = Heap::SymbolMapForString(string_); | 8485 Map* map = heap->SymbolMapForString(string_); |
| 8382 if (map != NULL) { | 8486 if (map != NULL) { |
| 8383 string_->set_map(map); | 8487 string_->set_map(map); |
| 8384 ASSERT(string_->IsSymbol()); | 8488 ASSERT(string_->IsSymbol()); |
| 8385 return string_; | 8489 return string_; |
| 8386 } | 8490 } |
| 8387 // Otherwise allocate a new symbol. | 8491 // Otherwise allocate a new symbol. |
| 8388 StringInputBuffer buffer(string_); | 8492 StringInputBuffer buffer(string_); |
| 8389 return Heap::AllocateInternalSymbol(&buffer, | 8493 return heap->AllocateInternalSymbol(&buffer, |
| 8390 string_->length(), | 8494 string_->length(), |
| 8391 string_->hash_field()); | 8495 string_->hash_field()); |
| 8392 } | 8496 } |
| 8393 | 8497 |
| 8394 static uint32_t StringHash(Object* obj) { | 8498 static uint32_t StringHash(Object* obj) { |
| 8395 return String::cast(obj)->Hash(); | 8499 return String::cast(obj)->Hash(); |
| 8396 } | 8500 } |
| 8397 | 8501 |
| 8398 String* string_; | 8502 String* string_; |
| 8399 }; | 8503 }; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 8418 PretenureFlag pretenure) { | 8522 PretenureFlag pretenure) { |
| 8419 const int kMinCapacity = 32; | 8523 const int kMinCapacity = 32; |
| 8420 int capacity = RoundUpToPowerOf2(at_least_space_for * 2); | 8524 int capacity = RoundUpToPowerOf2(at_least_space_for * 2); |
| 8421 if (capacity < kMinCapacity) { | 8525 if (capacity < kMinCapacity) { |
| 8422 capacity = kMinCapacity; // Guarantee min capacity. | 8526 capacity = kMinCapacity; // Guarantee min capacity. |
| 8423 } else if (capacity > HashTable::kMaxCapacity) { | 8527 } else if (capacity > HashTable::kMaxCapacity) { |
| 8424 return Failure::OutOfMemoryException(); | 8528 return Failure::OutOfMemoryException(); |
| 8425 } | 8529 } |
| 8426 | 8530 |
| 8427 Object* obj; | 8531 Object* obj; |
| 8428 { MaybeObject* maybe_obj = | 8532 { MaybeObject* maybe_obj = Isolate::Current()->heap()-> |
| 8429 Heap::AllocateHashTable(EntryToIndex(capacity), pretenure); | 8533 AllocateHashTable(EntryToIndex(capacity), pretenure); |
| 8430 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 8534 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 8431 } | 8535 } |
| 8432 HashTable::cast(obj)->SetNumberOfElements(0); | 8536 HashTable::cast(obj)->SetNumberOfElements(0); |
| 8433 HashTable::cast(obj)->SetNumberOfDeletedElements(0); | 8537 HashTable::cast(obj)->SetNumberOfDeletedElements(0); |
| 8434 HashTable::cast(obj)->SetCapacity(capacity); | 8538 HashTable::cast(obj)->SetCapacity(capacity); |
| 8435 return obj; | 8539 return obj; |
| 8436 } | 8540 } |
| 8437 | 8541 |
| 8438 | 8542 |
| 8439 // Find entry for key otherwise return kNotFound. | 8543 // Find entry for key otherwise return kNotFound. |
| 8440 template<typename Shape, typename Key> | |
| 8441 int HashTable<Shape, Key>::FindEntry(Key key) { | |
| 8442 uint32_t capacity = Capacity(); | |
| 8443 uint32_t entry = FirstProbe(Shape::Hash(key), capacity); | |
| 8444 uint32_t count = 1; | |
| 8445 // EnsureCapacity will guarantee the hash table is never full. | |
| 8446 while (true) { | |
| 8447 Object* element = KeyAt(entry); | |
| 8448 if (element->IsUndefined()) break; // Empty entry. | |
| 8449 if (!element->IsNull() && Shape::IsMatch(key, element)) return entry; | |
| 8450 entry = NextProbe(entry, count++, capacity); | |
| 8451 } | |
| 8452 return kNotFound; | |
| 8453 } | |
| 8454 | |
| 8455 | |
| 8456 // Find entry for key otherwise return kNotFound. | |
| 8457 int StringDictionary::FindEntry(String* key) { | 8544 int StringDictionary::FindEntry(String* key) { |
| 8458 if (!key->IsSymbol()) { | 8545 if (!key->IsSymbol()) { |
| 8459 return HashTable<StringDictionaryShape, String*>::FindEntry(key); | 8546 return HashTable<StringDictionaryShape, String*>::FindEntry(key); |
| 8460 } | 8547 } |
| 8461 | 8548 |
| 8462 // Optimized for symbol key. Knowledge of the key type allows: | 8549 // Optimized for symbol key. Knowledge of the key type allows: |
| 8463 // 1. Move the check if the key is a symbol out of the loop. | 8550 // 1. Move the check if the key is a symbol out of the loop. |
| 8464 // 2. Avoid comparing hash codes in symbol to symbol comparision. | 8551 // 2. Avoid comparing hash codes in symbol to symbol comparision. |
| 8465 // 3. Detect a case when a dictionary key is not a symbol but the key is. | 8552 // 3. Detect a case when a dictionary key is not a symbol but the key is. |
| 8466 // In case of positive result the dictionary key may be replaced by | 8553 // In case of positive result the dictionary key may be replaced by |
| (...skipping 21 matching lines...) Expand all Loading... |
| 8488 } | 8575 } |
| 8489 ASSERT(element->IsNull() || !String::cast(element)->Equals(key)); | 8576 ASSERT(element->IsNull() || !String::cast(element)->Equals(key)); |
| 8490 entry = NextProbe(entry, count++, capacity); | 8577 entry = NextProbe(entry, count++, capacity); |
| 8491 } | 8578 } |
| 8492 return kNotFound; | 8579 return kNotFound; |
| 8493 } | 8580 } |
| 8494 | 8581 |
| 8495 | 8582 |
| 8496 template<typename Shape, typename Key> | 8583 template<typename Shape, typename Key> |
| 8497 MaybeObject* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) { | 8584 MaybeObject* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) { |
| 8585 Heap* heap = GetHeap(); |
| 8498 int capacity = Capacity(); | 8586 int capacity = Capacity(); |
| 8499 int nof = NumberOfElements() + n; | 8587 int nof = NumberOfElements() + n; |
| 8500 int nod = NumberOfDeletedElements(); | 8588 int nod = NumberOfDeletedElements(); |
| 8501 // Return if: | 8589 // Return if: |
| 8502 // 50% is still free after adding n elements and | 8590 // 50% is still free after adding n elements and |
| 8503 // at most 50% of the free elements are deleted elements. | 8591 // at most 50% of the free elements are deleted elements. |
| 8504 if (nod <= (capacity - nof) >> 1) { | 8592 if (nod <= (capacity - nof) >> 1) { |
| 8505 int needed_free = nof >> 1; | 8593 int needed_free = nof >> 1; |
| 8506 if (nof + needed_free <= capacity) return this; | 8594 if (nof + needed_free <= capacity) return this; |
| 8507 } | 8595 } |
| 8508 | 8596 |
| 8509 const int kMinCapacityForPretenure = 256; | 8597 const int kMinCapacityForPretenure = 256; |
| 8510 bool pretenure = | 8598 bool pretenure = |
| 8511 (capacity > kMinCapacityForPretenure) && !Heap::InNewSpace(this); | 8599 (capacity > kMinCapacityForPretenure) && !heap->InNewSpace(this); |
| 8512 Object* obj; | 8600 Object* obj; |
| 8513 { MaybeObject* maybe_obj = | 8601 { MaybeObject* maybe_obj = |
| 8514 Allocate(nof * 2, pretenure ? TENURED : NOT_TENURED); | 8602 Allocate(nof * 2, pretenure ? TENURED : NOT_TENURED); |
| 8515 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 8603 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 8516 } | 8604 } |
| 8517 | 8605 |
| 8518 AssertNoAllocation no_gc; | 8606 AssertNoAllocation no_gc; |
| 8519 HashTable* table = HashTable::cast(obj); | 8607 HashTable* table = HashTable::cast(obj); |
| 8520 WriteBarrierMode mode = table->GetWriteBarrierMode(no_gc); | 8608 WriteBarrierMode mode = table->GetWriteBarrierMode(no_gc); |
| 8521 | 8609 |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8633 template | 8721 template |
| 8634 int Dictionary<StringDictionaryShape, String*>::NumberOfEnumElements(); | 8722 int Dictionary<StringDictionaryShape, String*>::NumberOfEnumElements(); |
| 8635 | 8723 |
| 8636 template | 8724 template |
| 8637 int HashTable<NumberDictionaryShape, uint32_t>::FindEntry(uint32_t); | 8725 int HashTable<NumberDictionaryShape, uint32_t>::FindEntry(uint32_t); |
| 8638 | 8726 |
| 8639 | 8727 |
| 8640 // Collates undefined and unexisting elements below limit from position | 8728 // Collates undefined and unexisting elements below limit from position |
| 8641 // zero of the elements. The object stays in Dictionary mode. | 8729 // zero of the elements. The object stays in Dictionary mode. |
| 8642 MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) { | 8730 MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) { |
| 8731 Heap* heap = GetHeap(); |
| 8643 ASSERT(HasDictionaryElements()); | 8732 ASSERT(HasDictionaryElements()); |
| 8644 // Must stay in dictionary mode, either because of requires_slow_elements, | 8733 // Must stay in dictionary mode, either because of requires_slow_elements, |
| 8645 // or because we are not going to sort (and therefore compact) all of the | 8734 // or because we are not going to sort (and therefore compact) all of the |
| 8646 // elements. | 8735 // elements. |
| 8647 NumberDictionary* dict = element_dictionary(); | 8736 NumberDictionary* dict = element_dictionary(); |
| 8648 HeapNumber* result_double = NULL; | 8737 HeapNumber* result_double = NULL; |
| 8649 if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { | 8738 if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { |
| 8650 // Allocate space for result before we start mutating the object. | 8739 // Allocate space for result before we start mutating the object. |
| 8651 Object* new_double; | 8740 Object* new_double; |
| 8652 { MaybeObject* maybe_new_double = Heap::AllocateHeapNumber(0.0); | 8741 { MaybeObject* maybe_new_double = heap->AllocateHeapNumber(0.0); |
| 8653 if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double; | 8742 if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double; |
| 8654 } | 8743 } |
| 8655 result_double = HeapNumber::cast(new_double); | 8744 result_double = HeapNumber::cast(new_double); |
| 8656 } | 8745 } |
| 8657 | 8746 |
| 8658 Object* obj; | 8747 Object* obj; |
| 8659 { MaybeObject* maybe_obj = | 8748 { MaybeObject* maybe_obj = |
| 8660 NumberDictionary::Allocate(dict->NumberOfElements()); | 8749 NumberDictionary::Allocate(dict->NumberOfElements()); |
| 8661 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 8750 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 8662 } | 8751 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8708 } | 8797 } |
| 8709 | 8798 |
| 8710 uint32_t result = pos; | 8799 uint32_t result = pos; |
| 8711 PropertyDetails no_details = PropertyDetails(NONE, NORMAL); | 8800 PropertyDetails no_details = PropertyDetails(NONE, NORMAL); |
| 8712 while (undefs > 0) { | 8801 while (undefs > 0) { |
| 8713 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { | 8802 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { |
| 8714 // Adding an entry with the key beyond smi-range requires | 8803 // Adding an entry with the key beyond smi-range requires |
| 8715 // allocation. Bailout. | 8804 // allocation. Bailout. |
| 8716 return Smi::FromInt(-1); | 8805 return Smi::FromInt(-1); |
| 8717 } | 8806 } |
| 8718 new_dict->AddNumberEntry(pos, Heap::undefined_value(), no_details)-> | 8807 new_dict->AddNumberEntry(pos, heap->undefined_value(), no_details)-> |
| 8719 ToObjectUnchecked(); | 8808 ToObjectUnchecked(); |
| 8720 pos++; | 8809 pos++; |
| 8721 undefs--; | 8810 undefs--; |
| 8722 } | 8811 } |
| 8723 | 8812 |
| 8724 set_elements(new_dict); | 8813 set_elements(new_dict); |
| 8725 | 8814 |
| 8726 if (result <= static_cast<uint32_t>(Smi::kMaxValue)) { | 8815 if (result <= static_cast<uint32_t>(Smi::kMaxValue)) { |
| 8727 return Smi::FromInt(static_cast<int>(result)); | 8816 return Smi::FromInt(static_cast<int>(result)); |
| 8728 } | 8817 } |
| 8729 | 8818 |
| 8730 ASSERT_NE(NULL, result_double); | 8819 ASSERT_NE(NULL, result_double); |
| 8731 result_double->set_value(static_cast<double>(result)); | 8820 result_double->set_value(static_cast<double>(result)); |
| 8732 return result_double; | 8821 return result_double; |
| 8733 } | 8822 } |
| 8734 | 8823 |
| 8735 | 8824 |
| 8736 // Collects all defined (non-hole) and non-undefined (array) elements at | 8825 // Collects all defined (non-hole) and non-undefined (array) elements at |
| 8737 // the start of the elements array. | 8826 // the start of the elements array. |
| 8738 // If the object is in dictionary mode, it is converted to fast elements | 8827 // If the object is in dictionary mode, it is converted to fast elements |
| 8739 // mode. | 8828 // mode. |
| 8740 MaybeObject* JSObject::PrepareElementsForSort(uint32_t limit) { | 8829 MaybeObject* JSObject::PrepareElementsForSort(uint32_t limit) { |
| 8830 Heap* heap = GetHeap(); |
| 8741 ASSERT(!HasExternalArrayElements()); | 8831 ASSERT(!HasExternalArrayElements()); |
| 8742 | 8832 |
| 8743 if (HasDictionaryElements()) { | 8833 if (HasDictionaryElements()) { |
| 8744 // Convert to fast elements containing only the existing properties. | 8834 // Convert to fast elements containing only the existing properties. |
| 8745 // Ordering is irrelevant, since we are going to sort anyway. | 8835 // Ordering is irrelevant, since we are going to sort anyway. |
| 8746 NumberDictionary* dict = element_dictionary(); | 8836 NumberDictionary* dict = element_dictionary(); |
| 8747 if (IsJSArray() || dict->requires_slow_elements() || | 8837 if (IsJSArray() || dict->requires_slow_elements() || |
| 8748 dict->max_number_key() >= limit) { | 8838 dict->max_number_key() >= limit) { |
| 8749 return PrepareSlowElementsForSort(limit); | 8839 return PrepareSlowElementsForSort(limit); |
| 8750 } | 8840 } |
| 8751 // Convert to fast elements. | 8841 // Convert to fast elements. |
| 8752 | 8842 |
| 8753 Object* obj; | 8843 Object* obj; |
| 8754 { MaybeObject* maybe_obj = map()->GetFastElementsMap(); | 8844 { MaybeObject* maybe_obj = map()->GetFastElementsMap(); |
| 8755 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 8845 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 8756 } | 8846 } |
| 8757 Map* new_map = Map::cast(obj); | 8847 Map* new_map = Map::cast(obj); |
| 8758 | 8848 |
| 8759 PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED: TENURED; | 8849 PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED; |
| 8760 Object* new_array; | 8850 Object* new_array; |
| 8761 { MaybeObject* maybe_new_array = | 8851 { MaybeObject* maybe_new_array = |
| 8762 Heap::AllocateFixedArray(dict->NumberOfElements(), tenure); | 8852 heap->AllocateFixedArray(dict->NumberOfElements(), tenure); |
| 8763 if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array; | 8853 if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array; |
| 8764 } | 8854 } |
| 8765 FixedArray* fast_elements = FixedArray::cast(new_array); | 8855 FixedArray* fast_elements = FixedArray::cast(new_array); |
| 8766 dict->CopyValuesTo(fast_elements); | 8856 dict->CopyValuesTo(fast_elements); |
| 8767 | 8857 |
| 8768 set_map(new_map); | 8858 set_map(new_map); |
| 8769 set_elements(fast_elements); | 8859 set_elements(fast_elements); |
| 8770 } else { | 8860 } else { |
| 8771 Object* obj; | 8861 Object* obj; |
| 8772 { MaybeObject* maybe_obj = EnsureWritableFastElements(); | 8862 { MaybeObject* maybe_obj = EnsureWritableFastElements(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 8785 } | 8875 } |
| 8786 if (limit == 0) { | 8876 if (limit == 0) { |
| 8787 return Smi::FromInt(0); | 8877 return Smi::FromInt(0); |
| 8788 } | 8878 } |
| 8789 | 8879 |
| 8790 HeapNumber* result_double = NULL; | 8880 HeapNumber* result_double = NULL; |
| 8791 if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { | 8881 if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { |
| 8792 // Pessimistically allocate space for return value before | 8882 // Pessimistically allocate space for return value before |
| 8793 // we start mutating the array. | 8883 // we start mutating the array. |
| 8794 Object* new_double; | 8884 Object* new_double; |
| 8795 { MaybeObject* maybe_new_double = Heap::AllocateHeapNumber(0.0); | 8885 { MaybeObject* maybe_new_double = heap->AllocateHeapNumber(0.0); |
| 8796 if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double; | 8886 if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double; |
| 8797 } | 8887 } |
| 8798 result_double = HeapNumber::cast(new_double); | 8888 result_double = HeapNumber::cast(new_double); |
| 8799 } | 8889 } |
| 8800 | 8890 |
| 8801 AssertNoAllocation no_alloc; | 8891 AssertNoAllocation no_alloc; |
| 8802 | 8892 |
| 8803 // Split elements into defined, undefined and the_hole, in that order. | 8893 // Split elements into defined, undefined and the_hole, in that order. |
| 8804 // Only count locations for undefined and the hole, and fill them afterwards. | 8894 // Only count locations for undefined and the hole, and fill them afterwards. |
| 8805 WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_alloc); | 8895 WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_alloc); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8879 // converted to a number type further up in the call chain. | 8969 // converted to a number type further up in the call chain. |
| 8880 ASSERT(value->IsUndefined()); | 8970 ASSERT(value->IsUndefined()); |
| 8881 } | 8971 } |
| 8882 set(index, clamped_value); | 8972 set(index, clamped_value); |
| 8883 } | 8973 } |
| 8884 return Smi::FromInt(clamped_value); | 8974 return Smi::FromInt(clamped_value); |
| 8885 } | 8975 } |
| 8886 | 8976 |
| 8887 | 8977 |
| 8888 template<typename ExternalArrayClass, typename ValueType> | 8978 template<typename ExternalArrayClass, typename ValueType> |
| 8889 static MaybeObject* ExternalArrayIntSetter(ExternalArrayClass* receiver, | 8979 static MaybeObject* ExternalArrayIntSetter(Heap* heap, |
| 8980 ExternalArrayClass* receiver, |
| 8890 uint32_t index, | 8981 uint32_t index, |
| 8891 Object* value) { | 8982 Object* value) { |
| 8892 ValueType cast_value = 0; | 8983 ValueType cast_value = 0; |
| 8893 if (index < static_cast<uint32_t>(receiver->length())) { | 8984 if (index < static_cast<uint32_t>(receiver->length())) { |
| 8894 if (value->IsSmi()) { | 8985 if (value->IsSmi()) { |
| 8895 int int_value = Smi::cast(value)->value(); | 8986 int int_value = Smi::cast(value)->value(); |
| 8896 cast_value = static_cast<ValueType>(int_value); | 8987 cast_value = static_cast<ValueType>(int_value); |
| 8897 } else if (value->IsHeapNumber()) { | 8988 } else if (value->IsHeapNumber()) { |
| 8898 double double_value = HeapNumber::cast(value)->value(); | 8989 double double_value = HeapNumber::cast(value)->value(); |
| 8899 cast_value = static_cast<ValueType>(DoubleToInt32(double_value)); | 8990 cast_value = static_cast<ValueType>(DoubleToInt32(double_value)); |
| 8900 } else { | 8991 } else { |
| 8901 // Clamp undefined to zero (default). All other types have been | 8992 // Clamp undefined to zero (default). All other types have been |
| 8902 // converted to a number type further up in the call chain. | 8993 // converted to a number type further up in the call chain. |
| 8903 ASSERT(value->IsUndefined()); | 8994 ASSERT(value->IsUndefined()); |
| 8904 } | 8995 } |
| 8905 receiver->set(index, cast_value); | 8996 receiver->set(index, cast_value); |
| 8906 } | 8997 } |
| 8907 return Heap::NumberFromInt32(cast_value); | 8998 return heap->NumberFromInt32(cast_value); |
| 8908 } | 8999 } |
| 8909 | 9000 |
| 8910 | 9001 |
| 8911 MaybeObject* ExternalByteArray::SetValue(uint32_t index, Object* value) { | 9002 MaybeObject* ExternalByteArray::SetValue(uint32_t index, Object* value) { |
| 8912 return ExternalArrayIntSetter<ExternalByteArray, int8_t> | 9003 return ExternalArrayIntSetter<ExternalByteArray, int8_t> |
| 8913 (this, index, value); | 9004 (GetHeap(), this, index, value); |
| 8914 } | 9005 } |
| 8915 | 9006 |
| 8916 | 9007 |
| 8917 MaybeObject* ExternalUnsignedByteArray::SetValue(uint32_t index, | 9008 MaybeObject* ExternalUnsignedByteArray::SetValue(uint32_t index, |
| 8918 Object* value) { | 9009 Object* value) { |
| 8919 return ExternalArrayIntSetter<ExternalUnsignedByteArray, uint8_t> | 9010 return ExternalArrayIntSetter<ExternalUnsignedByteArray, uint8_t> |
| 8920 (this, index, value); | 9011 (GetHeap(), this, index, value); |
| 8921 } | 9012 } |
| 8922 | 9013 |
| 8923 | 9014 |
| 8924 MaybeObject* ExternalShortArray::SetValue(uint32_t index, | 9015 MaybeObject* ExternalShortArray::SetValue(uint32_t index, |
| 8925 Object* value) { | 9016 Object* value) { |
| 8926 return ExternalArrayIntSetter<ExternalShortArray, int16_t> | 9017 return ExternalArrayIntSetter<ExternalShortArray, int16_t> |
| 8927 (this, index, value); | 9018 (GetHeap(), this, index, value); |
| 8928 } | 9019 } |
| 8929 | 9020 |
| 8930 | 9021 |
| 8931 MaybeObject* ExternalUnsignedShortArray::SetValue(uint32_t index, | 9022 MaybeObject* ExternalUnsignedShortArray::SetValue(uint32_t index, |
| 8932 Object* value) { | 9023 Object* value) { |
| 8933 return ExternalArrayIntSetter<ExternalUnsignedShortArray, uint16_t> | 9024 return ExternalArrayIntSetter<ExternalUnsignedShortArray, uint16_t> |
| 8934 (this, index, value); | 9025 (GetHeap(), this, index, value); |
| 8935 } | 9026 } |
| 8936 | 9027 |
| 8937 | 9028 |
| 8938 MaybeObject* ExternalIntArray::SetValue(uint32_t index, Object* value) { | 9029 MaybeObject* ExternalIntArray::SetValue(uint32_t index, Object* value) { |
| 8939 return ExternalArrayIntSetter<ExternalIntArray, int32_t> | 9030 return ExternalArrayIntSetter<ExternalIntArray, int32_t> |
| 8940 (this, index, value); | 9031 (GetHeap(), this, index, value); |
| 8941 } | 9032 } |
| 8942 | 9033 |
| 8943 | 9034 |
| 8944 MaybeObject* ExternalUnsignedIntArray::SetValue(uint32_t index, Object* value) { | 9035 MaybeObject* ExternalUnsignedIntArray::SetValue(uint32_t index, Object* value) { |
| 8945 uint32_t cast_value = 0; | 9036 uint32_t cast_value = 0; |
| 9037 Heap* heap = GetHeap(); |
| 8946 if (index < static_cast<uint32_t>(length())) { | 9038 if (index < static_cast<uint32_t>(length())) { |
| 8947 if (value->IsSmi()) { | 9039 if (value->IsSmi()) { |
| 8948 int int_value = Smi::cast(value)->value(); | 9040 int int_value = Smi::cast(value)->value(); |
| 8949 cast_value = static_cast<uint32_t>(int_value); | 9041 cast_value = static_cast<uint32_t>(int_value); |
| 8950 } else if (value->IsHeapNumber()) { | 9042 } else if (value->IsHeapNumber()) { |
| 8951 double double_value = HeapNumber::cast(value)->value(); | 9043 double double_value = HeapNumber::cast(value)->value(); |
| 8952 cast_value = static_cast<uint32_t>(DoubleToUint32(double_value)); | 9044 cast_value = static_cast<uint32_t>(DoubleToUint32(double_value)); |
| 8953 } else { | 9045 } else { |
| 8954 // Clamp undefined to zero (default). All other types have been | 9046 // Clamp undefined to zero (default). All other types have been |
| 8955 // converted to a number type further up in the call chain. | 9047 // converted to a number type further up in the call chain. |
| 8956 ASSERT(value->IsUndefined()); | 9048 ASSERT(value->IsUndefined()); |
| 8957 } | 9049 } |
| 8958 set(index, cast_value); | 9050 set(index, cast_value); |
| 8959 } | 9051 } |
| 8960 return Heap::NumberFromUint32(cast_value); | 9052 return heap->NumberFromUint32(cast_value); |
| 8961 } | 9053 } |
| 8962 | 9054 |
| 8963 | 9055 |
| 8964 MaybeObject* ExternalFloatArray::SetValue(uint32_t index, Object* value) { | 9056 MaybeObject* ExternalFloatArray::SetValue(uint32_t index, Object* value) { |
| 8965 float cast_value = 0; | 9057 float cast_value = 0; |
| 9058 Heap* heap = GetHeap(); |
| 8966 if (index < static_cast<uint32_t>(length())) { | 9059 if (index < static_cast<uint32_t>(length())) { |
| 8967 if (value->IsSmi()) { | 9060 if (value->IsSmi()) { |
| 8968 int int_value = Smi::cast(value)->value(); | 9061 int int_value = Smi::cast(value)->value(); |
| 8969 cast_value = static_cast<float>(int_value); | 9062 cast_value = static_cast<float>(int_value); |
| 8970 } else if (value->IsHeapNumber()) { | 9063 } else if (value->IsHeapNumber()) { |
| 8971 double double_value = HeapNumber::cast(value)->value(); | 9064 double double_value = HeapNumber::cast(value)->value(); |
| 8972 cast_value = static_cast<float>(double_value); | 9065 cast_value = static_cast<float>(double_value); |
| 8973 } else { | 9066 } else { |
| 8974 // Clamp undefined to zero (default). All other types have been | 9067 // Clamp undefined to zero (default). All other types have been |
| 8975 // converted to a number type further up in the call chain. | 9068 // converted to a number type further up in the call chain. |
| 8976 ASSERT(value->IsUndefined()); | 9069 ASSERT(value->IsUndefined()); |
| 8977 } | 9070 } |
| 8978 set(index, cast_value); | 9071 set(index, cast_value); |
| 8979 } | 9072 } |
| 8980 return Heap::AllocateHeapNumber(cast_value); | 9073 return heap->AllocateHeapNumber(cast_value); |
| 8981 } | 9074 } |
| 8982 | 9075 |
| 8983 | 9076 |
| 8984 JSGlobalPropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) { | 9077 JSGlobalPropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) { |
| 8985 ASSERT(!HasFastProperties()); | 9078 ASSERT(!HasFastProperties()); |
| 8986 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); | 9079 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); |
| 8987 return JSGlobalPropertyCell::cast(value); | 9080 return JSGlobalPropertyCell::cast(value); |
| 8988 } | 9081 } |
| 8989 | 9082 |
| 8990 | 9083 |
| 8991 MaybeObject* GlobalObject::EnsurePropertyCell(String* name) { | 9084 MaybeObject* GlobalObject::EnsurePropertyCell(String* name) { |
| 8992 ASSERT(!HasFastProperties()); | 9085 ASSERT(!HasFastProperties()); |
| 9086 Heap* heap = GetHeap(); |
| 8993 int entry = property_dictionary()->FindEntry(name); | 9087 int entry = property_dictionary()->FindEntry(name); |
| 8994 if (entry == StringDictionary::kNotFound) { | 9088 if (entry == StringDictionary::kNotFound) { |
| 8995 Object* cell; | 9089 Object* cell; |
| 8996 { MaybeObject* maybe_cell = | 9090 { MaybeObject* maybe_cell = |
| 8997 Heap::AllocateJSGlobalPropertyCell(Heap::the_hole_value()); | 9091 heap->AllocateJSGlobalPropertyCell(heap->the_hole_value()); |
| 8998 if (!maybe_cell->ToObject(&cell)) return maybe_cell; | 9092 if (!maybe_cell->ToObject(&cell)) return maybe_cell; |
| 8999 } | 9093 } |
| 9000 PropertyDetails details(NONE, NORMAL); | 9094 PropertyDetails details(NONE, NORMAL); |
| 9001 details = details.AsDeleted(); | 9095 details = details.AsDeleted(); |
| 9002 Object* dictionary; | 9096 Object* dictionary; |
| 9003 { MaybeObject* maybe_dictionary = | 9097 { MaybeObject* maybe_dictionary = |
| 9004 property_dictionary()->Add(name, cell, details); | 9098 property_dictionary()->Add(name, cell, details); |
| 9005 if (!maybe_dictionary->ToObject(&dictionary)) return maybe_dictionary; | 9099 if (!maybe_dictionary->ToObject(&dictionary)) return maybe_dictionary; |
| 9006 } | 9100 } |
| 9007 set_properties(StringDictionary::cast(dictionary)); | 9101 set_properties(StringDictionary::cast(dictionary)); |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9159 // Add the new symbol and return it along with the symbol table. | 9253 // Add the new symbol and return it along with the symbol table. |
| 9160 entry = table->FindInsertionEntry(key->Hash()); | 9254 entry = table->FindInsertionEntry(key->Hash()); |
| 9161 table->set(EntryToIndex(entry), symbol); | 9255 table->set(EntryToIndex(entry), symbol); |
| 9162 table->ElementAdded(); | 9256 table->ElementAdded(); |
| 9163 *s = symbol; | 9257 *s = symbol; |
| 9164 return table; | 9258 return table; |
| 9165 } | 9259 } |
| 9166 | 9260 |
| 9167 | 9261 |
| 9168 Object* CompilationCacheTable::Lookup(String* src) { | 9262 Object* CompilationCacheTable::Lookup(String* src) { |
| 9263 Heap* heap = GetHeap(); |
| 9169 StringKey key(src); | 9264 StringKey key(src); |
| 9170 int entry = FindEntry(&key); | 9265 int entry = FindEntry(&key); |
| 9171 if (entry == kNotFound) return Heap::undefined_value(); | 9266 if (entry == kNotFound) return heap->undefined_value(); |
| 9172 return get(EntryToIndex(entry) + 1); | 9267 return get(EntryToIndex(entry) + 1); |
| 9173 } | 9268 } |
| 9174 | 9269 |
| 9175 | 9270 |
| 9176 Object* CompilationCacheTable::LookupEval(String* src, | 9271 Object* CompilationCacheTable::LookupEval(String* src, |
| 9177 Context* context, | 9272 Context* context, |
| 9178 StrictModeFlag strict_mode) { | 9273 StrictModeFlag strict_mode) { |
| 9179 StringSharedKey key(src, context->closure()->shared(), strict_mode); | 9274 StringSharedKey key(src, context->closure()->shared(), strict_mode); |
| 9180 int entry = FindEntry(&key); | 9275 int entry = FindEntry(&key); |
| 9181 if (entry == kNotFound) return Heap::undefined_value(); | 9276 if (entry == kNotFound) return GetHeap()->undefined_value(); |
| 9182 return get(EntryToIndex(entry) + 1); | 9277 return get(EntryToIndex(entry) + 1); |
| 9183 } | 9278 } |
| 9184 | 9279 |
| 9185 | 9280 |
| 9186 Object* CompilationCacheTable::LookupRegExp(String* src, | 9281 Object* CompilationCacheTable::LookupRegExp(String* src, |
| 9187 JSRegExp::Flags flags) { | 9282 JSRegExp::Flags flags) { |
| 9283 Heap* heap = GetHeap(); |
| 9188 RegExpKey key(src, flags); | 9284 RegExpKey key(src, flags); |
| 9189 int entry = FindEntry(&key); | 9285 int entry = FindEntry(&key); |
| 9190 if (entry == kNotFound) return Heap::undefined_value(); | 9286 if (entry == kNotFound) return heap->undefined_value(); |
| 9191 return get(EntryToIndex(entry) + 1); | 9287 return get(EntryToIndex(entry) + 1); |
| 9192 } | 9288 } |
| 9193 | 9289 |
| 9194 | 9290 |
| 9195 MaybeObject* CompilationCacheTable::Put(String* src, Object* value) { | 9291 MaybeObject* CompilationCacheTable::Put(String* src, Object* value) { |
| 9196 StringKey key(src); | 9292 StringKey key(src); |
| 9197 Object* obj; | 9293 Object* obj; |
| 9198 { MaybeObject* maybe_obj = EnsureCapacity(1, &key); | 9294 { MaybeObject* maybe_obj = EnsureCapacity(1, &key); |
| 9199 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 9295 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 9200 } | 9296 } |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9251 // We store the value in the key slot, and compare the search key | 9347 // We store the value in the key slot, and compare the search key |
| 9252 // to the stored value with a custon IsMatch function during lookups. | 9348 // to the stored value with a custon IsMatch function during lookups. |
| 9253 cache->set(EntryToIndex(entry), value); | 9349 cache->set(EntryToIndex(entry), value); |
| 9254 cache->set(EntryToIndex(entry) + 1, value); | 9350 cache->set(EntryToIndex(entry) + 1, value); |
| 9255 cache->ElementAdded(); | 9351 cache->ElementAdded(); |
| 9256 return cache; | 9352 return cache; |
| 9257 } | 9353 } |
| 9258 | 9354 |
| 9259 | 9355 |
| 9260 void CompilationCacheTable::Remove(Object* value) { | 9356 void CompilationCacheTable::Remove(Object* value) { |
| 9357 Object* null_value = GetHeap()->null_value(); |
| 9261 for (int entry = 0, size = Capacity(); entry < size; entry++) { | 9358 for (int entry = 0, size = Capacity(); entry < size; entry++) { |
| 9262 int entry_index = EntryToIndex(entry); | 9359 int entry_index = EntryToIndex(entry); |
| 9263 int value_index = entry_index + 1; | 9360 int value_index = entry_index + 1; |
| 9264 if (get(value_index) == value) { | 9361 if (get(value_index) == value) { |
| 9265 fast_set(this, entry_index, Heap::null_value()); | 9362 fast_set(this, entry_index, null_value); |
| 9266 fast_set(this, value_index, Heap::null_value()); | 9363 fast_set(this, value_index, null_value); |
| 9267 ElementRemoved(); | 9364 ElementRemoved(); |
| 9268 } | 9365 } |
| 9269 } | 9366 } |
| 9270 return; | 9367 return; |
| 9271 } | 9368 } |
| 9272 | 9369 |
| 9273 | 9370 |
| 9274 // SymbolsKey used for HashTable where key is array of symbols. | 9371 // SymbolsKey used for HashTable where key is array of symbols. |
| 9275 class SymbolsKey : public HashTableKey { | 9372 class SymbolsKey : public HashTableKey { |
| 9276 public: | 9373 public: |
| (...skipping 22 matching lines...) Expand all Loading... |
| 9299 } | 9396 } |
| 9300 | 9397 |
| 9301 Object* AsObject() { return symbols_; } | 9398 Object* AsObject() { return symbols_; } |
| 9302 | 9399 |
| 9303 private: | 9400 private: |
| 9304 FixedArray* symbols_; | 9401 FixedArray* symbols_; |
| 9305 }; | 9402 }; |
| 9306 | 9403 |
| 9307 | 9404 |
| 9308 Object* MapCache::Lookup(FixedArray* array) { | 9405 Object* MapCache::Lookup(FixedArray* array) { |
| 9406 Heap* heap = GetHeap(); |
| 9309 SymbolsKey key(array); | 9407 SymbolsKey key(array); |
| 9310 int entry = FindEntry(&key); | 9408 int entry = FindEntry(&key); |
| 9311 if (entry == kNotFound) return Heap::undefined_value(); | 9409 if (entry == kNotFound) return heap->undefined_value(); |
| 9312 return get(EntryToIndex(entry) + 1); | 9410 return get(EntryToIndex(entry) + 1); |
| 9313 } | 9411 } |
| 9314 | 9412 |
| 9315 | 9413 |
| 9316 MaybeObject* MapCache::Put(FixedArray* array, Map* value) { | 9414 MaybeObject* MapCache::Put(FixedArray* array, Map* value) { |
| 9317 SymbolsKey key(array); | 9415 SymbolsKey key(array); |
| 9318 Object* obj; | 9416 Object* obj; |
| 9319 { MaybeObject* maybe_obj = EnsureCapacity(1, &key); | 9417 { MaybeObject* maybe_obj = EnsureCapacity(1, &key); |
| 9320 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 9418 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 9321 } | 9419 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 9338 } | 9436 } |
| 9339 // Initialize the next enumeration index. | 9437 // Initialize the next enumeration index. |
| 9340 Dictionary<Shape, Key>::cast(obj)-> | 9438 Dictionary<Shape, Key>::cast(obj)-> |
| 9341 SetNextEnumerationIndex(PropertyDetails::kInitialIndex); | 9439 SetNextEnumerationIndex(PropertyDetails::kInitialIndex); |
| 9342 return obj; | 9440 return obj; |
| 9343 } | 9441 } |
| 9344 | 9442 |
| 9345 | 9443 |
| 9346 template<typename Shape, typename Key> | 9444 template<typename Shape, typename Key> |
| 9347 MaybeObject* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() { | 9445 MaybeObject* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() { |
| 9446 Heap* heap = Dictionary<Shape, Key>::GetHeap(); |
| 9348 int length = HashTable<Shape, Key>::NumberOfElements(); | 9447 int length = HashTable<Shape, Key>::NumberOfElements(); |
| 9349 | 9448 |
| 9350 // Allocate and initialize iteration order array. | 9449 // Allocate and initialize iteration order array. |
| 9351 Object* obj; | 9450 Object* obj; |
| 9352 { MaybeObject* maybe_obj = Heap::AllocateFixedArray(length); | 9451 { MaybeObject* maybe_obj = heap->AllocateFixedArray(length); |
| 9353 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 9452 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 9354 } | 9453 } |
| 9355 FixedArray* iteration_order = FixedArray::cast(obj); | 9454 FixedArray* iteration_order = FixedArray::cast(obj); |
| 9356 for (int i = 0; i < length; i++) { | 9455 for (int i = 0; i < length; i++) { |
| 9357 iteration_order->set(i, Smi::FromInt(i)); | 9456 iteration_order->set(i, Smi::FromInt(i)); |
| 9358 } | 9457 } |
| 9359 | 9458 |
| 9360 // Allocate array with enumeration order. | 9459 // Allocate array with enumeration order. |
| 9361 { MaybeObject* maybe_obj = Heap::AllocateFixedArray(length); | 9460 { MaybeObject* maybe_obj = heap->AllocateFixedArray(length); |
| 9362 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 9461 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 9363 } | 9462 } |
| 9364 FixedArray* enumeration_order = FixedArray::cast(obj); | 9463 FixedArray* enumeration_order = FixedArray::cast(obj); |
| 9365 | 9464 |
| 9366 // Fill the enumeration order array with property details. | 9465 // Fill the enumeration order array with property details. |
| 9367 int capacity = HashTable<Shape, Key>::Capacity(); | 9466 int capacity = HashTable<Shape, Key>::Capacity(); |
| 9368 int pos = 0; | 9467 int pos = 0; |
| 9369 for (int i = 0; i < capacity; i++) { | 9468 for (int i = 0; i < capacity; i++) { |
| 9370 if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) { | 9469 if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) { |
| 9371 enumeration_order->set(pos++, Smi::FromInt(DetailsAt(i).index())); | 9470 enumeration_order->set(pos++, Smi::FromInt(DetailsAt(i).index())); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9412 } | 9511 } |
| 9413 } | 9512 } |
| 9414 return HashTable<Shape, Key>::EnsureCapacity(n, key); | 9513 return HashTable<Shape, Key>::EnsureCapacity(n, key); |
| 9415 } | 9514 } |
| 9416 | 9515 |
| 9417 | 9516 |
| 9418 void NumberDictionary::RemoveNumberEntries(uint32_t from, uint32_t to) { | 9517 void NumberDictionary::RemoveNumberEntries(uint32_t from, uint32_t to) { |
| 9419 // Do nothing if the interval [from, to) is empty. | 9518 // Do nothing if the interval [from, to) is empty. |
| 9420 if (from >= to) return; | 9519 if (from >= to) return; |
| 9421 | 9520 |
| 9521 Heap* heap = GetHeap(); |
| 9422 int removed_entries = 0; | 9522 int removed_entries = 0; |
| 9423 Object* sentinel = Heap::null_value(); | 9523 Object* sentinel = heap->null_value(); |
| 9424 int capacity = Capacity(); | 9524 int capacity = Capacity(); |
| 9425 for (int i = 0; i < capacity; i++) { | 9525 for (int i = 0; i < capacity; i++) { |
| 9426 Object* key = KeyAt(i); | 9526 Object* key = KeyAt(i); |
| 9427 if (key->IsNumber()) { | 9527 if (key->IsNumber()) { |
| 9428 uint32_t number = static_cast<uint32_t>(key->Number()); | 9528 uint32_t number = static_cast<uint32_t>(key->Number()); |
| 9429 if (from <= number && number < to) { | 9529 if (from <= number && number < to) { |
| 9430 SetEntry(i, sentinel, sentinel, Smi::FromInt(0)); | 9530 SetEntry(i, sentinel, sentinel, Smi::FromInt(0)); |
| 9431 removed_entries++; | 9531 removed_entries++; |
| 9432 } | 9532 } |
| 9433 } | 9533 } |
| 9434 } | 9534 } |
| 9435 | 9535 |
| 9436 // Update the number of elements. | 9536 // Update the number of elements. |
| 9437 ElementsRemoved(removed_entries); | 9537 ElementsRemoved(removed_entries); |
| 9438 } | 9538 } |
| 9439 | 9539 |
| 9440 | 9540 |
| 9441 template<typename Shape, typename Key> | 9541 template<typename Shape, typename Key> |
| 9442 Object* Dictionary<Shape, Key>::DeleteProperty(int entry, | 9542 Object* Dictionary<Shape, Key>::DeleteProperty(int entry, |
| 9443 JSObject::DeleteMode mode) { | 9543 JSObject::DeleteMode mode) { |
| 9544 Heap* heap = Dictionary<Shape, Key>::GetHeap(); |
| 9444 PropertyDetails details = DetailsAt(entry); | 9545 PropertyDetails details = DetailsAt(entry); |
| 9445 // Ignore attributes if forcing a deletion. | 9546 // Ignore attributes if forcing a deletion. |
| 9446 if (details.IsDontDelete() && mode != JSObject::FORCE_DELETION) { | 9547 if (details.IsDontDelete() && mode != JSObject::FORCE_DELETION) { |
| 9447 return Heap::false_value(); | 9548 return heap->false_value(); |
| 9448 } | 9549 } |
| 9449 SetEntry(entry, Heap::null_value(), Heap::null_value(), Smi::FromInt(0)); | 9550 SetEntry(entry, heap->null_value(), heap->null_value(), Smi::FromInt(0)); |
| 9450 HashTable<Shape, Key>::ElementRemoved(); | 9551 HashTable<Shape, Key>::ElementRemoved(); |
| 9451 return Heap::true_value(); | 9552 return heap->true_value(); |
| 9452 } | 9553 } |
| 9453 | 9554 |
| 9454 | 9555 |
| 9455 template<typename Shape, typename Key> | 9556 template<typename Shape, typename Key> |
| 9456 MaybeObject* Dictionary<Shape, Key>::AtPut(Key key, Object* value) { | 9557 MaybeObject* Dictionary<Shape, Key>::AtPut(Key key, Object* value) { |
| 9457 int entry = this->FindEntry(key); | 9558 int entry = this->FindEntry(key); |
| 9458 | 9559 |
| 9459 // If the entry is present set the value; | 9560 // If the entry is present set the value; |
| 9460 if (entry != Dictionary<Shape, Key>::kNotFound) { | 9561 if (entry != Dictionary<Shape, Key>::kNotFound) { |
| 9461 ValueAtPut(entry, value); | 9562 ValueAtPut(entry, value); |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9654 storage->set(index++, k); | 9755 storage->set(index++, k); |
| 9655 } | 9756 } |
| 9656 } | 9757 } |
| 9657 ASSERT(storage->length() >= index); | 9758 ASSERT(storage->length() >= index); |
| 9658 } | 9759 } |
| 9659 | 9760 |
| 9660 | 9761 |
| 9661 // Backwards lookup (slow). | 9762 // Backwards lookup (slow). |
| 9662 template<typename Shape, typename Key> | 9763 template<typename Shape, typename Key> |
| 9663 Object* Dictionary<Shape, Key>::SlowReverseLookup(Object* value) { | 9764 Object* Dictionary<Shape, Key>::SlowReverseLookup(Object* value) { |
| 9765 Heap* heap = Dictionary<Shape, Key>::GetHeap(); |
| 9664 int capacity = HashTable<Shape, Key>::Capacity(); | 9766 int capacity = HashTable<Shape, Key>::Capacity(); |
| 9665 for (int i = 0; i < capacity; i++) { | 9767 for (int i = 0; i < capacity; i++) { |
| 9666 Object* k = HashTable<Shape, Key>::KeyAt(i); | 9768 Object* k = HashTable<Shape, Key>::KeyAt(i); |
| 9667 if (Dictionary<Shape, Key>::IsKey(k)) { | 9769 if (Dictionary<Shape, Key>::IsKey(k)) { |
| 9668 Object* e = ValueAt(i); | 9770 Object* e = ValueAt(i); |
| 9669 if (e->IsJSGlobalPropertyCell()) { | 9771 if (e->IsJSGlobalPropertyCell()) { |
| 9670 e = JSGlobalPropertyCell::cast(e)->value(); | 9772 e = JSGlobalPropertyCell::cast(e)->value(); |
| 9671 } | 9773 } |
| 9672 if (e == value) return k; | 9774 if (e == value) return k; |
| 9673 } | 9775 } |
| 9674 } | 9776 } |
| 9675 return Heap::undefined_value(); | 9777 return heap->undefined_value(); |
| 9676 } | 9778 } |
| 9677 | 9779 |
| 9678 | 9780 |
| 9679 MaybeObject* StringDictionary::TransformPropertiesToFastFor( | 9781 MaybeObject* StringDictionary::TransformPropertiesToFastFor( |
| 9680 JSObject* obj, int unused_property_fields) { | 9782 JSObject* obj, int unused_property_fields) { |
| 9783 Heap* heap = GetHeap(); |
| 9681 // Make sure we preserve dictionary representation if there are too many | 9784 // Make sure we preserve dictionary representation if there are too many |
| 9682 // descriptors. | 9785 // descriptors. |
| 9683 if (NumberOfElements() > DescriptorArray::kMaxNumberOfDescriptors) return obj; | 9786 if (NumberOfElements() > DescriptorArray::kMaxNumberOfDescriptors) return obj; |
| 9684 | 9787 |
| 9685 // Figure out if it is necessary to generate new enumeration indices. | 9788 // Figure out if it is necessary to generate new enumeration indices. |
| 9686 int max_enumeration_index = | 9789 int max_enumeration_index = |
| 9687 NextEnumerationIndex() + | 9790 NextEnumerationIndex() + |
| 9688 (DescriptorArray::kMaxNumberOfDescriptors - | 9791 (DescriptorArray::kMaxNumberOfDescriptors - |
| 9689 NumberOfElements()); | 9792 NumberOfElements()); |
| 9690 if (!PropertyDetails::IsValidIndex(max_enumeration_index)) { | 9793 if (!PropertyDetails::IsValidIndex(max_enumeration_index)) { |
| 9691 Object* result; | 9794 Object* result; |
| 9692 { MaybeObject* maybe_result = GenerateNewEnumerationIndices(); | 9795 { MaybeObject* maybe_result = GenerateNewEnumerationIndices(); |
| 9693 if (!maybe_result->ToObject(&result)) return maybe_result; | 9796 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 9694 } | 9797 } |
| 9695 } | 9798 } |
| 9696 | 9799 |
| 9697 int instance_descriptor_length = 0; | 9800 int instance_descriptor_length = 0; |
| 9698 int number_of_fields = 0; | 9801 int number_of_fields = 0; |
| 9699 | 9802 |
| 9700 // Compute the length of the instance descriptor. | 9803 // Compute the length of the instance descriptor. |
| 9701 int capacity = Capacity(); | 9804 int capacity = Capacity(); |
| 9702 for (int i = 0; i < capacity; i++) { | 9805 for (int i = 0; i < capacity; i++) { |
| 9703 Object* k = KeyAt(i); | 9806 Object* k = KeyAt(i); |
| 9704 if (IsKey(k)) { | 9807 if (IsKey(k)) { |
| 9705 Object* value = ValueAt(i); | 9808 Object* value = ValueAt(i); |
| 9706 PropertyType type = DetailsAt(i).type(); | 9809 PropertyType type = DetailsAt(i).type(); |
| 9707 ASSERT(type != FIELD); | 9810 ASSERT(type != FIELD); |
| 9708 instance_descriptor_length++; | 9811 instance_descriptor_length++; |
| 9709 if (type == NORMAL && | 9812 if (type == NORMAL && |
| 9710 (!value->IsJSFunction() || Heap::InNewSpace(value))) { | 9813 (!value->IsJSFunction() || heap->InNewSpace(value))) { |
| 9711 number_of_fields += 1; | 9814 number_of_fields += 1; |
| 9712 } | 9815 } |
| 9713 } | 9816 } |
| 9714 } | 9817 } |
| 9715 | 9818 |
| 9716 // Allocate the instance descriptor. | 9819 // Allocate the instance descriptor. |
| 9717 Object* descriptors_unchecked; | 9820 Object* descriptors_unchecked; |
| 9718 { MaybeObject* maybe_descriptors_unchecked = | 9821 { MaybeObject* maybe_descriptors_unchecked = |
| 9719 DescriptorArray::Allocate(instance_descriptor_length); | 9822 DescriptorArray::Allocate(instance_descriptor_length); |
| 9720 if (!maybe_descriptors_unchecked->ToObject(&descriptors_unchecked)) { | 9823 if (!maybe_descriptors_unchecked->ToObject(&descriptors_unchecked)) { |
| 9721 return maybe_descriptors_unchecked; | 9824 return maybe_descriptors_unchecked; |
| 9722 } | 9825 } |
| 9723 } | 9826 } |
| 9724 DescriptorArray* descriptors = DescriptorArray::cast(descriptors_unchecked); | 9827 DescriptorArray* descriptors = DescriptorArray::cast(descriptors_unchecked); |
| 9725 | 9828 |
| 9726 int inobject_props = obj->map()->inobject_properties(); | 9829 int inobject_props = obj->map()->inobject_properties(); |
| 9727 int number_of_allocated_fields = | 9830 int number_of_allocated_fields = |
| 9728 number_of_fields + unused_property_fields - inobject_props; | 9831 number_of_fields + unused_property_fields - inobject_props; |
| 9729 if (number_of_allocated_fields < 0) { | 9832 if (number_of_allocated_fields < 0) { |
| 9730 // There is enough inobject space for all fields (including unused). | 9833 // There is enough inobject space for all fields (including unused). |
| 9731 number_of_allocated_fields = 0; | 9834 number_of_allocated_fields = 0; |
| 9732 unused_property_fields = inobject_props - number_of_fields; | 9835 unused_property_fields = inobject_props - number_of_fields; |
| 9733 } | 9836 } |
| 9734 | 9837 |
| 9735 // Allocate the fixed array for the fields. | 9838 // Allocate the fixed array for the fields. |
| 9736 Object* fields; | 9839 Object* fields; |
| 9737 { MaybeObject* maybe_fields = | 9840 { MaybeObject* maybe_fields = |
| 9738 Heap::AllocateFixedArray(number_of_allocated_fields); | 9841 heap->AllocateFixedArray(number_of_allocated_fields); |
| 9739 if (!maybe_fields->ToObject(&fields)) return maybe_fields; | 9842 if (!maybe_fields->ToObject(&fields)) return maybe_fields; |
| 9740 } | 9843 } |
| 9741 | 9844 |
| 9742 // Fill in the instance descriptor and the fields. | 9845 // Fill in the instance descriptor and the fields. |
| 9743 int next_descriptor = 0; | 9846 int next_descriptor = 0; |
| 9744 int current_offset = 0; | 9847 int current_offset = 0; |
| 9745 for (int i = 0; i < capacity; i++) { | 9848 for (int i = 0; i < capacity; i++) { |
| 9746 Object* k = KeyAt(i); | 9849 Object* k = KeyAt(i); |
| 9747 if (IsKey(k)) { | 9850 if (IsKey(k)) { |
| 9748 Object* value = ValueAt(i); | 9851 Object* value = ValueAt(i); |
| 9749 // Ensure the key is a symbol before writing into the instance descriptor. | 9852 // Ensure the key is a symbol before writing into the instance descriptor. |
| 9750 Object* key; | 9853 Object* key; |
| 9751 { MaybeObject* maybe_key = Heap::LookupSymbol(String::cast(k)); | 9854 { MaybeObject* maybe_key = heap->LookupSymbol(String::cast(k)); |
| 9752 if (!maybe_key->ToObject(&key)) return maybe_key; | 9855 if (!maybe_key->ToObject(&key)) return maybe_key; |
| 9753 } | 9856 } |
| 9754 PropertyDetails details = DetailsAt(i); | 9857 PropertyDetails details = DetailsAt(i); |
| 9755 PropertyType type = details.type(); | 9858 PropertyType type = details.type(); |
| 9756 | 9859 |
| 9757 if (value->IsJSFunction() && !Heap::InNewSpace(value)) { | 9860 if (value->IsJSFunction() && !heap->InNewSpace(value)) { |
| 9758 ConstantFunctionDescriptor d(String::cast(key), | 9861 ConstantFunctionDescriptor d(String::cast(key), |
| 9759 JSFunction::cast(value), | 9862 JSFunction::cast(value), |
| 9760 details.attributes(), | 9863 details.attributes(), |
| 9761 details.index()); | 9864 details.index()); |
| 9762 descriptors->Set(next_descriptor++, &d); | 9865 descriptors->Set(next_descriptor++, &d); |
| 9763 } else if (type == NORMAL) { | 9866 } else if (type == NORMAL) { |
| 9764 if (current_offset < inobject_props) { | 9867 if (current_offset < inobject_props) { |
| 9765 obj->InObjectPropertyAtPut(current_offset, | 9868 obj->InObjectPropertyAtPut(current_offset, |
| 9766 value, | 9869 value, |
| 9767 UPDATE_WRITE_BARRIER); | 9870 UPDATE_WRITE_BARRIER); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9818 | 9921 |
| 9819 // If there is no break point info object or no break points in the break | 9922 // If there is no break point info object or no break points in the break |
| 9820 // point info object there is no break point at this code position. | 9923 // point info object there is no break point at this code position. |
| 9821 if (break_point_info->IsUndefined()) return false; | 9924 if (break_point_info->IsUndefined()) return false; |
| 9822 return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0; | 9925 return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0; |
| 9823 } | 9926 } |
| 9824 | 9927 |
| 9825 | 9928 |
| 9826 // Get the break point info object for this code position. | 9929 // Get the break point info object for this code position. |
| 9827 Object* DebugInfo::GetBreakPointInfo(int code_position) { | 9930 Object* DebugInfo::GetBreakPointInfo(int code_position) { |
| 9931 Heap* heap = GetHeap(); |
| 9828 // Find the index of the break point info object for this code position. | 9932 // Find the index of the break point info object for this code position. |
| 9829 int index = GetBreakPointInfoIndex(code_position); | 9933 int index = GetBreakPointInfoIndex(code_position); |
| 9830 | 9934 |
| 9831 // Return the break point info object if any. | 9935 // Return the break point info object if any. |
| 9832 if (index == kNoBreakPointInfo) return Heap::undefined_value(); | 9936 if (index == kNoBreakPointInfo) return heap->undefined_value(); |
| 9833 return BreakPointInfo::cast(break_points()->get(index)); | 9937 return BreakPointInfo::cast(break_points()->get(index)); |
| 9834 } | 9938 } |
| 9835 | 9939 |
| 9836 | 9940 |
| 9837 // Clear a break point at the specified code position. | 9941 // Clear a break point at the specified code position. |
| 9838 void DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info, | 9942 void DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info, |
| 9839 int code_position, | 9943 int code_position, |
| 9840 Handle<Object> break_point_object) { | 9944 Handle<Object> break_point_object) { |
| 9841 Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position)); | 9945 Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position)); |
| 9842 if (break_point_info->IsUndefined()) return; | 9946 if (break_point_info->IsUndefined()) return; |
| 9843 BreakPointInfo::ClearBreakPoint( | 9947 BreakPointInfo::ClearBreakPoint( |
| 9844 Handle<BreakPointInfo>::cast(break_point_info), | 9948 Handle<BreakPointInfo>::cast(break_point_info), |
| 9845 break_point_object); | 9949 break_point_object); |
| 9846 } | 9950 } |
| 9847 | 9951 |
| 9848 | 9952 |
| 9849 void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info, | 9953 void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info, |
| 9850 int code_position, | 9954 int code_position, |
| 9851 int source_position, | 9955 int source_position, |
| 9852 int statement_position, | 9956 int statement_position, |
| 9853 Handle<Object> break_point_object) { | 9957 Handle<Object> break_point_object) { |
| 9958 Isolate* isolate = Isolate::Current(); |
| 9854 Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position)); | 9959 Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position)); |
| 9855 if (!break_point_info->IsUndefined()) { | 9960 if (!break_point_info->IsUndefined()) { |
| 9856 BreakPointInfo::SetBreakPoint( | 9961 BreakPointInfo::SetBreakPoint( |
| 9857 Handle<BreakPointInfo>::cast(break_point_info), | 9962 Handle<BreakPointInfo>::cast(break_point_info), |
| 9858 break_point_object); | 9963 break_point_object); |
| 9859 return; | 9964 return; |
| 9860 } | 9965 } |
| 9861 | 9966 |
| 9862 // Adding a new break point for a code position which did not have any | 9967 // Adding a new break point for a code position which did not have any |
| 9863 // break points before. Try to find a free slot. | 9968 // break points before. Try to find a free slot. |
| 9864 int index = kNoBreakPointInfo; | 9969 int index = kNoBreakPointInfo; |
| 9865 for (int i = 0; i < debug_info->break_points()->length(); i++) { | 9970 for (int i = 0; i < debug_info->break_points()->length(); i++) { |
| 9866 if (debug_info->break_points()->get(i)->IsUndefined()) { | 9971 if (debug_info->break_points()->get(i)->IsUndefined()) { |
| 9867 index = i; | 9972 index = i; |
| 9868 break; | 9973 break; |
| 9869 } | 9974 } |
| 9870 } | 9975 } |
| 9871 if (index == kNoBreakPointInfo) { | 9976 if (index == kNoBreakPointInfo) { |
| 9872 // No free slot - extend break point info array. | 9977 // No free slot - extend break point info array. |
| 9873 Handle<FixedArray> old_break_points = | 9978 Handle<FixedArray> old_break_points = |
| 9874 Handle<FixedArray>(FixedArray::cast(debug_info->break_points())); | 9979 Handle<FixedArray>(FixedArray::cast(debug_info->break_points())); |
| 9875 Handle<FixedArray> new_break_points = | 9980 Handle<FixedArray> new_break_points = |
| 9876 Factory::NewFixedArray(old_break_points->length() + | 9981 isolate->factory()->NewFixedArray( |
| 9877 Debug::kEstimatedNofBreakPointsInFunction); | 9982 old_break_points->length() + |
| 9983 Debug::kEstimatedNofBreakPointsInFunction); |
| 9878 | 9984 |
| 9879 debug_info->set_break_points(*new_break_points); | 9985 debug_info->set_break_points(*new_break_points); |
| 9880 for (int i = 0; i < old_break_points->length(); i++) { | 9986 for (int i = 0; i < old_break_points->length(); i++) { |
| 9881 new_break_points->set(i, old_break_points->get(i)); | 9987 new_break_points->set(i, old_break_points->get(i)); |
| 9882 } | 9988 } |
| 9883 index = old_break_points->length(); | 9989 index = old_break_points->length(); |
| 9884 } | 9990 } |
| 9885 ASSERT(index != kNoBreakPointInfo); | 9991 ASSERT(index != kNoBreakPointInfo); |
| 9886 | 9992 |
| 9887 // Allocate new BreakPointInfo object and set the break point. | 9993 // Allocate new BreakPointInfo object and set the break point. |
| 9888 Handle<BreakPointInfo> new_break_point_info = | 9994 Handle<BreakPointInfo> new_break_point_info = Handle<BreakPointInfo>::cast( |
| 9889 Handle<BreakPointInfo>::cast(Factory::NewStruct(BREAK_POINT_INFO_TYPE)); | 9995 isolate->factory()->NewStruct(BREAK_POINT_INFO_TYPE)); |
| 9890 new_break_point_info->set_code_position(Smi::FromInt(code_position)); | 9996 new_break_point_info->set_code_position(Smi::FromInt(code_position)); |
| 9891 new_break_point_info->set_source_position(Smi::FromInt(source_position)); | 9997 new_break_point_info->set_source_position(Smi::FromInt(source_position)); |
| 9892 new_break_point_info-> | 9998 new_break_point_info-> |
| 9893 set_statement_position(Smi::FromInt(statement_position)); | 9999 set_statement_position(Smi::FromInt(statement_position)); |
| 9894 new_break_point_info->set_break_point_objects(Heap::undefined_value()); | 10000 new_break_point_info->set_break_point_objects( |
| 10001 isolate->heap()->undefined_value()); |
| 9895 BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object); | 10002 BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object); |
| 9896 debug_info->break_points()->set(index, *new_break_point_info); | 10003 debug_info->break_points()->set(index, *new_break_point_info); |
| 9897 } | 10004 } |
| 9898 | 10005 |
| 9899 | 10006 |
| 9900 // Get the break point objects for a code position. | 10007 // Get the break point objects for a code position. |
| 9901 Object* DebugInfo::GetBreakPointObjects(int code_position) { | 10008 Object* DebugInfo::GetBreakPointObjects(int code_position) { |
| 10009 Heap* heap = GetHeap(); |
| 9902 Object* break_point_info = GetBreakPointInfo(code_position); | 10010 Object* break_point_info = GetBreakPointInfo(code_position); |
| 9903 if (break_point_info->IsUndefined()) { | 10011 if (break_point_info->IsUndefined()) { |
| 9904 return Heap::undefined_value(); | 10012 return heap->undefined_value(); |
| 9905 } | 10013 } |
| 9906 return BreakPointInfo::cast(break_point_info)->break_point_objects(); | 10014 return BreakPointInfo::cast(break_point_info)->break_point_objects(); |
| 9907 } | 10015 } |
| 9908 | 10016 |
| 9909 | 10017 |
| 9910 // Get the total number of break points. | 10018 // Get the total number of break points. |
| 9911 int DebugInfo::GetBreakPointCount() { | 10019 int DebugInfo::GetBreakPointCount() { |
| 9912 if (break_points()->IsUndefined()) return 0; | 10020 if (break_points()->IsUndefined()) return 0; |
| 9913 int count = 0; | 10021 int count = 0; |
| 9914 for (int i = 0; i < break_points()->length(); i++) { | 10022 for (int i = 0; i < break_points()->length(); i++) { |
| 9915 if (!break_points()->get(i)->IsUndefined()) { | 10023 if (!break_points()->get(i)->IsUndefined()) { |
| 9916 BreakPointInfo* break_point_info = | 10024 BreakPointInfo* break_point_info = |
| 9917 BreakPointInfo::cast(break_points()->get(i)); | 10025 BreakPointInfo::cast(break_points()->get(i)); |
| 9918 count += break_point_info->GetBreakPointCount(); | 10026 count += break_point_info->GetBreakPointCount(); |
| 9919 } | 10027 } |
| 9920 } | 10028 } |
| 9921 return count; | 10029 return count; |
| 9922 } | 10030 } |
| 9923 | 10031 |
| 9924 | 10032 |
| 9925 Object* DebugInfo::FindBreakPointInfo(Handle<DebugInfo> debug_info, | 10033 Object* DebugInfo::FindBreakPointInfo(Handle<DebugInfo> debug_info, |
| 9926 Handle<Object> break_point_object) { | 10034 Handle<Object> break_point_object) { |
| 9927 if (debug_info->break_points()->IsUndefined()) return Heap::undefined_value(); | 10035 Heap* heap = Isolate::Current()->heap(); |
| 10036 if (debug_info->break_points()->IsUndefined()) return heap->undefined_value(); |
| 9928 for (int i = 0; i < debug_info->break_points()->length(); i++) { | 10037 for (int i = 0; i < debug_info->break_points()->length(); i++) { |
| 9929 if (!debug_info->break_points()->get(i)->IsUndefined()) { | 10038 if (!debug_info->break_points()->get(i)->IsUndefined()) { |
| 9930 Handle<BreakPointInfo> break_point_info = | 10039 Handle<BreakPointInfo> break_point_info = |
| 9931 Handle<BreakPointInfo>(BreakPointInfo::cast( | 10040 Handle<BreakPointInfo>(BreakPointInfo::cast( |
| 9932 debug_info->break_points()->get(i))); | 10041 debug_info->break_points()->get(i))); |
| 9933 if (BreakPointInfo::HasBreakPointObject(break_point_info, | 10042 if (BreakPointInfo::HasBreakPointObject(break_point_info, |
| 9934 break_point_object)) { | 10043 break_point_object)) { |
| 9935 return *break_point_info; | 10044 return *break_point_info; |
| 9936 } | 10045 } |
| 9937 } | 10046 } |
| 9938 } | 10047 } |
| 9939 return Heap::undefined_value(); | 10048 return heap->undefined_value(); |
| 9940 } | 10049 } |
| 9941 | 10050 |
| 9942 | 10051 |
| 9943 // Find the index of the break point info object for the specified code | 10052 // Find the index of the break point info object for the specified code |
| 9944 // position. | 10053 // position. |
| 9945 int DebugInfo::GetBreakPointInfoIndex(int code_position) { | 10054 int DebugInfo::GetBreakPointInfoIndex(int code_position) { |
| 9946 if (break_points()->IsUndefined()) return kNoBreakPointInfo; | 10055 if (break_points()->IsUndefined()) return kNoBreakPointInfo; |
| 9947 for (int i = 0; i < break_points()->length(); i++) { | 10056 for (int i = 0; i < break_points()->length(); i++) { |
| 9948 if (!break_points()->get(i)->IsUndefined()) { | 10057 if (!break_points()->get(i)->IsUndefined()) { |
| 9949 BreakPointInfo* break_point_info = | 10058 BreakPointInfo* break_point_info = |
| 9950 BreakPointInfo::cast(break_points()->get(i)); | 10059 BreakPointInfo::cast(break_points()->get(i)); |
| 9951 if (break_point_info->code_position()->value() == code_position) { | 10060 if (break_point_info->code_position()->value() == code_position) { |
| 9952 return i; | 10061 return i; |
| 9953 } | 10062 } |
| 9954 } | 10063 } |
| 9955 } | 10064 } |
| 9956 return kNoBreakPointInfo; | 10065 return kNoBreakPointInfo; |
| 9957 } | 10066 } |
| 9958 | 10067 |
| 9959 | 10068 |
| 9960 // Remove the specified break point object. | 10069 // Remove the specified break point object. |
| 9961 void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info, | 10070 void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info, |
| 9962 Handle<Object> break_point_object) { | 10071 Handle<Object> break_point_object) { |
| 10072 Isolate* isolate = Isolate::Current(); |
| 9963 // If there are no break points just ignore. | 10073 // If there are no break points just ignore. |
| 9964 if (break_point_info->break_point_objects()->IsUndefined()) return; | 10074 if (break_point_info->break_point_objects()->IsUndefined()) return; |
| 9965 // If there is a single break point clear it if it is the same. | 10075 // If there is a single break point clear it if it is the same. |
| 9966 if (!break_point_info->break_point_objects()->IsFixedArray()) { | 10076 if (!break_point_info->break_point_objects()->IsFixedArray()) { |
| 9967 if (break_point_info->break_point_objects() == *break_point_object) { | 10077 if (break_point_info->break_point_objects() == *break_point_object) { |
| 9968 break_point_info->set_break_point_objects(Heap::undefined_value()); | 10078 break_point_info->set_break_point_objects( |
| 10079 isolate->heap()->undefined_value()); |
| 9969 } | 10080 } |
| 9970 return; | 10081 return; |
| 9971 } | 10082 } |
| 9972 // If there are multiple break points shrink the array | 10083 // If there are multiple break points shrink the array |
| 9973 ASSERT(break_point_info->break_point_objects()->IsFixedArray()); | 10084 ASSERT(break_point_info->break_point_objects()->IsFixedArray()); |
| 9974 Handle<FixedArray> old_array = | 10085 Handle<FixedArray> old_array = |
| 9975 Handle<FixedArray>( | 10086 Handle<FixedArray>( |
| 9976 FixedArray::cast(break_point_info->break_point_objects())); | 10087 FixedArray::cast(break_point_info->break_point_objects())); |
| 9977 Handle<FixedArray> new_array = | 10088 Handle<FixedArray> new_array = |
| 9978 Factory::NewFixedArray(old_array->length() - 1); | 10089 isolate->factory()->NewFixedArray(old_array->length() - 1); |
| 9979 int found_count = 0; | 10090 int found_count = 0; |
| 9980 for (int i = 0; i < old_array->length(); i++) { | 10091 for (int i = 0; i < old_array->length(); i++) { |
| 9981 if (old_array->get(i) == *break_point_object) { | 10092 if (old_array->get(i) == *break_point_object) { |
| 9982 ASSERT(found_count == 0); | 10093 ASSERT(found_count == 0); |
| 9983 found_count++; | 10094 found_count++; |
| 9984 } else { | 10095 } else { |
| 9985 new_array->set(i - found_count, old_array->get(i)); | 10096 new_array->set(i - found_count, old_array->get(i)); |
| 9986 } | 10097 } |
| 9987 } | 10098 } |
| 9988 // If the break point was found in the list change it. | 10099 // If the break point was found in the list change it. |
| 9989 if (found_count > 0) break_point_info->set_break_point_objects(*new_array); | 10100 if (found_count > 0) break_point_info->set_break_point_objects(*new_array); |
| 9990 } | 10101 } |
| 9991 | 10102 |
| 9992 | 10103 |
| 9993 // Add the specified break point object. | 10104 // Add the specified break point object. |
| 9994 void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info, | 10105 void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info, |
| 9995 Handle<Object> break_point_object) { | 10106 Handle<Object> break_point_object) { |
| 9996 // If there was no break point objects before just set it. | 10107 // If there was no break point objects before just set it. |
| 9997 if (break_point_info->break_point_objects()->IsUndefined()) { | 10108 if (break_point_info->break_point_objects()->IsUndefined()) { |
| 9998 break_point_info->set_break_point_objects(*break_point_object); | 10109 break_point_info->set_break_point_objects(*break_point_object); |
| 9999 return; | 10110 return; |
| 10000 } | 10111 } |
| 10001 // If the break point object is the same as before just ignore. | 10112 // If the break point object is the same as before just ignore. |
| 10002 if (break_point_info->break_point_objects() == *break_point_object) return; | 10113 if (break_point_info->break_point_objects() == *break_point_object) return; |
| 10003 // If there was one break point object before replace with array. | 10114 // If there was one break point object before replace with array. |
| 10004 if (!break_point_info->break_point_objects()->IsFixedArray()) { | 10115 if (!break_point_info->break_point_objects()->IsFixedArray()) { |
| 10005 Handle<FixedArray> array = Factory::NewFixedArray(2); | 10116 Handle<FixedArray> array = FACTORY->NewFixedArray(2); |
| 10006 array->set(0, break_point_info->break_point_objects()); | 10117 array->set(0, break_point_info->break_point_objects()); |
| 10007 array->set(1, *break_point_object); | 10118 array->set(1, *break_point_object); |
| 10008 break_point_info->set_break_point_objects(*array); | 10119 break_point_info->set_break_point_objects(*array); |
| 10009 return; | 10120 return; |
| 10010 } | 10121 } |
| 10011 // If there was more than one break point before extend array. | 10122 // If there was more than one break point before extend array. |
| 10012 Handle<FixedArray> old_array = | 10123 Handle<FixedArray> old_array = |
| 10013 Handle<FixedArray>( | 10124 Handle<FixedArray>( |
| 10014 FixedArray::cast(break_point_info->break_point_objects())); | 10125 FixedArray::cast(break_point_info->break_point_objects())); |
| 10015 Handle<FixedArray> new_array = | 10126 Handle<FixedArray> new_array = |
| 10016 Factory::NewFixedArray(old_array->length() + 1); | 10127 FACTORY->NewFixedArray(old_array->length() + 1); |
| 10017 for (int i = 0; i < old_array->length(); i++) { | 10128 for (int i = 0; i < old_array->length(); i++) { |
| 10018 // If the break point was there before just ignore. | 10129 // If the break point was there before just ignore. |
| 10019 if (old_array->get(i) == *break_point_object) return; | 10130 if (old_array->get(i) == *break_point_object) return; |
| 10020 new_array->set(i, old_array->get(i)); | 10131 new_array->set(i, old_array->get(i)); |
| 10021 } | 10132 } |
| 10022 // Add the new break point. | 10133 // Add the new break point. |
| 10023 new_array->set(old_array->length(), *break_point_object); | 10134 new_array->set(old_array->length(), *break_point_object); |
| 10024 break_point_info->set_break_point_objects(*new_array); | 10135 break_point_info->set_break_point_objects(*new_array); |
| 10025 } | 10136 } |
| 10026 | 10137 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 10051 if (break_point_objects()->IsUndefined()) return 0; | 10162 if (break_point_objects()->IsUndefined()) return 0; |
| 10052 // Single beak point. | 10163 // Single beak point. |
| 10053 if (!break_point_objects()->IsFixedArray()) return 1; | 10164 if (!break_point_objects()->IsFixedArray()) return 1; |
| 10054 // Multiple break points. | 10165 // Multiple break points. |
| 10055 return FixedArray::cast(break_point_objects())->length(); | 10166 return FixedArray::cast(break_point_objects())->length(); |
| 10056 } | 10167 } |
| 10057 #endif | 10168 #endif |
| 10058 | 10169 |
| 10059 | 10170 |
| 10060 } } // namespace v8::internal | 10171 } } // namespace v8::internal |
| OLD | NEW |