Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/objects.cc

Issue 8139027: Version 3.6.5 (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: '' Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 21 matching lines...) Expand all
32 #include "bootstrapper.h" 32 #include "bootstrapper.h"
33 #include "codegen.h" 33 #include "codegen.h"
34 #include "debug.h" 34 #include "debug.h"
35 #include "deoptimizer.h" 35 #include "deoptimizer.h"
36 #include "elements.h" 36 #include "elements.h"
37 #include "execution.h" 37 #include "execution.h"
38 #include "full-codegen.h" 38 #include "full-codegen.h"
39 #include "hydrogen.h" 39 #include "hydrogen.h"
40 #include "objects-inl.h" 40 #include "objects-inl.h"
41 #include "objects-visiting.h" 41 #include "objects-visiting.h"
42 #include "objects-visiting-inl.h"
42 #include "macro-assembler.h" 43 #include "macro-assembler.h"
44 #include "mark-compact.h"
43 #include "safepoint-table.h" 45 #include "safepoint-table.h"
44 #include "string-stream.h" 46 #include "string-stream.h"
45 #include "utils.h" 47 #include "utils.h"
46 #include "vm-state-inl.h" 48 #include "vm-state-inl.h"
47 49
48 #ifdef ENABLE_DISASSEMBLER 50 #ifdef ENABLE_DISASSEMBLER
49 #include "disasm.h" 51 #include "disasm.h"
50 #include "disassembler.h" 52 #include "disassembler.h"
51 #endif 53 #endif
52 54
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 } 127 }
126 if (heap_object->IsHeapNumber()) { 128 if (heap_object->IsHeapNumber()) {
127 return HeapNumber::cast(this)->HeapNumberToBoolean(); 129 return HeapNumber::cast(this)->HeapNumberToBoolean();
128 } 130 }
129 return heap_object->GetHeap()->true_value(); 131 return heap_object->GetHeap()->true_value();
130 } 132 }
131 133
132 134
133 void Object::Lookup(String* name, LookupResult* result) { 135 void Object::Lookup(String* name, LookupResult* result) {
134 Object* holder = NULL; 136 Object* holder = NULL;
135 if (IsSmi()) { 137 if (IsJSReceiver()) {
138 holder = this;
139 } else {
136 Context* global_context = Isolate::Current()->context()->global_context(); 140 Context* global_context = Isolate::Current()->context()->global_context();
137 holder = global_context->number_function()->instance_prototype(); 141 if (IsNumber()) {
138 } else { 142 holder = global_context->number_function()->instance_prototype();
139 HeapObject* heap_object = HeapObject::cast(this); 143 } else if (IsString()) {
140 if (heap_object->IsJSObject()) {
141 return JSObject::cast(this)->Lookup(name, result);
142 } else if (heap_object->IsJSProxy()) {
143 return result->HandlerResult();
144 }
145 Context* global_context = Isolate::Current()->context()->global_context();
146 if (heap_object->IsString()) {
147 holder = global_context->string_function()->instance_prototype(); 144 holder = global_context->string_function()->instance_prototype();
148 } else if (heap_object->IsHeapNumber()) { 145 } else if (IsBoolean()) {
149 holder = global_context->number_function()->instance_prototype();
150 } else if (heap_object->IsBoolean()) {
151 holder = global_context->boolean_function()->instance_prototype(); 146 holder = global_context->boolean_function()->instance_prototype();
152 } 147 }
153 } 148 }
154 ASSERT(holder != NULL); // Cannot handle null or undefined. 149 ASSERT(holder != NULL); // Cannot handle null or undefined.
155 JSObject::cast(holder)->Lookup(name, result); 150 JSReceiver::cast(holder)->Lookup(name, result);
156 } 151 }
157 152
158 153
159 MaybeObject* Object::GetPropertyWithReceiver(Object* receiver, 154 MaybeObject* Object::GetPropertyWithReceiver(Object* receiver,
160 String* name, 155 String* name,
161 PropertyAttributes* attributes) { 156 PropertyAttributes* attributes) {
162 LookupResult result; 157 LookupResult result;
163 Lookup(name, &result); 158 Lookup(name, &result);
164 MaybeObject* value = GetProperty(receiver, &result, name, attributes); 159 MaybeObject* value = GetProperty(receiver, &result, name, attributes);
165 ASSERT(*attributes <= ABSENT); 160 ASSERT(*attributes <= ABSENT);
166 return value; 161 return value;
167 } 162 }
168 163
169 164
170 MaybeObject* Object::GetPropertyWithCallback(Object* receiver, 165 MaybeObject* JSObject::GetPropertyWithCallback(Object* receiver,
171 Object* structure, 166 Object* structure,
172 String* name, 167 String* name) {
173 Object* holder) {
174 Isolate* isolate = name->GetIsolate(); 168 Isolate* isolate = name->GetIsolate();
175 // To accommodate both the old and the new api we switch on the 169 // To accommodate both the old and the new api we switch on the
176 // data structure used to store the callbacks. Eventually foreign 170 // data structure used to store the callbacks. Eventually foreign
177 // callbacks should be phased out. 171 // callbacks should be phased out.
178 if (structure->IsForeign()) { 172 if (structure->IsForeign()) {
179 AccessorDescriptor* callback = 173 AccessorDescriptor* callback =
180 reinterpret_cast<AccessorDescriptor*>( 174 reinterpret_cast<AccessorDescriptor*>(
181 Foreign::cast(structure)->address()); 175 Foreign::cast(structure)->address());
182 MaybeObject* value = (callback->getter)(receiver, callback->data); 176 MaybeObject* value = (callback->getter)(receiver, callback->data);
183 RETURN_IF_SCHEDULED_EXCEPTION(isolate); 177 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
184 return value; 178 return value;
185 } 179 }
186 180
187 // api style callbacks. 181 // api style callbacks.
188 if (structure->IsAccessorInfo()) { 182 if (structure->IsAccessorInfo()) {
189 AccessorInfo* data = AccessorInfo::cast(structure); 183 AccessorInfo* data = AccessorInfo::cast(structure);
190 Object* fun_obj = data->getter(); 184 Object* fun_obj = data->getter();
191 v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj); 185 v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj);
192 HandleScope scope(isolate); 186 HandleScope scope(isolate);
193 JSObject* self = JSObject::cast(receiver); 187 JSObject* self = JSObject::cast(receiver);
194 JSObject* holder_handle = JSObject::cast(holder);
195 Handle<String> key(name); 188 Handle<String> key(name);
196 LOG(isolate, ApiNamedPropertyAccess("load", self, name)); 189 LOG(isolate, ApiNamedPropertyAccess("load", self, name));
197 CustomArguments args(isolate, data->data(), self, holder_handle); 190 CustomArguments args(isolate, data->data(), self, this);
198 v8::AccessorInfo info(args.end()); 191 v8::AccessorInfo info(args.end());
199 v8::Handle<v8::Value> result; 192 v8::Handle<v8::Value> result;
200 { 193 {
201 // Leaving JavaScript. 194 // Leaving JavaScript.
202 VMState state(isolate, EXTERNAL); 195 VMState state(isolate, EXTERNAL);
203 result = call_fun(v8::Utils::ToLocal(key), info); 196 result = call_fun(v8::Utils::ToLocal(key), info);
204 } 197 }
205 RETURN_IF_SCHEDULED_EXCEPTION(isolate); 198 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
206 if (result.IsEmpty()) { 199 if (result.IsEmpty()) {
207 return isolate->heap()->undefined_value(); 200 return isolate->heap()->undefined_value();
208 } 201 }
209 return *v8::Utils::OpenHandle(*result); 202 return *v8::Utils::OpenHandle(*result);
210 } 203 }
211 204
212 // __defineGetter__ callback 205 // __defineGetter__ callback
213 if (structure->IsFixedArray()) { 206 if (structure->IsFixedArray()) {
214 Object* getter = FixedArray::cast(structure)->get(kGetterIndex); 207 Object* getter = FixedArray::cast(structure)->get(kGetterIndex);
215 if (getter->IsJSFunction()) { 208 if (getter->IsSpecFunction()) {
216 return Object::GetPropertyWithDefinedGetter(receiver, 209 // TODO(rossberg): nicer would be to cast to some JSCallable here...
217 JSFunction::cast(getter)); 210 return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter));
218 } 211 }
219 // Getter is not a function. 212 // Getter is not a function.
220 return isolate->heap()->undefined_value(); 213 return isolate->heap()->undefined_value();
221 } 214 }
222 215
223 UNREACHABLE(); 216 UNREACHABLE();
224 return NULL; 217 return NULL;
225 } 218 }
226 219
227 220
228 MaybeObject* Object::GetPropertyWithHandler(Object* receiver_raw, 221 MaybeObject* JSProxy::GetPropertyWithHandler(Object* receiver_raw,
229 String* name_raw, 222 String* name_raw) {
230 Object* handler_raw) { 223 Isolate* isolate = GetIsolate();
231 Isolate* isolate = name_raw->GetIsolate();
232 HandleScope scope(isolate); 224 HandleScope scope(isolate);
233 Handle<Object> receiver(receiver_raw); 225 Handle<Object> receiver(receiver_raw);
234 Handle<Object> name(name_raw); 226 Handle<Object> name(name_raw);
235 Handle<Object> handler(handler_raw);
236 227
237 // Extract trap function. 228 Handle<Object> args[] = { receiver, name };
238 Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("get"); 229 Handle<Object> result = CallTrap(
239 Handle<Object> trap(v8::internal::GetProperty(handler, trap_name)); 230 "get", isolate->derived_get_trap(), ARRAY_SIZE(args), args);
240 if (isolate->has_pending_exception()) return Failure::Exception(); 231 if (isolate->has_pending_exception()) return Failure::Exception();
241 if (trap->IsUndefined()) {
242 // Get the derived `get' property.
243 trap = isolate->derived_get_trap();
244 }
245
246 // Call trap function.
247 Object** args[] = { receiver.location(), name.location() };
248 bool has_exception;
249 Handle<Object> result =
250 Execution::Call(trap, handler, ARRAY_SIZE(args), args, &has_exception);
251 if (has_exception) return Failure::Exception();
252 232
253 return *result; 233 return *result;
254 } 234 }
255 235
256 236
237 MaybeObject* JSProxy::GetElementWithHandler(Object* receiver,
238 uint32_t index) {
239 String* name;
240 MaybeObject* maybe = GetHeap()->Uint32ToString(index);
241 if (!maybe->To<String>(&name)) return maybe;
242 return GetPropertyWithHandler(receiver, name);
243 }
244
245
246 MaybeObject* JSProxy::SetElementWithHandler(uint32_t index,
247 Object* value,
248 StrictModeFlag strict_mode) {
249 String* name;
250 MaybeObject* maybe = GetHeap()->Uint32ToString(index);
251 if (!maybe->To<String>(&name)) return maybe;
252 return SetPropertyWithHandler(name, value, NONE, strict_mode);
253 }
254
255
256 bool JSProxy::HasElementWithHandler(uint32_t index) {
257 String* name;
258 MaybeObject* maybe = GetHeap()->Uint32ToString(index);
259 if (!maybe->To<String>(&name)) return maybe;
260 return HasPropertyWithHandler(name);
261 }
262
263
257 MaybeObject* Object::GetPropertyWithDefinedGetter(Object* receiver, 264 MaybeObject* Object::GetPropertyWithDefinedGetter(Object* receiver,
258 JSFunction* getter) { 265 JSReceiver* getter) {
259 HandleScope scope; 266 HandleScope scope;
260 Handle<JSFunction> fun(JSFunction::cast(getter)); 267 Handle<JSReceiver> fun(getter);
261 Handle<Object> self(receiver); 268 Handle<Object> self(receiver);
262 #ifdef ENABLE_DEBUGGER_SUPPORT 269 #ifdef ENABLE_DEBUGGER_SUPPORT
263 Debug* debug = fun->GetHeap()->isolate()->debug(); 270 Debug* debug = fun->GetHeap()->isolate()->debug();
264 // Handle stepping into a getter if step into is active. 271 // Handle stepping into a getter if step into is active.
265 if (debug->StepInActive()) { 272 // TODO(rossberg): should this apply to getters that are function proxies?
266 debug->HandleStepIn(fun, Handle<Object>::null(), 0, false); 273 if (debug->StepInActive() && fun->IsJSFunction()) {
274 debug->HandleStepIn(
275 Handle<JSFunction>::cast(fun), Handle<Object>::null(), 0, false);
267 } 276 }
268 #endif 277 #endif
278
269 bool has_pending_exception; 279 bool has_pending_exception;
270 Handle<Object> result = 280 Handle<Object> result =
271 Execution::Call(fun, self, 0, NULL, &has_pending_exception); 281 Execution::Call(fun, self, 0, NULL, &has_pending_exception);
272 // Check for pending exception and return the result. 282 // Check for pending exception and return the result.
273 if (has_pending_exception) return Failure::Exception(); 283 if (has_pending_exception) return Failure::Exception();
274 return *result; 284 return *result;
275 } 285 }
276 286
277 287
278 // Only deal with CALLBACKS and INTERCEPTOR 288 // Only deal with CALLBACKS and INTERCEPTOR
279 MaybeObject* JSObject::GetPropertyWithFailedAccessCheck( 289 MaybeObject* JSObject::GetPropertyWithFailedAccessCheck(
280 Object* receiver, 290 Object* receiver,
281 LookupResult* result, 291 LookupResult* result,
282 String* name, 292 String* name,
283 PropertyAttributes* attributes) { 293 PropertyAttributes* attributes) {
284 if (result->IsProperty()) { 294 if (result->IsProperty()) {
285 switch (result->type()) { 295 switch (result->type()) {
286 case CALLBACKS: { 296 case CALLBACKS: {
287 // Only allow API accessors. 297 // Only allow API accessors.
288 Object* obj = result->GetCallbackObject(); 298 Object* obj = result->GetCallbackObject();
289 if (obj->IsAccessorInfo()) { 299 if (obj->IsAccessorInfo()) {
290 AccessorInfo* info = AccessorInfo::cast(obj); 300 AccessorInfo* info = AccessorInfo::cast(obj);
291 if (info->all_can_read()) { 301 if (info->all_can_read()) {
292 *attributes = result->GetAttributes(); 302 *attributes = result->GetAttributes();
293 return GetPropertyWithCallback(receiver, 303 return result->holder()->GetPropertyWithCallback(
294 result->GetCallbackObject(), 304 receiver, result->GetCallbackObject(), name);
295 name,
296 result->holder());
297 } 305 }
298 } 306 }
299 break; 307 break;
300 } 308 }
301 case NORMAL: 309 case NORMAL:
302 case FIELD: 310 case FIELD:
303 case CONSTANT_FUNCTION: { 311 case CONSTANT_FUNCTION: {
304 // Search ALL_CAN_READ accessors in prototype chain. 312 // Search ALL_CAN_READ accessors in prototype chain.
305 LookupResult r; 313 LookupResult r;
306 result->holder()->LookupRealNamedPropertyInPrototypes(name, &r); 314 result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
479 // from the DontDelete cell without checking if it contains 487 // from the DontDelete cell without checking if it contains
480 // the hole value. 488 // the hole value.
481 Object* new_map; 489 Object* new_map;
482 { MaybeObject* maybe_new_map = map()->CopyDropDescriptors(); 490 { MaybeObject* maybe_new_map = map()->CopyDropDescriptors();
483 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; 491 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
484 } 492 }
485 set_map(Map::cast(new_map)); 493 set_map(Map::cast(new_map));
486 } 494 }
487 JSGlobalPropertyCell* cell = 495 JSGlobalPropertyCell* cell =
488 JSGlobalPropertyCell::cast(dictionary->ValueAt(entry)); 496 JSGlobalPropertyCell::cast(dictionary->ValueAt(entry));
489 cell->set_value(cell->heap()->the_hole_value()); 497 cell->set_value(cell->GetHeap()->the_hole_value());
490 dictionary->DetailsAtPut(entry, details.AsDeleted()); 498 dictionary->DetailsAtPut(entry, details.AsDeleted());
491 } else { 499 } else {
492 Object* deleted = dictionary->DeleteProperty(entry, mode); 500 Object* deleted = dictionary->DeleteProperty(entry, mode);
493 if (deleted == GetHeap()->true_value()) { 501 if (deleted == GetHeap()->true_value()) {
494 FixedArray* new_properties = NULL; 502 FixedArray* new_properties = NULL;
495 MaybeObject* maybe_properties = dictionary->Shrink(name); 503 MaybeObject* maybe_properties = dictionary->Shrink(name);
496 if (!maybe_properties->To(&new_properties)) { 504 if (!maybe_properties->To(&new_properties)) {
497 return maybe_properties; 505 return maybe_properties;
498 } 506 }
499 set_properties(new_properties); 507 set_properties(new_properties);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
559 if (current == last) break; 567 if (current == last) break;
560 } 568 }
561 } 569 }
562 570
563 if (!result->IsProperty()) { 571 if (!result->IsProperty()) {
564 *attributes = ABSENT; 572 *attributes = ABSENT;
565 return heap->undefined_value(); 573 return heap->undefined_value();
566 } 574 }
567 *attributes = result->GetAttributes(); 575 *attributes = result->GetAttributes();
568 Object* value; 576 Object* value;
569 JSObject* holder = result->holder();
570 switch (result->type()) { 577 switch (result->type()) {
571 case NORMAL: 578 case NORMAL:
572 value = holder->GetNormalizedProperty(result); 579 value = result->holder()->GetNormalizedProperty(result);
573 ASSERT(!value->IsTheHole() || result->IsReadOnly()); 580 ASSERT(!value->IsTheHole() || result->IsReadOnly());
574 return value->IsTheHole() ? heap->undefined_value() : value; 581 return value->IsTheHole() ? heap->undefined_value() : value;
575 case FIELD: 582 case FIELD:
576 value = holder->FastPropertyAt(result->GetFieldIndex()); 583 value = result->holder()->FastPropertyAt(result->GetFieldIndex());
577 ASSERT(!value->IsTheHole() || result->IsReadOnly()); 584 ASSERT(!value->IsTheHole() || result->IsReadOnly());
578 return value->IsTheHole() ? heap->undefined_value() : value; 585 return value->IsTheHole() ? heap->undefined_value() : value;
579 case CONSTANT_FUNCTION: 586 case CONSTANT_FUNCTION:
580 return result->GetConstantFunction(); 587 return result->GetConstantFunction();
581 case CALLBACKS: 588 case CALLBACKS:
582 return GetPropertyWithCallback(receiver, 589 return result->holder()->GetPropertyWithCallback(
583 result->GetCallbackObject(), 590 receiver, result->GetCallbackObject(), name);
584 name, 591 case HANDLER:
585 holder); 592 return result->proxy()->GetPropertyWithHandler(receiver, name);
586 case HANDLER: {
587 JSProxy* proxy = JSProxy::cast(this);
588 return GetPropertyWithHandler(receiver, name, proxy->handler());
589 }
590 case INTERCEPTOR: { 593 case INTERCEPTOR: {
591 JSObject* recvr = JSObject::cast(receiver); 594 JSObject* recvr = JSObject::cast(receiver);
592 return holder->GetPropertyWithInterceptor(recvr, name, attributes); 595 return result->holder()->GetPropertyWithInterceptor(
596 recvr, name, attributes);
593 } 597 }
594 case MAP_TRANSITION: 598 case MAP_TRANSITION:
595 case ELEMENTS_TRANSITION: 599 case ELEMENTS_TRANSITION:
596 case CONSTANT_TRANSITION: 600 case CONSTANT_TRANSITION:
597 case NULL_DESCRIPTOR: 601 case NULL_DESCRIPTOR:
598 break; 602 break;
599 } 603 }
600 UNREACHABLE(); 604 UNREACHABLE();
601 return NULL; 605 return NULL;
602 } 606 }
603 607
604 608
605 MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) { 609 MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) {
606 Heap* heap = IsSmi() 610 Heap* heap = IsSmi()
607 ? Isolate::Current()->heap() 611 ? Isolate::Current()->heap()
608 : HeapObject::cast(this)->GetHeap(); 612 : HeapObject::cast(this)->GetHeap();
609 Object* holder = this; 613 Object* holder = this;
610 614
611 // Iterate up the prototype chain until an element is found or the null 615 // Iterate up the prototype chain until an element is found or the null
612 // prototype is encountered. 616 // prototype is encountered.
613 for (holder = this; 617 for (holder = this;
614 holder != heap->null_value(); 618 holder != heap->null_value();
615 holder = holder->GetPrototype()) { 619 holder = holder->GetPrototype()) {
616 if (holder->IsSmi()) { 620 if (!holder->IsJSObject()) {
617 Context* global_context = Isolate::Current()->context()->global_context(); 621 Isolate* isolate = heap->isolate();
618 holder = global_context->number_function()->instance_prototype(); 622 Context* global_context = isolate->context()->global_context();
619 } else { 623 if (holder->IsNumber()) {
620 HeapObject* heap_object = HeapObject::cast(holder); 624 holder = global_context->number_function()->instance_prototype();
621 if (!heap_object->IsJSObject()) { 625 } else if (holder->IsString()) {
622 Isolate* isolate = heap->isolate(); 626 holder = global_context->string_function()->instance_prototype();
623 Context* global_context = isolate->context()->global_context(); 627 } else if (holder->IsBoolean()) {
624 if (heap_object->IsString()) { 628 holder = global_context->boolean_function()->instance_prototype();
625 holder = global_context->string_function()->instance_prototype(); 629 } else if (holder->IsJSProxy()) {
626 } else if (heap_object->IsHeapNumber()) { 630 return JSProxy::cast(holder)->GetElementWithHandler(receiver, index);
627 holder = global_context->number_function()->instance_prototype(); 631 } else {
628 } else if (heap_object->IsBoolean()) { 632 // Undefined and null have no indexed properties.
629 holder = global_context->boolean_function()->instance_prototype(); 633 ASSERT(holder->IsUndefined() || holder->IsNull());
630 } else if (heap_object->IsJSProxy()) { 634 return heap->undefined_value();
631 // TODO(rossberg): do something
632 return heap->undefined_value(); // For now...
633 } else {
634 // Undefined and null have no indexed properties.
635 ASSERT(heap_object->IsUndefined() || heap_object->IsNull());
636 return heap->undefined_value();
637 }
638 } 635 }
639 } 636 }
640 637
641 // Inline the case for JSObjects. Doing so significantly improves the 638 // Inline the case for JSObjects. Doing so significantly improves the
642 // performance of fetching elements where checking the prototype chain is 639 // performance of fetching elements where checking the prototype chain is
643 // necessary. 640 // necessary.
644 JSObject* js_object = JSObject::cast(holder); 641 JSObject* js_object = JSObject::cast(holder);
645 642
646 // Check access rights if needed. 643 // Check access rights if needed.
647 if (js_object->IsAccessCheckNeeded()) { 644 if (js_object->IsAccessCheckNeeded()) {
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
870 self->Hash(); // Force regeneration of the hash value. 867 self->Hash(); // Force regeneration of the hash value.
871 // Now morph this external string into a external symbol. 868 // Now morph this external string into a external symbol.
872 this->set_map(is_ascii ? 869 this->set_map(is_ascii ?
873 heap->external_symbol_with_ascii_data_map() : 870 heap->external_symbol_with_ascii_data_map() :
874 heap->external_symbol_map()); 871 heap->external_symbol_map());
875 } 872 }
876 873
877 // Fill the remainder of the string with dead wood. 874 // Fill the remainder of the string with dead wood.
878 int new_size = this->Size(); // Byte size of the external String object. 875 int new_size = this->Size(); // Byte size of the external String object.
879 heap->CreateFillerObjectAt(this->address() + new_size, size - new_size); 876 heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
877 if (Marking::IsBlack(Marking::MarkBitFrom(this))) {
878 MemoryChunk::IncrementLiveBytes(this->address(), new_size - size);
879 }
880 return true; 880 return true;
881 } 881 }
882 882
883 883
884 bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) { 884 bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) {
885 #ifdef DEBUG 885 #ifdef DEBUG
886 if (FLAG_enable_slow_asserts) { 886 if (FLAG_enable_slow_asserts) {
887 // Assert that the resource and the string are equivalent. 887 // Assert that the resource and the string are equivalent.
888 ASSERT(static_cast<size_t>(this->length()) == resource->length()); 888 ASSERT(static_cast<size_t>(this->length()) == resource->length());
889 ScopedVector<char> smart_chars(this->length()); 889 ScopedVector<char> smart_chars(this->length());
(...skipping 26 matching lines...) Expand all
916 // was a symbol to start with. 916 // was a symbol to start with.
917 if (is_symbol) { 917 if (is_symbol) {
918 self->Hash(); // Force regeneration of the hash value. 918 self->Hash(); // Force regeneration of the hash value.
919 // Now morph this external string into a external symbol. 919 // Now morph this external string into a external symbol.
920 this->set_map(heap->external_ascii_symbol_map()); 920 this->set_map(heap->external_ascii_symbol_map());
921 } 921 }
922 922
923 // Fill the remainder of the string with dead wood. 923 // Fill the remainder of the string with dead wood.
924 int new_size = this->Size(); // Byte size of the external String object. 924 int new_size = this->Size(); // Byte size of the external String object.
925 heap->CreateFillerObjectAt(this->address() + new_size, size - new_size); 925 heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
926 if (Marking::IsBlack(Marking::MarkBitFrom(this))) {
927 MemoryChunk::IncrementLiveBytes(this->address(), new_size - size);
928 }
929
926 return true; 930 return true;
927 } 931 }
928 932
929 933
930 void String::StringShortPrint(StringStream* accumulator) { 934 void String::StringShortPrint(StringStream* accumulator) {
931 int len = length(); 935 int len = length();
932 if (len > kMaxShortPrintLength) { 936 if (len > kMaxShortPrintLength) {
933 accumulator->Add("<Very long string[%u]>", len); 937 accumulator->Add("<Very long string[%u]>", len);
934 return; 938 return;
935 } 939 }
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
991 995
992 996
993 void JSObject::JSObjectShortPrint(StringStream* accumulator) { 997 void JSObject::JSObjectShortPrint(StringStream* accumulator) {
994 switch (map()->instance_type()) { 998 switch (map()->instance_type()) {
995 case JS_ARRAY_TYPE: { 999 case JS_ARRAY_TYPE: {
996 double length = JSArray::cast(this)->length()->Number(); 1000 double length = JSArray::cast(this)->length()->Number();
997 accumulator->Add("<JS array[%u]>", static_cast<uint32_t>(length)); 1001 accumulator->Add("<JS array[%u]>", static_cast<uint32_t>(length));
998 break; 1002 break;
999 } 1003 }
1000 case JS_WEAK_MAP_TYPE: { 1004 case JS_WEAK_MAP_TYPE: {
1001 int elements = JSWeakMap::cast(this)->table()->NumberOfElements(); 1005 accumulator->Add("<JS WeakMap>");
1002 accumulator->Add("<JS WeakMap[%d]>", elements);
1003 break; 1006 break;
1004 } 1007 }
1005 case JS_REGEXP_TYPE: { 1008 case JS_REGEXP_TYPE: {
1006 accumulator->Add("<JS RegExp>"); 1009 accumulator->Add("<JS RegExp>");
1007 break; 1010 break;
1008 } 1011 }
1009 case JS_FUNCTION_TYPE: { 1012 case JS_FUNCTION_TYPE: {
1010 Object* fun_name = JSFunction::cast(this)->shared()->name(); 1013 Object* fun_name = JSFunction::cast(this)->shared()->name();
1011 bool printed = false; 1014 bool printed = false;
1012 if (fun_name->IsString()) { 1015 if (fun_name->IsString()) {
1013 String* str = String::cast(fun_name); 1016 String* str = String::cast(fun_name);
1014 if (str->length() > 0) { 1017 if (str->length() > 0) {
1015 accumulator->Add("<JS Function "); 1018 accumulator->Add("<JS Function ");
1016 accumulator->Put(str); 1019 accumulator->Put(str);
1017 accumulator->Put('>'); 1020 accumulator->Put('>');
1018 printed = true; 1021 printed = true;
1019 } 1022 }
1020 } 1023 }
1021 if (!printed) { 1024 if (!printed) {
1022 accumulator->Add("<JS Function>"); 1025 accumulator->Add("<JS Function>");
1023 } 1026 }
1024 break; 1027 break;
1025 } 1028 }
1026 // All other JSObjects are rather similar to each other (JSObject, 1029 // All other JSObjects are rather similar to each other (JSObject,
1027 // JSGlobalProxy, JSGlobalObject, JSUndetectableObject, JSValue). 1030 // JSGlobalProxy, JSGlobalObject, JSUndetectableObject, JSValue).
1028 default: { 1031 default: {
1029 Map* map_of_this = map(); 1032 Map* map_of_this = map();
1030 Heap* heap = map_of_this->heap(); 1033 Heap* heap = GetHeap();
1031 Object* constructor = map_of_this->constructor(); 1034 Object* constructor = map_of_this->constructor();
1032 bool printed = false; 1035 bool printed = false;
1033 if (constructor->IsHeapObject() && 1036 if (constructor->IsHeapObject() &&
1034 !heap->Contains(HeapObject::cast(constructor))) { 1037 !heap->Contains(HeapObject::cast(constructor))) {
1035 accumulator->Add("!!!INVALID CONSTRUCTOR!!!"); 1038 accumulator->Add("!!!INVALID CONSTRUCTOR!!!");
1036 } else { 1039 } else {
1037 bool global_object = IsJSGlobalProxy(); 1040 bool global_object = IsJSGlobalProxy();
1038 if (constructor->IsJSFunction()) { 1041 if (constructor->IsJSFunction()) {
1039 if (!heap->Contains(JSFunction::cast(constructor)->shared())) { 1042 if (!heap->Contains(JSFunction::cast(constructor)->shared())) {
1040 accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!"); 1043 accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!");
1041 } else { 1044 } else {
1042 Object* constructor_name = 1045 Object* constructor_name =
1043 JSFunction::cast(constructor)->shared()->name(); 1046 JSFunction::cast(constructor)->shared()->name();
1044 if (constructor_name->IsString()) { 1047 if (constructor_name->IsString()) {
1045 String* str = String::cast(constructor_name); 1048 String* str = String::cast(constructor_name);
1046 if (str->length() > 0) { 1049 if (str->length() > 0) {
1047 bool vowel = AnWord(str); 1050 bool vowel = AnWord(str);
1048 accumulator->Add("<%sa%s ", 1051 accumulator->Add("<%sa%s ",
1049 global_object ? "Global Object: " : "", 1052 global_object ? "Global Object: " : "",
1050 vowel ? "n" : ""); 1053 vowel ? "n" : "");
1051 accumulator->Put(str); 1054 accumulator->Put(str);
1052 accumulator->Put('>');
1053 printed = true; 1055 printed = true;
1054 } 1056 }
1055 } 1057 }
1056 } 1058 }
1057 } 1059 }
1058 if (!printed) { 1060 if (!printed) {
1059 accumulator->Add("<JS %sObject", global_object ? "Global " : ""); 1061 accumulator->Add("<JS %sObject", global_object ? "Global " : "");
1060 } 1062 }
1061 } 1063 }
1062 if (IsJSValue()) { 1064 if (IsJSValue()) {
1063 accumulator->Add(" value = "); 1065 accumulator->Add(" value = ");
1064 JSValue::cast(this)->value()->ShortPrint(accumulator); 1066 JSValue::cast(this)->value()->ShortPrint(accumulator);
1065 } 1067 }
1066 accumulator->Put('>'); 1068 accumulator->Put('>');
1067 break; 1069 break;
1068 } 1070 }
1069 } 1071 }
1070 } 1072 }
1071 1073
1072 1074
1073 void HeapObject::HeapObjectShortPrint(StringStream* accumulator) { 1075 void HeapObject::HeapObjectShortPrint(StringStream* accumulator) {
1074 // if (!HEAP->InNewSpace(this)) PrintF("*", this);
1075 Heap* heap = GetHeap(); 1076 Heap* heap = GetHeap();
1076 if (!heap->Contains(this)) { 1077 if (!heap->Contains(this)) {
1077 accumulator->Add("!!!INVALID POINTER!!!"); 1078 accumulator->Add("!!!INVALID POINTER!!!");
1078 return; 1079 return;
1079 } 1080 }
1080 if (!heap->Contains(map())) { 1081 if (!heap->Contains(map())) {
1081 accumulator->Add("!!!INVALID MAP!!!"); 1082 accumulator->Add("!!!INVALID MAP!!!");
1082 return; 1083 return;
1083 } 1084 }
1084 1085
(...skipping 10 matching lines...) Expand all
1095 switch (map()->instance_type()) { 1096 switch (map()->instance_type()) {
1096 case MAP_TYPE: 1097 case MAP_TYPE:
1097 accumulator->Add("<Map>"); 1098 accumulator->Add("<Map>");
1098 break; 1099 break;
1099 case FIXED_ARRAY_TYPE: 1100 case FIXED_ARRAY_TYPE:
1100 accumulator->Add("<FixedArray[%u]>", FixedArray::cast(this)->length()); 1101 accumulator->Add("<FixedArray[%u]>", FixedArray::cast(this)->length());
1101 break; 1102 break;
1102 case BYTE_ARRAY_TYPE: 1103 case BYTE_ARRAY_TYPE:
1103 accumulator->Add("<ByteArray[%u]>", ByteArray::cast(this)->length()); 1104 accumulator->Add("<ByteArray[%u]>", ByteArray::cast(this)->length());
1104 break; 1105 break;
1106 case FREE_SPACE_TYPE:
1107 accumulator->Add("<FreeSpace[%u]>", FreeSpace::cast(this)->Size());
1108 break;
1105 case EXTERNAL_PIXEL_ARRAY_TYPE: 1109 case EXTERNAL_PIXEL_ARRAY_TYPE:
1106 accumulator->Add("<ExternalPixelArray[%u]>", 1110 accumulator->Add("<ExternalPixelArray[%u]>",
1107 ExternalPixelArray::cast(this)->length()); 1111 ExternalPixelArray::cast(this)->length());
1108 break; 1112 break;
1109 case EXTERNAL_BYTE_ARRAY_TYPE: 1113 case EXTERNAL_BYTE_ARRAY_TYPE:
1110 accumulator->Add("<ExternalByteArray[%u]>", 1114 accumulator->Add("<ExternalByteArray[%u]>",
1111 ExternalByteArray::cast(this)->length()); 1115 ExternalByteArray::cast(this)->length());
1112 break; 1116 break;
1113 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE: 1117 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
1114 accumulator->Add("<ExternalUnsignedByteArray[%u]>", 1118 accumulator->Add("<ExternalUnsignedByteArray[%u]>",
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
1270 break; 1274 break;
1271 case CODE_TYPE: 1275 case CODE_TYPE:
1272 reinterpret_cast<Code*>(this)->CodeIterateBody(v); 1276 reinterpret_cast<Code*>(this)->CodeIterateBody(v);
1273 break; 1277 break;
1274 case JS_GLOBAL_PROPERTY_CELL_TYPE: 1278 case JS_GLOBAL_PROPERTY_CELL_TYPE:
1275 JSGlobalPropertyCell::BodyDescriptor::IterateBody(this, v); 1279 JSGlobalPropertyCell::BodyDescriptor::IterateBody(this, v);
1276 break; 1280 break;
1277 case HEAP_NUMBER_TYPE: 1281 case HEAP_NUMBER_TYPE:
1278 case FILLER_TYPE: 1282 case FILLER_TYPE:
1279 case BYTE_ARRAY_TYPE: 1283 case BYTE_ARRAY_TYPE:
1284 case FREE_SPACE_TYPE:
1280 case EXTERNAL_PIXEL_ARRAY_TYPE: 1285 case EXTERNAL_PIXEL_ARRAY_TYPE:
1281 case EXTERNAL_BYTE_ARRAY_TYPE: 1286 case EXTERNAL_BYTE_ARRAY_TYPE:
1282 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE: 1287 case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
1283 case EXTERNAL_SHORT_ARRAY_TYPE: 1288 case EXTERNAL_SHORT_ARRAY_TYPE:
1284 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE: 1289 case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
1285 case EXTERNAL_INT_ARRAY_TYPE: 1290 case EXTERNAL_INT_ARRAY_TYPE:
1286 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE: 1291 case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
1287 case EXTERNAL_FLOAT_ARRAY_TYPE: 1292 case EXTERNAL_FLOAT_ARRAY_TYPE:
1288 case EXTERNAL_DOUBLE_ARRAY_TYPE: 1293 case EXTERNAL_DOUBLE_ARRAY_TYPE:
1289 break; 1294 break;
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
1526 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; 1531 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
1527 } 1532 }
1528 1533
1529 DescriptorArray* descriptors = DescriptorArray::cast(new_descriptors); 1534 DescriptorArray* descriptors = DescriptorArray::cast(new_descriptors);
1530 Map::cast(new_map)->set_instance_descriptors(descriptors); 1535 Map::cast(new_map)->set_instance_descriptors(descriptors);
1531 Map* old_map = map(); 1536 Map* old_map = map();
1532 set_map(Map::cast(new_map)); 1537 set_map(Map::cast(new_map));
1533 1538
1534 // If the old map is the global object map (from new Object()), 1539 // If the old map is the global object map (from new Object()),
1535 // then transitions are not added to it, so we are done. 1540 // then transitions are not added to it, so we are done.
1536 Heap* heap = old_map->heap(); 1541 Heap* heap = GetHeap();
1537 if (old_map == heap->isolate()->context()->global_context()-> 1542 if (old_map == heap->isolate()->context()->global_context()->
1538 object_function()->map()) { 1543 object_function()->map()) {
1539 return function; 1544 return function;
1540 } 1545 }
1541 1546
1542 // Do not add CONSTANT_TRANSITIONS to global objects 1547 // Do not add CONSTANT_TRANSITIONS to global objects
1543 if (IsGlobalObject()) { 1548 if (IsGlobalObject()) {
1544 return function; 1549 return function;
1545 } 1550 }
1546 1551
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1602 return value; 1607 return value;
1603 } 1608 }
1604 1609
1605 1610
1606 MaybeObject* JSObject::AddProperty(String* name, 1611 MaybeObject* JSObject::AddProperty(String* name,
1607 Object* value, 1612 Object* value,
1608 PropertyAttributes attributes, 1613 PropertyAttributes attributes,
1609 StrictModeFlag strict_mode) { 1614 StrictModeFlag strict_mode) {
1610 ASSERT(!IsJSGlobalProxy()); 1615 ASSERT(!IsJSGlobalProxy());
1611 Map* map_of_this = map(); 1616 Map* map_of_this = map();
1612 Heap* heap = map_of_this->heap(); 1617 Heap* heap = GetHeap();
1613 if (!map_of_this->is_extensible()) { 1618 if (!map_of_this->is_extensible()) {
1614 if (strict_mode == kNonStrictMode) { 1619 if (strict_mode == kNonStrictMode) {
1615 return heap->undefined_value(); 1620 return heap->undefined_value();
1616 } else { 1621 } else {
1617 Handle<Object> args[1] = {Handle<String>(name)}; 1622 Handle<Object> args[1] = {Handle<String>(name)};
1618 return heap->isolate()->Throw( 1623 return heap->isolate()->Throw(
1619 *FACTORY->NewTypeError("object_not_extensible", 1624 *FACTORY->NewTypeError("object_not_extensible",
1620 HandleVector(args, 1))); 1625 HandleVector(args, 1)));
1621 } 1626 }
1622 } 1627 }
(...skipping 28 matching lines...) Expand all
1651 PropertyAttributes attributes, 1656 PropertyAttributes attributes,
1652 StrictModeFlag strict_mode) { 1657 StrictModeFlag strict_mode) {
1653 // Check local property, ignore interceptor. 1658 // Check local property, ignore interceptor.
1654 LookupResult result; 1659 LookupResult result;
1655 LocalLookupRealNamedProperty(name, &result); 1660 LocalLookupRealNamedProperty(name, &result);
1656 if (result.IsFound()) { 1661 if (result.IsFound()) {
1657 // An existing property, a map transition or a null descriptor was 1662 // An existing property, a map transition or a null descriptor was
1658 // found. Use set property to handle all these cases. 1663 // found. Use set property to handle all these cases.
1659 return SetProperty(&result, name, value, attributes, strict_mode); 1664 return SetProperty(&result, name, value, attributes, strict_mode);
1660 } 1665 }
1666 bool found = false;
1667 MaybeObject* result_object;
1668 result_object = SetPropertyWithCallbackSetterInPrototypes(name,
1669 value,
1670 attributes,
1671 &found,
1672 strict_mode);
1673 if (found) return result_object;
1661 // Add a new real property. 1674 // Add a new real property.
1662 return AddProperty(name, value, attributes, strict_mode); 1675 return AddProperty(name, value, attributes, strict_mode);
1663 } 1676 }
1664 1677
1665 1678
1666 MaybeObject* JSObject::ReplaceSlowProperty(String* name, 1679 MaybeObject* JSObject::ReplaceSlowProperty(String* name,
1667 Object* value, 1680 Object* value,
1668 PropertyAttributes attributes) { 1681 PropertyAttributes attributes) {
1669 StringDictionary* dictionary = property_dictionary(); 1682 StringDictionary* dictionary = property_dictionary();
1670 int old_index = dictionary->FindEntry(name); 1683 int old_index = dictionary->FindEntry(name);
(...skipping 18 matching lines...) Expand all
1689 { MaybeObject* maybe_result = 1702 { MaybeObject* maybe_result =
1690 ConvertDescriptorToField(name, new_value, attributes); 1703 ConvertDescriptorToField(name, new_value, attributes);
1691 if (!maybe_result->ToObject(&result)) return maybe_result; 1704 if (!maybe_result->ToObject(&result)) return maybe_result;
1692 } 1705 }
1693 // If we get to this point we have succeeded - do not return failure 1706 // If we get to this point we have succeeded - do not return failure
1694 // after this point. Later stuff is optional. 1707 // after this point. Later stuff is optional.
1695 if (!HasFastProperties()) { 1708 if (!HasFastProperties()) {
1696 return result; 1709 return result;
1697 } 1710 }
1698 // Do not add transitions to the map of "new Object()". 1711 // Do not add transitions to the map of "new Object()".
1699 if (map() == old_map->heap()->isolate()->context()->global_context()-> 1712 if (map() == GetIsolate()->context()->global_context()->
1700 object_function()->map()) { 1713 object_function()->map()) {
1701 return result; 1714 return result;
1702 } 1715 }
1703 1716
1704 MapTransitionDescriptor transition(name, 1717 MapTransitionDescriptor transition(name,
1705 map(), 1718 map(),
1706 attributes); 1719 attributes);
1707 Object* new_descriptors; 1720 Object* new_descriptors;
1708 { MaybeObject* maybe_new_descriptors = old_map->instance_descriptors()-> 1721 { MaybeObject* maybe_new_descriptors = old_map->instance_descriptors()->
1709 CopyInsert(&transition, KEEP_TRANSITIONS); 1722 CopyInsert(&transition, KEEP_TRANSITIONS);
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
1873 call_fun(v8::Utils::ToLocal(key), 1886 call_fun(v8::Utils::ToLocal(key),
1874 v8::Utils::ToLocal(value_handle), 1887 v8::Utils::ToLocal(value_handle),
1875 info); 1888 info);
1876 } 1889 }
1877 RETURN_IF_SCHEDULED_EXCEPTION(isolate); 1890 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1878 return *value_handle; 1891 return *value_handle;
1879 } 1892 }
1880 1893
1881 if (structure->IsFixedArray()) { 1894 if (structure->IsFixedArray()) {
1882 Object* setter = FixedArray::cast(structure)->get(kSetterIndex); 1895 Object* setter = FixedArray::cast(structure)->get(kSetterIndex);
1883 if (setter->IsJSFunction()) { 1896 if (setter->IsSpecFunction()) {
1884 return SetPropertyWithDefinedSetter(JSFunction::cast(setter), value); 1897 // TODO(rossberg): nicer would be to cast to some JSCallable here...
1898 return SetPropertyWithDefinedSetter(JSReceiver::cast(setter), value);
1885 } else { 1899 } else {
1886 if (strict_mode == kNonStrictMode) { 1900 if (strict_mode == kNonStrictMode) {
1887 return value; 1901 return value;
1888 } 1902 }
1889 Handle<String> key(name); 1903 Handle<String> key(name);
1890 Handle<Object> holder_handle(holder, isolate); 1904 Handle<Object> holder_handle(holder, isolate);
1891 Handle<Object> args[2] = { key, holder_handle }; 1905 Handle<Object> args[2] = { key, holder_handle };
1892 return isolate->Throw( 1906 return isolate->Throw(
1893 *isolate->factory()->NewTypeError("no_setter_in_callback", 1907 *isolate->factory()->NewTypeError("no_setter_in_callback",
1894 HandleVector(args, 2))); 1908 HandleVector(args, 2)));
1895 } 1909 }
1896 } 1910 }
1897 1911
1898 UNREACHABLE(); 1912 UNREACHABLE();
1899 return NULL; 1913 return NULL;
1900 } 1914 }
1901 1915
1902 1916
1903 MaybeObject* JSObject::SetPropertyWithDefinedSetter(JSFunction* setter, 1917 MaybeObject* JSReceiver::SetPropertyWithDefinedSetter(JSReceiver* setter,
1904 Object* value) { 1918 Object* value) {
1905 Isolate* isolate = GetIsolate(); 1919 Isolate* isolate = GetIsolate();
1906 Handle<Object> value_handle(value, isolate); 1920 Handle<Object> value_handle(value, isolate);
1907 Handle<JSFunction> fun(JSFunction::cast(setter), isolate); 1921 Handle<JSReceiver> fun(setter, isolate);
1908 Handle<JSObject> self(this, isolate); 1922 Handle<JSReceiver> self(this, isolate);
1909 #ifdef ENABLE_DEBUGGER_SUPPORT 1923 #ifdef ENABLE_DEBUGGER_SUPPORT
1910 Debug* debug = isolate->debug(); 1924 Debug* debug = isolate->debug();
1911 // Handle stepping into a setter if step into is active. 1925 // Handle stepping into a setter if step into is active.
1912 if (debug->StepInActive()) { 1926 // TODO(rossberg): should this apply to getters that are function proxies?
1913 debug->HandleStepIn(fun, Handle<Object>::null(), 0, false); 1927 if (debug->StepInActive() && fun->IsJSFunction()) {
1928 debug->HandleStepIn(
1929 Handle<JSFunction>::cast(fun), Handle<Object>::null(), 0, false);
1914 } 1930 }
1915 #endif 1931 #endif
1916 bool has_pending_exception; 1932 bool has_pending_exception;
1917 Object** argv[] = { value_handle.location() }; 1933 Object** argv[] = { value_handle.location() };
1918 Execution::Call(fun, self, 1, argv, &has_pending_exception); 1934 Execution::Call(fun, self, 1, argv, &has_pending_exception);
1919 // Check for pending exception and return the result. 1935 // Check for pending exception and return the result.
1920 if (has_pending_exception) return Failure::Exception(); 1936 if (has_pending_exception) return Failure::Exception();
1921 return *value_handle; 1937 return *value_handle;
1922 } 1938 }
1923 1939
1924 1940
1925 void JSObject::LookupCallbackSetterInPrototypes(String* name, 1941 void JSObject::LookupCallbackSetterInPrototypes(String* name,
1926 LookupResult* result) { 1942 LookupResult* result) {
1927 Heap* heap = GetHeap(); 1943 Heap* heap = GetHeap();
1928 for (Object* pt = GetPrototype(); 1944 for (Object* pt = GetPrototype();
1929 pt != heap->null_value(); 1945 pt != heap->null_value();
1930 pt = pt->GetPrototype()) { 1946 pt = pt->GetPrototype()) {
1947 if (pt->IsJSProxy()) {
1948 return result->HandlerResult(JSProxy::cast(pt));
1949 }
1931 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result); 1950 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
1932 if (result->IsProperty()) { 1951 if (result->IsProperty()) {
1933 if (result->type() == CALLBACKS && !result->IsReadOnly()) return; 1952 if (result->type() == CALLBACKS && !result->IsReadOnly()) return;
1934 // Found non-callback or read-only callback, stop looking. 1953 // Found non-callback or read-only callback, stop looking.
1935 break; 1954 break;
1936 } 1955 }
1937 } 1956 }
1938 result->NotFound(); 1957 result->NotFound();
1939 } 1958 }
1940 1959
1941 1960
1942 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes( 1961 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(
1943 uint32_t index, 1962 uint32_t index,
1944 Object* value, 1963 Object* value,
1945 bool* found, 1964 bool* found,
1946 StrictModeFlag strict_mode) { 1965 StrictModeFlag strict_mode) {
1947 Heap* heap = GetHeap(); 1966 Heap* heap = GetHeap();
1948 for (Object* pt = GetPrototype(); 1967 for (Object* pt = GetPrototype();
1949 pt != heap->null_value(); 1968 pt != heap->null_value();
1950 pt = pt->GetPrototype()) { 1969 pt = pt->GetPrototype()) {
1970 if (pt->IsJSProxy()) {
1971 String* name;
1972 MaybeObject* maybe = GetHeap()->Uint32ToString(index);
1973 if (!maybe->To<String>(&name)) {
1974 *found = true; // Force abort
1975 return maybe;
1976 }
1977 return JSProxy::cast(pt)->SetPropertyWithHandlerIfDefiningSetter(
1978 name, value, NONE, strict_mode, found);
1979 }
1951 if (!JSObject::cast(pt)->HasDictionaryElements()) { 1980 if (!JSObject::cast(pt)->HasDictionaryElements()) {
1952 continue; 1981 continue;
1953 } 1982 }
1954 NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary(); 1983 NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary();
1955 int entry = dictionary->FindEntry(index); 1984 int entry = dictionary->FindEntry(index);
1956 if (entry != NumberDictionary::kNotFound) { 1985 if (entry != NumberDictionary::kNotFound) {
1957 PropertyDetails details = dictionary->DetailsAt(entry); 1986 PropertyDetails details = dictionary->DetailsAt(entry);
1958 if (details.type() == CALLBACKS) { 1987 if (details.type() == CALLBACKS) {
1959 *found = true; 1988 *found = true;
1960 return SetElementWithCallback(dictionary->ValueAt(entry), 1989 return SetElementWithCallback(dictionary->ValueAt(entry),
1961 index, 1990 index,
1962 value, 1991 value,
1963 JSObject::cast(pt), 1992 JSObject::cast(pt),
1964 strict_mode); 1993 strict_mode);
1965 } 1994 }
1966 } 1995 }
1967 } 1996 }
1968 *found = false; 1997 *found = false;
1969 return heap->the_hole_value(); 1998 return heap->the_hole_value();
1970 } 1999 }
1971 2000
2001 MaybeObject* JSObject::SetPropertyWithCallbackSetterInPrototypes(
2002 String* name,
2003 Object* value,
2004 PropertyAttributes attributes,
2005 bool* found,
2006 StrictModeFlag strict_mode) {
2007 LookupResult result;
2008 LookupCallbackSetterInPrototypes(name, &result);
2009 Heap* heap = GetHeap();
2010 if (result.IsFound()) {
2011 *found = true;
2012 if (result.type() == CALLBACKS) {
2013 return SetPropertyWithCallback(result.GetCallbackObject(),
2014 name,
2015 value,
2016 result.holder(),
2017 strict_mode);
2018 } else if (result.type() == HANDLER) {
2019 // We could not find a local property so let's check whether there is an
2020 // accessor that wants to handle the property.
2021 LookupResult accessor_result;
2022 LookupCallbackSetterInPrototypes(name, &accessor_result);
2023 if (accessor_result.IsFound()) {
2024 if (accessor_result.type() == CALLBACKS) {
2025 return SetPropertyWithCallback(accessor_result.GetCallbackObject(),
2026 name,
2027 value,
2028 accessor_result.holder(),
2029 strict_mode);
2030 } else if (accessor_result.type() == HANDLER) {
2031 // There is a proxy in the prototype chain. Invoke its
2032 // getOwnPropertyDescriptor trap.
2033 bool found = false;
2034 // SetPropertyWithHandlerIfDefiningSetter can cause GC,
2035 // make sure to use the handlified references after calling
2036 // the function.
2037 Handle<JSObject> self(this);
2038 Handle<String> hname(name);
2039 Handle<Object> hvalue(value);
2040 MaybeObject* result =
2041 accessor_result.proxy()->SetPropertyWithHandlerIfDefiningSetter(
2042 name, value, attributes, strict_mode, &found);
2043 if (found) return result;
2044 // The proxy does not define the property as an accessor.
2045 // Consequently, it has no effect on setting the receiver.
2046 return self->AddProperty(*hname, *hvalue, attributes, strict_mode);
2047 }
2048 }
2049 }
2050 }
2051 *found = false;
2052 return heap->the_hole_value();
2053 }
2054
1972 2055
1973 void JSObject::LookupInDescriptor(String* name, LookupResult* result) { 2056 void JSObject::LookupInDescriptor(String* name, LookupResult* result) {
1974 DescriptorArray* descriptors = map()->instance_descriptors(); 2057 DescriptorArray* descriptors = map()->instance_descriptors();
1975 int number = descriptors->SearchWithCache(name); 2058 int number = descriptors->SearchWithCache(name);
1976 if (number != DescriptorArray::kNotFound) { 2059 if (number != DescriptorArray::kNotFound) {
1977 result->DescriptorResult(this, descriptors->GetDetails(number), number); 2060 result->DescriptorResult(this, descriptors->GetDetails(number), number);
1978 } else { 2061 } else {
1979 result->NotFound(); 2062 result->NotFound();
1980 } 2063 }
1981 } 2064 }
1982 2065
1983 2066
1984 void Map::LookupInDescriptors(JSObject* holder, 2067 void Map::LookupInDescriptors(JSObject* holder,
1985 String* name, 2068 String* name,
1986 LookupResult* result) { 2069 LookupResult* result) {
1987 DescriptorArray* descriptors = instance_descriptors(); 2070 DescriptorArray* descriptors = instance_descriptors();
1988 DescriptorLookupCache* cache = heap()->isolate()->descriptor_lookup_cache(); 2071 DescriptorLookupCache* cache =
2072 GetHeap()->isolate()->descriptor_lookup_cache();
1989 int number = cache->Lookup(descriptors, name); 2073 int number = cache->Lookup(descriptors, name);
1990 if (number == DescriptorLookupCache::kAbsent) { 2074 if (number == DescriptorLookupCache::kAbsent) {
1991 number = descriptors->Search(name); 2075 number = descriptors->Search(name);
1992 cache->Update(descriptors, name, number); 2076 cache->Update(descriptors, name, number);
1993 } 2077 }
1994 if (number != DescriptorArray::kNotFound) { 2078 if (number != DescriptorArray::kNotFound) {
1995 result->DescriptorResult(holder, descriptors->GetDetails(number), number); 2079 result->DescriptorResult(holder, descriptors->GetDetails(number), number);
1996 } else { 2080 } else {
1997 result->NotFound(); 2081 result->NotFound();
1998 } 2082 }
1999 } 2083 }
2000 2084
2001 2085
2002 MaybeObject* Map::GetElementsTransitionMap(ElementsKind elements_kind, 2086 static Map* GetElementsTransitionMapFromDescriptor(Object* descriptor_contents,
2003 bool safe_to_add_transition) { 2087 ElementsKind elements_kind) {
2004 Heap* current_heap = heap(); 2088 if (descriptor_contents->IsMap()) {
2005 DescriptorArray* descriptors = instance_descriptors(); 2089 Map* map = Map::cast(descriptor_contents);
2090 if (map->elements_kind() == elements_kind) {
2091 return map;
2092 }
2093 return NULL;
2094 }
2095
2096 FixedArray* map_array = FixedArray::cast(descriptor_contents);
2097 for (int i = 0; i < map_array->length(); ++i) {
2098 Object* current = map_array->get(i);
2099 // Skip undefined slots, they are sentinels for reclaimed maps.
2100 if (!current->IsUndefined()) {
2101 Map* current_map = Map::cast(map_array->get(i));
2102 if (current_map->elements_kind() == elements_kind) {
2103 return current_map;
2104 }
2105 }
2106 }
2107
2108 return NULL;
2109 }
2110
2111
2112 static MaybeObject* AddElementsTransitionMapToDescriptor(
2113 Object* descriptor_contents,
2114 Map* new_map) {
2115 // Nothing was in the descriptor for an ELEMENTS_TRANSITION,
2116 // simply add the map.
2117 if (descriptor_contents == NULL) {
2118 return new_map;
2119 }
2120
2121 // There was already a map in the descriptor, create a 2-element FixedArray
2122 // to contain the existing map plus the new one.
2123 FixedArray* new_array;
2124 Heap* heap = new_map->GetHeap();
2125 if (descriptor_contents->IsMap()) {
2126 // Must tenure, DescriptorArray expects no new-space objects.
2127 MaybeObject* maybe_new_array = heap->AllocateFixedArray(2, TENURED);
2128 if (!maybe_new_array->To<FixedArray>(&new_array)) {
2129 return maybe_new_array;
2130 }
2131 new_array->set(0, descriptor_contents);
2132 new_array->set(1, new_map);
2133 return new_array;
2134 }
2135
2136 // The descriptor already contained a list of maps for different ElementKinds
2137 // of ELEMENTS_TRANSITION, first check the existing array for an undefined
2138 // slot, and if that's not available, create a FixedArray to hold the existing
2139 // maps plus the new one and fill it in.
2140 FixedArray* array = FixedArray::cast(descriptor_contents);
2141 for (int i = 0; i < array->length(); ++i) {
2142 if (array->get(i)->IsUndefined()) {
2143 array->set(i, new_map);
2144 return array;
2145 }
2146 }
2147
2148 // Must tenure, DescriptorArray expects no new-space objects.
2149 MaybeObject* maybe_new_array =
2150 heap->AllocateFixedArray(array->length() + 1, TENURED);
2151 if (!maybe_new_array->To<FixedArray>(&new_array)) {
2152 return maybe_new_array;
2153 }
2154 int i = 0;
2155 while (i < array->length()) {
2156 new_array->set(i, array->get(i));
2157 ++i;
2158 }
2159 new_array->set(i, new_map);
2160 return new_array;
2161 }
2162
2163
2164 MaybeObject* JSObject::GetElementsTransitionMap(ElementsKind elements_kind) {
2165 Heap* current_heap = GetHeap();
2166 Map* current_map = map();
2167 DescriptorArray* descriptors = current_map->instance_descriptors();
2006 String* elements_transition_sentinel_name = current_heap->empty_symbol(); 2168 String* elements_transition_sentinel_name = current_heap->empty_symbol();
2007 2169
2170 if (current_map->elements_kind() == elements_kind) return current_map;
2171
2172 // Only objects with FastProperties can have DescriptorArrays and can track
2173 // element-related maps. Also don't add descriptors to maps that are shared.
2174 bool safe_to_add_transition = HasFastProperties() &&
2175 !current_map->IsUndefined() &&
2176 !current_map->is_shared();
2177
2178 // Prevent long chains of DICTIONARY -> FAST_ELEMENTS maps cause by objects
2179 // with elements that switch back and forth between dictionary and fast
2180 // element mode.
2181 if ((current_map->elements_kind() == DICTIONARY_ELEMENTS &&
2182 elements_kind == FAST_ELEMENTS)) {
2183 safe_to_add_transition = false;
2184 }
2185
2186 Object* descriptor_contents = NULL;
2008 if (safe_to_add_transition) { 2187 if (safe_to_add_transition) {
2009 // It's only safe to manipulate the descriptor array if it would be 2188 // It's only safe to manipulate the descriptor array if it would be
2010 // safe to add a transition. 2189 // safe to add a transition.
2011 2190
2012 ASSERT(!is_shared()); // no transitions can be added to shared maps.
2013 // Check if the elements transition already exists. 2191 // Check if the elements transition already exists.
2014 DescriptorLookupCache* cache = 2192 DescriptorLookupCache* cache =
2015 current_heap->isolate()->descriptor_lookup_cache(); 2193 current_heap->isolate()->descriptor_lookup_cache();
2016 int index = cache->Lookup(descriptors, elements_transition_sentinel_name); 2194 int index = cache->Lookup(descriptors, elements_transition_sentinel_name);
2017 if (index == DescriptorLookupCache::kAbsent) { 2195 if (index == DescriptorLookupCache::kAbsent) {
2018 index = descriptors->Search(elements_transition_sentinel_name); 2196 index = descriptors->Search(elements_transition_sentinel_name);
2019 cache->Update(descriptors, 2197 cache->Update(descriptors,
2020 elements_transition_sentinel_name, 2198 elements_transition_sentinel_name,
2021 index); 2199 index);
2022 } 2200 }
2023 2201
2024 // If the transition already exists, check the type. If there is a match, 2202 // If the transition already exists, check the type. If there is a match,
2025 // return it. 2203 // return it.
2026 if (index != DescriptorArray::kNotFound) { 2204 if (index != DescriptorArray::kNotFound) {
2027 PropertyDetails details(PropertyDetails(descriptors->GetDetails(index))); 2205 PropertyDetails details(PropertyDetails(descriptors->GetDetails(index)));
2028 if (details.type() == ELEMENTS_TRANSITION && 2206 if (details.type() == ELEMENTS_TRANSITION) {
2029 details.elements_kind() == elements_kind) { 2207 descriptor_contents = descriptors->GetValue(index);
2030 return descriptors->GetValue(index); 2208 Map* maybe_transition_map =
2209 GetElementsTransitionMapFromDescriptor(descriptor_contents,
2210 elements_kind);
2211 if (maybe_transition_map != NULL) {
2212 ASSERT(maybe_transition_map->IsMap());
2213 return maybe_transition_map;
2214 }
2031 } else { 2215 } else {
2032 safe_to_add_transition = false; 2216 safe_to_add_transition = false;
2033 } 2217 }
2034 } 2218 }
2035 } 2219 }
2036 2220
2037 // No transition to an existing map for the given ElementsKind. Make a new 2221 // No transition to an existing map for the given ElementsKind. Make a new
2038 // one. 2222 // one.
2039 Object* obj; 2223 Object* obj;
2040 { MaybeObject* maybe_map = CopyDropTransitions(); 2224 { MaybeObject* maybe_map = current_map->CopyDropTransitions();
2041 if (!maybe_map->ToObject(&obj)) return maybe_map; 2225 if (!maybe_map->ToObject(&obj)) return maybe_map;
2042 } 2226 }
2043 Map* new_map = Map::cast(obj); 2227 Map* new_map = Map::cast(obj);
2044 2228
2045 new_map->set_elements_kind(elements_kind); 2229 new_map->set_elements_kind(elements_kind);
2046 GetIsolate()->counters()->map_to_external_array_elements()->Increment();
2047 2230
2048 // Only remember the map transition if the object's map is NOT equal to the 2231 // Only remember the map transition if the object's map is NOT equal to the
2049 // global object_function's map and there is not an already existing 2232 // global object_function's map and there is not an already existing
2050 // non-matching element transition. 2233 // non-matching element transition.
2051 bool allow_map_transition = 2234 bool allow_map_transition = safe_to_add_transition &&
2052 safe_to_add_transition &&
2053 (GetIsolate()->context()->global_context()->object_function()->map() != 2235 (GetIsolate()->context()->global_context()->object_function()->map() !=
2054 map()); 2236 map());
2055 if (allow_map_transition) { 2237 if (allow_map_transition) {
2056 // Allocate new instance descriptors for the old map with map transition. 2238 MaybeObject* maybe_new_contents =
2239 AddElementsTransitionMapToDescriptor(descriptor_contents, new_map);
2240 Object* new_contents;
2241 if (!maybe_new_contents->ToObject(&new_contents)) {
2242 return maybe_new_contents;
2243 }
2244
2057 ElementsTransitionDescriptor desc(elements_transition_sentinel_name, 2245 ElementsTransitionDescriptor desc(elements_transition_sentinel_name,
2058 Map::cast(new_map), 2246 new_contents);
2059 elements_kind);
2060 Object* new_descriptors; 2247 Object* new_descriptors;
2061 MaybeObject* maybe_new_descriptors = descriptors->CopyInsert( 2248 MaybeObject* maybe_new_descriptors = descriptors->CopyInsert(
2062 &desc, 2249 &desc,
2063 KEEP_TRANSITIONS); 2250 KEEP_TRANSITIONS);
2064 if (!maybe_new_descriptors->ToObject(&new_descriptors)) { 2251 if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
2065 return maybe_new_descriptors; 2252 return maybe_new_descriptors;
2066 } 2253 }
2067 descriptors = DescriptorArray::cast(new_descriptors); 2254 descriptors = DescriptorArray::cast(new_descriptors);
2068 set_instance_descriptors(descriptors); 2255 current_map->set_instance_descriptors(descriptors);
2069 } 2256 }
2070 2257
2071 return new_map; 2258 return new_map;
2072 } 2259 }
2073 2260
2074 2261
2075 void JSObject::LocalLookupRealNamedProperty(String* name, 2262 void JSObject::LocalLookupRealNamedProperty(String* name,
2076 LookupResult* result) { 2263 LookupResult* result) {
2077 if (IsJSGlobalProxy()) { 2264 if (IsJSGlobalProxy()) {
2078 Object* proto = GetPrototype(); 2265 Object* proto = GetPrototype();
2079 if (proto->IsNull()) return result->NotFound(); 2266 if (proto->IsNull()) return result->NotFound();
2080 ASSERT(proto->IsJSGlobalObject()); 2267 ASSERT(proto->IsJSGlobalObject());
2268 // A GlobalProxy's prototype should always be a proper JSObject.
2081 return JSObject::cast(proto)->LocalLookupRealNamedProperty(name, result); 2269 return JSObject::cast(proto)->LocalLookupRealNamedProperty(name, result);
2082 } 2270 }
2083 2271
2084 if (HasFastProperties()) { 2272 if (HasFastProperties()) {
2085 LookupInDescriptor(name, result); 2273 LookupInDescriptor(name, result);
2086 if (result->IsFound()) { 2274 if (result->IsFound()) {
2087 // A property, a map transition or a null descriptor was found. 2275 // A property, a map transition or a null descriptor was found.
2088 // We return all of these result types because 2276 // We return all of these result types because
2089 // LocalLookupRealNamedProperty is used when setting properties 2277 // LocalLookupRealNamedProperty is used when setting properties
2090 // where map transitions and null descriptors are handled. 2278 // where map transitions and null descriptors are handled.
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
2197 return *value_handle; 2385 return *value_handle;
2198 } 2386 }
2199 2387
2200 2388
2201 MaybeObject* JSReceiver::SetProperty(LookupResult* result, 2389 MaybeObject* JSReceiver::SetProperty(LookupResult* result,
2202 String* key, 2390 String* key,
2203 Object* value, 2391 Object* value,
2204 PropertyAttributes attributes, 2392 PropertyAttributes attributes,
2205 StrictModeFlag strict_mode) { 2393 StrictModeFlag strict_mode) {
2206 if (result->IsFound() && result->type() == HANDLER) { 2394 if (result->IsFound() && result->type() == HANDLER) {
2207 return JSProxy::cast(this)->SetPropertyWithHandler( 2395 return result->proxy()->SetPropertyWithHandler(
2208 key, value, attributes, strict_mode); 2396 key, value, attributes, strict_mode);
2209 } else { 2397 } else {
2210 return JSObject::cast(this)->SetPropertyForResult( 2398 return JSObject::cast(this)->SetPropertyForResult(
2211 result, key, value, attributes, strict_mode); 2399 result, key, value, attributes, strict_mode);
2212 } 2400 }
2213 } 2401 }
2214 2402
2215 2403
2216 bool JSProxy::HasPropertyWithHandler(String* name_raw) { 2404 bool JSProxy::HasPropertyWithHandler(String* name_raw) {
2217 Isolate* isolate = GetIsolate(); 2405 Isolate* isolate = GetIsolate();
2218 HandleScope scope(isolate); 2406 HandleScope scope(isolate);
2219 Handle<Object> receiver(this); 2407 Handle<Object> receiver(this);
2220 Handle<Object> name(name_raw); 2408 Handle<Object> name(name_raw);
2221 Handle<Object> handler(this->handler());
2222 2409
2223 // Extract trap function. 2410 Handle<Object> args[] = { name };
2224 Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("has"); 2411 Handle<Object> result = CallTrap(
2225 Handle<Object> trap(v8::internal::GetProperty(handler, trap_name)); 2412 "has", isolate->derived_has_trap(), ARRAY_SIZE(args), args);
2226 if (isolate->has_pending_exception()) return Failure::Exception(); 2413 if (isolate->has_pending_exception()) return Failure::Exception();
2227 if (trap->IsUndefined()) {
2228 trap = isolate->derived_has_trap();
2229 }
2230
2231 // Call trap function.
2232 Object** args[] = { name.location() };
2233 bool has_exception;
2234 Handle<Object> result =
2235 Execution::Call(trap, handler, ARRAY_SIZE(args), args, &has_exception);
2236 if (has_exception) return Failure::Exception();
2237 2414
2238 return result->ToBoolean()->IsTrue(); 2415 return result->ToBoolean()->IsTrue();
2239 } 2416 }
2240 2417
2241 2418
2242 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler( 2419 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler(
2243 String* name_raw, 2420 String* name_raw,
2244 Object* value_raw, 2421 Object* value_raw,
2245 PropertyAttributes attributes, 2422 PropertyAttributes attributes,
2246 StrictModeFlag strict_mode) { 2423 StrictModeFlag strict_mode) {
2247 Isolate* isolate = GetIsolate(); 2424 Isolate* isolate = GetIsolate();
2248 HandleScope scope(isolate); 2425 HandleScope scope(isolate);
2249 Handle<Object> receiver(this); 2426 Handle<Object> receiver(this);
2250 Handle<Object> name(name_raw); 2427 Handle<Object> name(name_raw);
2251 Handle<Object> value(value_raw); 2428 Handle<Object> value(value_raw);
2252 Handle<Object> handler(this->handler());
2253 2429
2254 // Extract trap function. 2430 Handle<Object> args[] = { receiver, name, value };
2255 Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("set"); 2431 CallTrap("set", isolate->derived_set_trap(), ARRAY_SIZE(args), args);
2256 Handle<Object> trap(v8::internal::GetProperty(handler, trap_name));
2257 if (isolate->has_pending_exception()) return Failure::Exception(); 2432 if (isolate->has_pending_exception()) return Failure::Exception();
2258 if (trap->IsUndefined()) {
2259 trap = isolate->derived_set_trap();
2260 }
2261
2262 // Call trap function.
2263 Object** args[] = {
2264 receiver.location(), name.location(), value.location()
2265 };
2266 bool has_exception;
2267 Execution::Call(trap, handler, ARRAY_SIZE(args), args, &has_exception);
2268 if (has_exception) return Failure::Exception();
2269 2433
2270 return *value; 2434 return *value;
2271 } 2435 }
2272 2436
2437
2438 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandlerIfDefiningSetter(
2439 String* name_raw,
2440 Object* value_raw,
2441 PropertyAttributes attributes,
2442 StrictModeFlag strict_mode,
2443 bool* found) {
2444 *found = true; // except where defined otherwise...
2445 Isolate* isolate = GetHeap()->isolate();
2446 Handle<JSProxy> proxy(this);
2447 Handle<String> name(name_raw);
2448 Handle<Object> value(value_raw);
2449 Handle<Object> args[] = { name };
2450 Handle<Object> result = proxy->CallTrap(
2451 "getOwnPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args);
2452 if (isolate->has_pending_exception()) return Failure::Exception();
2453
2454 if (!result->IsUndefined()) {
2455 // The proxy handler cares about this property.
2456 // Check whether it is virtualized as an accessor.
2457 // Emulate [[GetProperty]] semantics for proxies.
2458 bool has_pending_exception;
2459 Object** argv[] = { result.location() };
2460 Handle<Object> desc =
2461 Execution::Call(isolate->to_complete_property_descriptor(), result,
2462 ARRAY_SIZE(argv), argv, &has_pending_exception);
2463 if (has_pending_exception) return Failure::Exception();
2464
2465 Handle<String> conf_name =
2466 isolate->factory()->LookupAsciiSymbol("configurable_");
2467 Handle<Object> configurable(v8::internal::GetProperty(desc, conf_name));
2468 ASSERT(!isolate->has_pending_exception());
2469 if (configurable->IsFalse()) {
2470 Handle<Object> args[] = { Handle<Object>(proxy->handler()), proxy, name };
2471 Handle<Object> error = isolate->factory()->NewTypeError(
2472 "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args)));
2473 return isolate->Throw(*error);
2474 }
2475 ASSERT(configurable->IsTrue());
2476
2477 // Check for AccessorDescriptor.
2478 Handle<String> set_name = isolate->factory()->LookupAsciiSymbol("set_");
2479 Handle<Object> setter(v8::internal::GetProperty(desc, set_name));
2480 ASSERT(!isolate->has_pending_exception());
2481 if (!setter->IsUndefined()) {
2482 // We have a setter -- invoke it.
2483 // TODO(rossberg): nicer would be to cast to some JSCallable here...
2484 return proxy->SetPropertyWithDefinedSetter(
2485 JSReceiver::cast(*setter), *value);
2486 } else {
2487 Handle<String> get_name = isolate->factory()->LookupAsciiSymbol("get_");
2488 Handle<Object> getter(v8::internal::GetProperty(desc, get_name));
2489 ASSERT(!isolate->has_pending_exception());
2490 if (!getter->IsUndefined()) {
2491 // We have a getter but no setter -- the property may not be
2492 // written. In strict mode, throw an error.
2493 if (strict_mode == kNonStrictMode) return *value;
2494 Handle<Object> args[] = { name, proxy };
2495 Handle<Object> error = isolate->factory()->NewTypeError(
2496 "no_setter_in_callback", HandleVector(args, ARRAY_SIZE(args)));
2497 return isolate->Throw(*error);
2498 }
2499 }
2500 // Fall-through.
2501 }
2502
2503 // The proxy does not define the property as an accessor.
2504 *found = false;
2505 return *value;
2506 }
2507
2273 2508
2274 MUST_USE_RESULT MaybeObject* JSProxy::DeletePropertyWithHandler( 2509 MUST_USE_RESULT MaybeObject* JSProxy::DeletePropertyWithHandler(
2275 String* name_raw, DeleteMode mode) { 2510 String* name_raw, DeleteMode mode) {
2276 Isolate* isolate = GetIsolate(); 2511 Isolate* isolate = GetIsolate();
2277 HandleScope scope(isolate); 2512 HandleScope scope(isolate);
2278 Handle<Object> receiver(this); 2513 Handle<Object> receiver(this);
2279 Handle<Object> name(name_raw); 2514 Handle<Object> name(name_raw);
2280 Handle<Object> handler(this->handler());
2281 2515
2282 // Extract trap function. 2516 Handle<Object> args[] = { name };
2283 Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("delete"); 2517 Handle<Object> result = CallTrap(
2284 Handle<Object> trap(v8::internal::GetProperty(handler, trap_name)); 2518 "delete", Handle<Object>(), ARRAY_SIZE(args), args);
2285 if (isolate->has_pending_exception()) return Failure::Exception(); 2519 if (isolate->has_pending_exception()) return Failure::Exception();
2286 if (trap->IsUndefined()) {
2287 Handle<Object> args[] = { handler, trap_name };
2288 Handle<Object> error = isolate->factory()->NewTypeError(
2289 "handler_trap_missing", HandleVector(args, ARRAY_SIZE(args)));
2290 isolate->Throw(*error);
2291 return Failure::Exception();
2292 }
2293
2294 // Call trap function.
2295 Object** args[] = { name.location() };
2296 bool has_exception;
2297 Handle<Object> result =
2298 Execution::Call(trap, handler, ARRAY_SIZE(args), args, &has_exception);
2299 if (has_exception) return Failure::Exception();
2300 2520
2301 Object* bool_result = result->ToBoolean(); 2521 Object* bool_result = result->ToBoolean();
2302 if (mode == STRICT_DELETION && 2522 if (mode == STRICT_DELETION && bool_result == GetHeap()->false_value()) {
2303 bool_result == isolate->heap()->false_value()) { 2523 Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("delete");
2304 Handle<Object> args[] = { handler, trap_name }; 2524 Handle<Object> args[] = { Handle<Object>(handler()), trap_name };
2305 Handle<Object> error = isolate->factory()->NewTypeError( 2525 Handle<Object> error = isolate->factory()->NewTypeError(
2306 "handler_failed", HandleVector(args, ARRAY_SIZE(args))); 2526 "handler_failed", HandleVector(args, ARRAY_SIZE(args)));
2307 isolate->Throw(*error); 2527 isolate->Throw(*error);
2308 return Failure::Exception(); 2528 return Failure::Exception();
2309 } 2529 }
2310 return bool_result; 2530 return bool_result;
2311 } 2531 }
2312 2532
2313 2533
2534 MUST_USE_RESULT MaybeObject* JSProxy::DeleteElementWithHandler(
2535 uint32_t index,
2536 DeleteMode mode) {
2537 Isolate* isolate = GetIsolate();
2538 HandleScope scope(isolate);
2539 Handle<String> name = isolate->factory()->Uint32ToString(index);
2540 return JSProxy::DeletePropertyWithHandler(*name, mode);
2541 }
2542
2543
2314 MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler( 2544 MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler(
2315 JSReceiver* receiver_raw, 2545 JSReceiver* receiver_raw,
2316 String* name_raw, 2546 String* name_raw) {
2317 bool* has_exception) {
2318 Isolate* isolate = GetIsolate(); 2547 Isolate* isolate = GetIsolate();
2319 HandleScope scope(isolate); 2548 HandleScope scope(isolate);
2549 Handle<JSProxy> proxy(this);
2320 Handle<JSReceiver> receiver(receiver_raw); 2550 Handle<JSReceiver> receiver(receiver_raw);
2321 Handle<Object> name(name_raw); 2551 Handle<Object> name(name_raw);
2322 Handle<Object> handler(this->handler());
2323 2552
2324 // Extract trap function. 2553 Handle<Object> args[] = { name };
2325 Handle<String> trap_name = 2554 Handle<Object> result = CallTrap(
2326 isolate->factory()->LookupAsciiSymbol("getPropertyDescriptor"); 2555 "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args);
2327 Handle<Object> trap(v8::internal::GetProperty(handler, trap_name));
2328 if (isolate->has_pending_exception()) return NONE; 2556 if (isolate->has_pending_exception()) return NONE;
2329 if (trap->IsUndefined()) { 2557
2330 Handle<Object> args[] = { handler, trap_name }; 2558 if (result->IsUndefined()) return ABSENT;
2559
2560 bool has_pending_exception;
2561 Object** argv[] = { result.location() };
2562 Handle<Object> desc =
2563 Execution::Call(isolate->to_complete_property_descriptor(), result,
2564 ARRAY_SIZE(argv), argv, &has_pending_exception);
2565 if (has_pending_exception) return NONE;
2566
2567 // Convert result to PropertyAttributes.
2568 Handle<String> enum_n = isolate->factory()->LookupAsciiSymbol("enumerable");
2569 Handle<Object> enumerable(v8::internal::GetProperty(desc, enum_n));
2570 if (isolate->has_pending_exception()) return NONE;
2571 Handle<String> conf_n = isolate->factory()->LookupAsciiSymbol("configurable");
2572 Handle<Object> configurable(v8::internal::GetProperty(desc, conf_n));
2573 if (isolate->has_pending_exception()) return NONE;
2574 Handle<String> writ_n = isolate->factory()->LookupAsciiSymbol("writable");
2575 Handle<Object> writable(v8::internal::GetProperty(desc, writ_n));
2576 if (isolate->has_pending_exception()) return NONE;
2577
2578 if (configurable->IsFalse()) {
2579 Handle<Object> args[] = { Handle<Object>(proxy->handler()), proxy, name };
2331 Handle<Object> error = isolate->factory()->NewTypeError( 2580 Handle<Object> error = isolate->factory()->NewTypeError(
2332 "handler_trap_missing", HandleVector(args, ARRAY_SIZE(args))); 2581 "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args)));
2333 isolate->Throw(*error); 2582 isolate->Throw(*error);
2334 *has_exception = true;
2335 return NONE; 2583 return NONE;
2336 } 2584 }
2337 2585
2338 // Call trap function. 2586 int attributes = NONE;
2339 Object** args[] = { name.location() }; 2587 if (enumerable->ToBoolean()->IsFalse()) attributes |= DONT_ENUM;
2340 Handle<Object> result = 2588 if (configurable->ToBoolean()->IsFalse()) attributes |= DONT_DELETE;
2341 Execution::Call(trap, handler, ARRAY_SIZE(args), args, has_exception); 2589 if (writable->ToBoolean()->IsFalse()) attributes |= READ_ONLY;
2342 if (has_exception) return NONE; 2590 return static_cast<PropertyAttributes>(attributes);
2343
2344 // TODO(rossberg): convert result to PropertyAttributes
2345 USE(result);
2346 return NONE;
2347 } 2591 }
2348 2592
2349 2593
2594 MUST_USE_RESULT PropertyAttributes JSProxy::GetElementAttributeWithHandler(
2595 JSReceiver* receiver,
2596 uint32_t index) {
2597 Isolate* isolate = GetIsolate();
2598 HandleScope scope(isolate);
2599 Handle<String> name = isolate->factory()->Uint32ToString(index);
2600 return GetPropertyAttributeWithHandler(receiver, *name);
2601 }
2602
2603
2350 void JSProxy::Fix() { 2604 void JSProxy::Fix() {
2351 Isolate* isolate = GetIsolate(); 2605 Isolate* isolate = GetIsolate();
2352 HandleScope scope(isolate); 2606 HandleScope scope(isolate);
2353 Handle<JSProxy> self(this); 2607 Handle<JSProxy> self(this);
2354 2608
2609 // Save identity hash.
2610 MaybeObject* maybe_hash = GetIdentityHash(OMIT_CREATION);
2611
2355 if (IsJSFunctionProxy()) { 2612 if (IsJSFunctionProxy()) {
2356 isolate->factory()->BecomeJSFunction(self); 2613 isolate->factory()->BecomeJSFunction(self);
2357 // Code will be set on the JavaScript side. 2614 // Code will be set on the JavaScript side.
2358 } else { 2615 } else {
2359 isolate->factory()->BecomeJSObject(self); 2616 isolate->factory()->BecomeJSObject(self);
2360 } 2617 }
2361 ASSERT(self->IsJSObject()); 2618 ASSERT(self->IsJSObject());
2619
2620 // Inherit identity, if it was present.
2621 Object* hash;
2622 if (maybe_hash->To<Object>(&hash) && hash->IsSmi()) {
2623 Handle<JSObject> new_self(JSObject::cast(*self));
2624 isolate->factory()->SetIdentityHash(new_self, hash);
2625 }
2362 } 2626 }
2363 2627
2364 2628
2629 MUST_USE_RESULT Handle<Object> JSProxy::CallTrap(
2630 const char* name,
2631 Handle<Object> derived,
2632 int argc,
2633 Handle<Object> args[]) {
2634 Isolate* isolate = GetIsolate();
2635 Handle<Object> handler(this->handler());
2636
2637 Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol(name);
2638 Handle<Object> trap(v8::internal::GetProperty(handler, trap_name));
2639 if (isolate->has_pending_exception()) return trap;
2640
2641 if (trap->IsUndefined()) {
2642 if (derived.is_null()) {
2643 Handle<Object> args[] = { handler, trap_name };
2644 Handle<Object> error = isolate->factory()->NewTypeError(
2645 "handler_trap_missing", HandleVector(args, ARRAY_SIZE(args)));
2646 isolate->Throw(*error);
2647 return Handle<Object>();
2648 }
2649 trap = Handle<Object>(derived);
2650 }
2651
2652 Object*** argv = reinterpret_cast<Object***>(args);
2653 bool threw;
2654 return Execution::Call(trap, handler, argc, argv, &threw);
2655 }
2656
2365 2657
2366 MaybeObject* JSObject::SetPropertyForResult(LookupResult* result, 2658 MaybeObject* JSObject::SetPropertyForResult(LookupResult* result,
2367 String* name, 2659 String* name,
2368 Object* value, 2660 Object* value,
2369 PropertyAttributes attributes, 2661 PropertyAttributes attributes,
2370 StrictModeFlag strict_mode) { 2662 StrictModeFlag strict_mode) {
2371 Heap* heap = GetHeap(); 2663 Heap* heap = GetHeap();
2372 // Make sure that the top context does not change when doing callbacks or 2664 // Make sure that the top context does not change when doing callbacks or
2373 // interceptor calls. 2665 // interceptor calls.
2374 AssertNoContextChange ncc; 2666 AssertNoContextChange ncc;
2375 2667
2376 // Optimization for 2-byte strings often used as keys in a decompression 2668 // Optimization for 2-byte strings often used as keys in a decompression
2377 // dictionary. We make these short keys into symbols to avoid constantly 2669 // dictionary. We make these short keys into symbols to avoid constantly
2378 // reallocating them. 2670 // reallocating them.
2379 if (!name->IsSymbol() && name->length() <= 2) { 2671 if (!name->IsSymbol() && name->length() <= 2) {
2380 Object* symbol_version; 2672 Object* symbol_version;
2381 { MaybeObject* maybe_symbol_version = heap->LookupSymbol(name); 2673 { MaybeObject* maybe_symbol_version = heap->LookupSymbol(name);
2382 if (maybe_symbol_version->ToObject(&symbol_version)) { 2674 if (maybe_symbol_version->ToObject(&symbol_version)) {
2383 name = String::cast(symbol_version); 2675 name = String::cast(symbol_version);
2384 } 2676 }
2385 } 2677 }
2386 } 2678 }
2387 2679
2388 // Check access rights if needed. 2680 // Check access rights if needed.
2389 if (IsAccessCheckNeeded() 2681 if (IsAccessCheckNeeded()) {
2390 && !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_SET)) { 2682 if (!heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_SET)) {
2391 return SetPropertyWithFailedAccessCheck(result, 2683 return SetPropertyWithFailedAccessCheck(
2392 name, 2684 result, name, value, true, strict_mode);
2393 value, 2685 }
2394 true,
2395 strict_mode);
2396 } 2686 }
2397 2687
2398 if (IsJSGlobalProxy()) { 2688 if (IsJSGlobalProxy()) {
2399 Object* proto = GetPrototype(); 2689 Object* proto = GetPrototype();
2400 if (proto->IsNull()) return value; 2690 if (proto->IsNull()) return value;
2401 ASSERT(proto->IsJSGlobalObject()); 2691 ASSERT(proto->IsJSGlobalObject());
2402 return JSObject::cast(proto)->SetProperty( 2692 return JSObject::cast(proto)->SetPropertyForResult(
2403 result, name, value, attributes, strict_mode); 2693 result, name, value, attributes, strict_mode);
2404 } 2694 }
2405 2695
2406 if (!result->IsProperty() && !IsJSContextExtensionObject()) { 2696 if (!result->IsProperty() && !IsJSContextExtensionObject()) {
2407 // We could not find a local property so let's check whether there is an 2697 bool found = false;
2408 // accessor that wants to handle the property. 2698 MaybeObject* result_object;
2409 LookupResult accessor_result; 2699 result_object = SetPropertyWithCallbackSetterInPrototypes(name,
2410 LookupCallbackSetterInPrototypes(name, &accessor_result); 2700 value,
2411 if (accessor_result.IsProperty()) { 2701 attributes,
2412 return SetPropertyWithCallback(accessor_result.GetCallbackObject(), 2702 &found,
2413 name, 2703 strict_mode);
2414 value, 2704 if (found) return result_object;
2415 accessor_result.holder(),
2416 strict_mode);
2417 }
2418 } 2705 }
2706
2707 // At this point, no GC should have happened, as this would invalidate
2708 // 'result', which we cannot handlify!
2709
2419 if (!result->IsFound()) { 2710 if (!result->IsFound()) {
2420 // Neither properties nor transitions found. 2711 // Neither properties nor transitions found.
2421 return AddProperty(name, value, attributes, strict_mode); 2712 return AddProperty(name, value, attributes, strict_mode);
2422 } 2713 }
2423 if (result->IsReadOnly() && result->IsProperty()) { 2714 if (result->IsReadOnly() && result->IsProperty()) {
2424 if (strict_mode == kStrictMode) { 2715 if (strict_mode == kStrictMode) {
2425 HandleScope scope(heap->isolate()); 2716 Handle<JSObject> self(this);
2426 Handle<String> key(name); 2717 Handle<String> hname(name);
2427 Handle<Object> holder(this); 2718 Handle<Object> args[] = { hname, self };
2428 Handle<Object> args[2] = { key, holder };
2429 return heap->isolate()->Throw(*heap->isolate()->factory()->NewTypeError( 2719 return heap->isolate()->Throw(*heap->isolate()->factory()->NewTypeError(
2430 "strict_read_only_property", HandleVector(args, 2))); 2720 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))));
2431 } else { 2721 } else {
2432 return value; 2722 return value;
2433 } 2723 }
2434 } 2724 }
2435 // This is a real property that is not read-only, or it is a 2725 // This is a real property that is not read-only, or it is a
2436 // transition or null descriptor and there are no setters in the prototypes. 2726 // transition or null descriptor and there are no setters in the prototypes.
2437 switch (result->type()) { 2727 switch (result->type()) {
2438 case NORMAL: 2728 case NORMAL:
2439 return SetNormalizedProperty(result, value); 2729 return SetNormalizedProperty(result, value);
2440 case FIELD: 2730 case FIELD:
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
2649 *name_handle, 2939 *name_handle,
2650 continue_search); 2940 continue_search);
2651 } 2941 }
2652 2942
2653 2943
2654 PropertyAttributes JSReceiver::GetPropertyAttributeWithReceiver( 2944 PropertyAttributes JSReceiver::GetPropertyAttributeWithReceiver(
2655 JSReceiver* receiver, 2945 JSReceiver* receiver,
2656 String* key) { 2946 String* key) {
2657 uint32_t index = 0; 2947 uint32_t index = 0;
2658 if (IsJSObject() && key->AsArrayIndex(&index)) { 2948 if (IsJSObject() && key->AsArrayIndex(&index)) {
2659 if (JSObject::cast(this)->HasElementWithReceiver(receiver, index)) 2949 return JSObject::cast(this)->HasElementWithReceiver(receiver, index)
2660 return NONE; 2950 ? NONE : ABSENT;
2661 return ABSENT;
2662 } 2951 }
2663 // Named property. 2952 // Named property.
2664 LookupResult result; 2953 LookupResult result;
2665 Lookup(key, &result); 2954 Lookup(key, &result);
2666 return GetPropertyAttribute(receiver, &result, key, true); 2955 return GetPropertyAttribute(receiver, &result, key, true);
2667 } 2956 }
2668 2957
2669 2958
2670 PropertyAttributes JSReceiver::GetPropertyAttribute(JSReceiver* receiver, 2959 PropertyAttributes JSReceiver::GetPropertyAttribute(JSReceiver* receiver,
2671 LookupResult* result, 2960 LookupResult* result,
2672 String* name, 2961 String* name,
2673 bool continue_search) { 2962 bool continue_search) {
2674 // Check access rights if needed. 2963 // Check access rights if needed.
2675 if (IsAccessCheckNeeded()) { 2964 if (IsAccessCheckNeeded()) {
2676 JSObject* this_obj = JSObject::cast(this); 2965 JSObject* this_obj = JSObject::cast(this);
2677 Heap* heap = GetHeap(); 2966 Heap* heap = GetHeap();
2678 if (!heap->isolate()->MayNamedAccess(this_obj, name, v8::ACCESS_HAS)) { 2967 if (!heap->isolate()->MayNamedAccess(this_obj, name, v8::ACCESS_HAS)) {
2679 return this_obj->GetPropertyAttributeWithFailedAccessCheck( 2968 return this_obj->GetPropertyAttributeWithFailedAccessCheck(
2680 receiver, result, name, continue_search); 2969 receiver, result, name, continue_search);
2681 } 2970 }
2682 } 2971 }
2683 if (result->IsProperty()) { 2972 if (result->IsProperty()) {
2684 switch (result->type()) { 2973 switch (result->type()) {
2685 case NORMAL: // fall through 2974 case NORMAL: // fall through
2686 case FIELD: 2975 case FIELD:
2687 case CONSTANT_FUNCTION: 2976 case CONSTANT_FUNCTION:
2688 case CALLBACKS: 2977 case CALLBACKS:
2689 return result->GetAttributes(); 2978 return result->GetAttributes();
2690 case HANDLER: { 2979 case HANDLER: {
2691 // TODO(rossberg): propagate exceptions properly. 2980 return JSProxy::cast(result->proxy())->GetPropertyAttributeWithHandler(
2692 bool has_exception = false; 2981 receiver, name);
2693 return JSProxy::cast(this)->GetPropertyAttributeWithHandler(
2694 receiver, name, &has_exception);
2695 } 2982 }
2696 case INTERCEPTOR: 2983 case INTERCEPTOR:
2697 return result->holder()->GetPropertyAttributeWithInterceptor( 2984 return result->holder()->GetPropertyAttributeWithInterceptor(
2698 JSObject::cast(receiver), name, continue_search); 2985 JSObject::cast(receiver), name, continue_search);
2699 default: 2986 default:
2700 UNREACHABLE(); 2987 UNREACHABLE();
2701 } 2988 }
2702 } 2989 }
2703 return ABSENT; 2990 return ABSENT;
2704 } 2991 }
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
2850 case CONSTANT_TRANSITION: 3137 case CONSTANT_TRANSITION:
2851 case NULL_DESCRIPTOR: 3138 case NULL_DESCRIPTOR:
2852 case INTERCEPTOR: 3139 case INTERCEPTOR:
2853 case ELEMENTS_TRANSITION: 3140 case ELEMENTS_TRANSITION:
2854 break; 3141 break;
2855 default: 3142 default:
2856 UNREACHABLE(); 3143 UNREACHABLE();
2857 } 3144 }
2858 } 3145 }
2859 3146
2860 Heap* current_heap = map_of_this->heap(); 3147 Heap* current_heap = GetHeap();
2861 3148
2862 // Copy the next enumeration index from instance descriptor. 3149 // Copy the next enumeration index from instance descriptor.
2863 int index = map_of_this->instance_descriptors()->NextEnumerationIndex(); 3150 int index = map_of_this->instance_descriptors()->NextEnumerationIndex();
2864 dictionary->SetNextEnumerationIndex(index); 3151 dictionary->SetNextEnumerationIndex(index);
2865 3152
2866 { MaybeObject* maybe_obj = 3153 { MaybeObject* maybe_obj =
2867 current_heap->isolate()->context()->global_context()-> 3154 current_heap->isolate()->context()->global_context()->
2868 normalized_map_cache()->Get(this, mode); 3155 normalized_map_cache()->Get(this, mode);
2869 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 3156 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
2870 } 3157 }
2871 Map* new_map = Map::cast(obj); 3158 Map* new_map = Map::cast(obj);
2872 3159
2873 // We have now successfully allocated all the necessary objects. 3160 // We have now successfully allocated all the necessary objects.
2874 // Changes can now be made with the guarantee that all of them take effect. 3161 // Changes can now be made with the guarantee that all of them take effect.
2875 3162
2876 // Resize the object in the heap if necessary. 3163 // Resize the object in the heap if necessary.
2877 int new_instance_size = new_map->instance_size(); 3164 int new_instance_size = new_map->instance_size();
2878 int instance_size_delta = map_of_this->instance_size() - new_instance_size; 3165 int instance_size_delta = map_of_this->instance_size() - new_instance_size;
2879 ASSERT(instance_size_delta >= 0); 3166 ASSERT(instance_size_delta >= 0);
2880 current_heap->CreateFillerObjectAt(this->address() + new_instance_size, 3167 current_heap->CreateFillerObjectAt(this->address() + new_instance_size,
2881 instance_size_delta); 3168 instance_size_delta);
3169 if (Marking::IsBlack(Marking::MarkBitFrom(this))) {
3170 MemoryChunk::IncrementLiveBytes(this->address(), -instance_size_delta);
3171 }
3172
2882 3173
2883 set_map(new_map); 3174 set_map(new_map);
2884 new_map->clear_instance_descriptors(); 3175 new_map->clear_instance_descriptors();
2885 3176
2886 set_properties(dictionary); 3177 set_properties(dictionary);
2887 3178
2888 current_heap->isolate()->counters()->props_to_dictionary()->Increment(); 3179 current_heap->isolate()->counters()->props_to_dictionary()->Increment();
2889 3180
2890 #ifdef DEBUG 3181 #ifdef DEBUG
2891 if (FLAG_trace_normalization) { 3182 if (FLAG_trace_normalization) {
(...skipping 13 matching lines...) Expand all
2905 } 3196 }
2906 3197
2907 3198
2908 MaybeObject* JSObject::NormalizeElements() { 3199 MaybeObject* JSObject::NormalizeElements() {
2909 ASSERT(!HasExternalArrayElements()); 3200 ASSERT(!HasExternalArrayElements());
2910 3201
2911 // Find the backing store. 3202 // Find the backing store.
2912 FixedArrayBase* array = FixedArrayBase::cast(elements()); 3203 FixedArrayBase* array = FixedArrayBase::cast(elements());
2913 Map* old_map = array->map(); 3204 Map* old_map = array->map();
2914 bool is_arguments = 3205 bool is_arguments =
2915 (old_map == old_map->heap()->non_strict_arguments_elements_map()); 3206 (old_map == old_map->GetHeap()->non_strict_arguments_elements_map());
2916 if (is_arguments) { 3207 if (is_arguments) {
2917 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1)); 3208 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1));
2918 } 3209 }
2919 if (array->IsDictionary()) return array; 3210 if (array->IsDictionary()) return array;
2920 3211
2921 ASSERT(HasFastElements() || 3212 ASSERT(HasFastElements() ||
3213 HasFastSmiOnlyElements() ||
2922 HasFastDoubleElements() || 3214 HasFastDoubleElements() ||
2923 HasFastArgumentsElements()); 3215 HasFastArgumentsElements());
2924 // Compute the effective length and allocate a new backing store. 3216 // Compute the effective length and allocate a new backing store.
2925 int length = IsJSArray() 3217 int length = IsJSArray()
2926 ? Smi::cast(JSArray::cast(this)->length())->value() 3218 ? Smi::cast(JSArray::cast(this)->length())->value()
2927 : array->length(); 3219 : array->length();
2928 int old_capacity = 0; 3220 int old_capacity = 0;
2929 int used_elements = 0; 3221 int used_elements = 0;
2930 GetElementsCapacityAndUsage(&old_capacity, &used_elements); 3222 GetElementsCapacityAndUsage(&old_capacity, &used_elements);
2931 NumberDictionary* dictionary = NULL; 3223 NumberDictionary* dictionary = NULL;
(...skipping 14 matching lines...) Expand all
2946 } else { 3238 } else {
2947 // Objects must be allocated in the old object space, since the 3239 // Objects must be allocated in the old object space, since the
2948 // overall number of HeapNumbers needed for the conversion might 3240 // overall number of HeapNumbers needed for the conversion might
2949 // exceed the capacity of new space, and we would fail repeatedly 3241 // exceed the capacity of new space, and we would fail repeatedly
2950 // trying to convert the FixedDoubleArray. 3242 // trying to convert the FixedDoubleArray.
2951 MaybeObject* maybe_value_object = 3243 MaybeObject* maybe_value_object =
2952 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED); 3244 GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED);
2953 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; 3245 if (!maybe_value_object->ToObject(&value)) return maybe_value_object;
2954 } 3246 }
2955 } else { 3247 } else {
2956 ASSERT(old_map->has_fast_elements()); 3248 ASSERT(old_map->has_fast_elements() ||
3249 old_map->has_fast_smi_only_elements());
2957 value = FixedArray::cast(array)->get(i); 3250 value = FixedArray::cast(array)->get(i);
2958 } 3251 }
2959 PropertyDetails details = PropertyDetails(NONE, NORMAL); 3252 PropertyDetails details = PropertyDetails(NONE, NORMAL);
2960 if (!value->IsTheHole()) { 3253 if (!value->IsTheHole()) {
2961 Object* result; 3254 Object* result;
2962 MaybeObject* maybe_result = 3255 MaybeObject* maybe_result =
2963 dictionary->AddNumberEntry(i, value, details); 3256 dictionary->AddNumberEntry(i, value, details);
2964 if (!maybe_result->ToObject(&result)) return maybe_result; 3257 if (!maybe_result->ToObject(&result)) return maybe_result;
2965 dictionary = NumberDictionary::cast(result); 3258 dictionary = NumberDictionary::cast(result);
2966 } 3259 }
2967 } 3260 }
2968 3261
2969 // Switch to using the dictionary as the backing storage for elements. 3262 // Switch to using the dictionary as the backing storage for elements.
2970 if (is_arguments) { 3263 if (is_arguments) {
2971 FixedArray::cast(elements())->set(1, dictionary); 3264 FixedArray::cast(elements())->set(1, dictionary);
2972 } else { 3265 } else {
2973 // Set the new map first to satify the elements type assert in 3266 // Set the new map first to satify the elements type assert in
2974 // set_elements(). 3267 // set_elements().
2975 Object* new_map; 3268 Object* new_map;
2976 MaybeObject* maybe = map()->GetSlowElementsMap(); 3269 MaybeObject* maybe = GetElementsTransitionMap(DICTIONARY_ELEMENTS);
2977 if (!maybe->ToObject(&new_map)) return maybe; 3270 if (!maybe->ToObject(&new_map)) return maybe;
2978 set_map(Map::cast(new_map)); 3271 set_map(Map::cast(new_map));
2979 set_elements(dictionary); 3272 set_elements(dictionary);
2980 } 3273 }
2981 3274
2982 old_map->isolate()->counters()->elements_to_dictionary()->Increment(); 3275 old_map->GetHeap()->isolate()->counters()->elements_to_dictionary()->
3276 Increment();
2983 3277
2984 #ifdef DEBUG 3278 #ifdef DEBUG
2985 if (FLAG_trace_normalization) { 3279 if (FLAG_trace_normalization) {
2986 PrintF("Object elements have been normalized:\n"); 3280 PrintF("Object elements have been normalized:\n");
2987 Print(); 3281 Print();
2988 } 3282 }
2989 #endif 3283 #endif
2990 3284
2991 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); 3285 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
2992 return dictionary; 3286 return dictionary;
2993 } 3287 }
2994 3288
2995 3289
2996 MaybeObject* JSObject::GetHiddenProperties(HiddenPropertiesFlag flag) { 3290 Smi* JSReceiver::GenerateIdentityHash() {
2997 Isolate* isolate = GetIsolate(); 3291 Isolate* isolate = GetIsolate();
2998 Heap* heap = isolate->heap();
2999 Object* holder = BypassGlobalProxy();
3000 if (holder->IsUndefined()) return heap->undefined_value();
3001 JSObject* obj = JSObject::cast(holder);
3002 if (obj->HasFastProperties()) {
3003 // If the object has fast properties, check whether the first slot
3004 // in the descriptor array matches the hidden symbol. Since the
3005 // hidden symbols hash code is zero (and no other string has hash
3006 // code zero) it will always occupy the first entry if present.
3007 DescriptorArray* descriptors = obj->map()->instance_descriptors();
3008 if ((descriptors->number_of_descriptors() > 0) &&
3009 (descriptors->GetKey(0) == heap->hidden_symbol()) &&
3010 descriptors->IsProperty(0)) {
3011 ASSERT(descriptors->GetType(0) == FIELD);
3012 return obj->FastPropertyAt(descriptors->GetFieldIndex(0));
3013 }
3014 }
3015
3016 // Only attempt to find the hidden properties in the local object and not
3017 // in the prototype chain.
3018 if (!obj->HasHiddenPropertiesObject()) {
3019 // Hidden properties object not found. Allocate a new hidden properties
3020 // object if requested. Otherwise return the undefined value.
3021 if (flag == ALLOW_CREATION) {
3022 Object* hidden_obj;
3023 { MaybeObject* maybe_obj = heap->AllocateJSObject(
3024 isolate->context()->global_context()->object_function());
3025 if (!maybe_obj->ToObject(&hidden_obj)) return maybe_obj;
3026 }
3027 // Don't allow leakage of the hidden object through accessors
3028 // on Object.prototype.
3029 {
3030 MaybeObject* maybe_obj =
3031 JSObject::cast(hidden_obj)->SetPrototype(heap->null_value(), false);
3032 if (maybe_obj->IsFailure()) return maybe_obj;
3033 }
3034 return obj->SetHiddenPropertiesObject(hidden_obj);
3035 } else {
3036 return heap->undefined_value();
3037 }
3038 }
3039 return obj->GetHiddenPropertiesObject();
3040 }
3041
3042
3043 MaybeObject* JSObject::GetIdentityHash(HiddenPropertiesFlag flag) {
3044 Isolate* isolate = GetIsolate();
3045 Object* hidden_props_obj;
3046 { MaybeObject* maybe_obj = GetHiddenProperties(flag);
3047 if (!maybe_obj->ToObject(&hidden_props_obj)) return maybe_obj;
3048 }
3049 if (!hidden_props_obj->IsJSObject()) {
3050 // We failed to create hidden properties. That's a detached
3051 // global proxy.
3052 ASSERT(hidden_props_obj->IsUndefined());
3053 return Smi::FromInt(0);
3054 }
3055 JSObject* hidden_props = JSObject::cast(hidden_props_obj);
3056 String* hash_symbol = isolate->heap()->identity_hash_symbol();
3057 {
3058 // Note that HasLocalProperty() can cause a GC in the general case in the
3059 // presence of interceptors.
3060 AssertNoAllocation no_alloc;
3061 if (hidden_props->HasLocalProperty(hash_symbol)) {
3062 MaybeObject* hash = hidden_props->GetProperty(hash_symbol);
3063 return Smi::cast(hash->ToObjectChecked());
3064 }
3065 }
3066 3292
3067 int hash_value; 3293 int hash_value;
3068 int attempts = 0; 3294 int attempts = 0;
3069 do { 3295 do {
3070 // Generate a random 32-bit hash value but limit range to fit 3296 // Generate a random 32-bit hash value but limit range to fit
3071 // within a smi. 3297 // within a smi.
3072 hash_value = V8::Random(isolate) & Smi::kMaxValue; 3298 hash_value = V8::Random(isolate) & Smi::kMaxValue;
3073 attempts++; 3299 attempts++;
3074 } while (hash_value == 0 && attempts < 30); 3300 } while (hash_value == 0 && attempts < 30);
3075 hash_value = hash_value != 0 ? hash_value : 1; // never return 0 3301 hash_value = hash_value != 0 ? hash_value : 1; // never return 0
3076 3302
3077 Smi* hash = Smi::FromInt(hash_value); 3303 return Smi::FromInt(hash_value);
3078 { MaybeObject* result = hidden_props->SetLocalPropertyIgnoreAttributes( 3304 }
3079 hash_symbol, 3305
3080 hash, 3306
3081 static_cast<PropertyAttributes>(None)); 3307 MaybeObject* JSObject::SetIdentityHash(Object* hash, CreationFlag flag) {
3082 if (result->IsFailure()) return result; 3308 MaybeObject* maybe = SetHiddenProperty(GetHeap()->identity_hash_symbol(),
3309 hash);
3310 if (maybe->IsFailure()) return maybe;
3311 return this;
3312 }
3313
3314
3315 MaybeObject* JSObject::GetIdentityHash(CreationFlag flag) {
3316 Object* stored_value = GetHiddenProperty(GetHeap()->identity_hash_symbol());
3317 if (stored_value->IsSmi()) return stored_value;
3318
3319 Smi* hash = GenerateIdentityHash();
3320 MaybeObject* result = SetHiddenProperty(GetHeap()->identity_hash_symbol(),
3321 hash);
3322 if (result->IsFailure()) return result;
3323 if (result->ToObjectUnchecked()->IsUndefined()) {
3324 // Trying to get hash of detached proxy.
3325 return Smi::FromInt(0);
3083 } 3326 }
3084 return hash; 3327 return hash;
3085 } 3328 }
3086 3329
3087 3330
3331 MaybeObject* JSProxy::GetIdentityHash(CreationFlag flag) {
3332 Object* hash = this->hash();
3333 if (!hash->IsSmi() && flag == ALLOW_CREATION) {
3334 hash = GenerateIdentityHash();
3335 set_hash(hash);
3336 }
3337 return hash;
3338 }
3339
3340
3341 Object* JSObject::GetHiddenProperty(String* key) {
3342 if (IsJSGlobalProxy()) {
3343 // For a proxy, use the prototype as target object.
3344 Object* proxy_parent = GetPrototype();
3345 // If the proxy is detached, return undefined.
3346 if (proxy_parent->IsNull()) return GetHeap()->undefined_value();
3347 ASSERT(proxy_parent->IsJSGlobalObject());
3348 return JSObject::cast(proxy_parent)->GetHiddenProperty(key);
3349 }
3350 ASSERT(!IsJSGlobalProxy());
3351 MaybeObject* hidden_lookup = GetHiddenPropertiesDictionary(false);
3352 ASSERT(!hidden_lookup->IsFailure()); // No failure when passing false as arg.
3353 if (hidden_lookup->ToObjectUnchecked()->IsUndefined()) {
3354 return GetHeap()->undefined_value();
3355 }
3356 StringDictionary* dictionary =
3357 StringDictionary::cast(hidden_lookup->ToObjectUnchecked());
3358 int entry = dictionary->FindEntry(key);
3359 if (entry == StringDictionary::kNotFound) return GetHeap()->undefined_value();
3360 return dictionary->ValueAt(entry);
3361 }
3362
3363
3364 MaybeObject* JSObject::SetHiddenProperty(String* key, Object* value) {
3365 if (IsJSGlobalProxy()) {
3366 // For a proxy, use the prototype as target object.
3367 Object* proxy_parent = GetPrototype();
3368 // If the proxy is detached, return undefined.
3369 if (proxy_parent->IsNull()) return GetHeap()->undefined_value();
3370 ASSERT(proxy_parent->IsJSGlobalObject());
3371 return JSObject::cast(proxy_parent)->SetHiddenProperty(key, value);
3372 }
3373 ASSERT(!IsJSGlobalProxy());
3374 MaybeObject* hidden_lookup = GetHiddenPropertiesDictionary(true);
3375 StringDictionary* dictionary;
3376 if (!hidden_lookup->To<StringDictionary>(&dictionary)) return hidden_lookup;
3377
3378 // If it was found, check if the key is already in the dictionary.
3379 int entry = dictionary->FindEntry(key);
3380 if (entry != StringDictionary::kNotFound) {
3381 // If key was found, just update the value.
3382 dictionary->ValueAtPut(entry, value);
3383 return this;
3384 }
3385 // Key was not already in the dictionary, so add the entry.
3386 MaybeObject* insert_result = dictionary->Add(key,
3387 value,
3388 PropertyDetails(NONE, NORMAL));
3389 StringDictionary* new_dict;
3390 if (!insert_result->To<StringDictionary>(&new_dict)) return insert_result;
3391 if (new_dict != dictionary) {
3392 // If adding the key expanded the dictionary (i.e., Add returned a new
3393 // dictionary), store it back to the object.
3394 MaybeObject* store_result = SetHiddenPropertiesDictionary(new_dict);
3395 if (store_result->IsFailure()) return store_result;
3396 }
3397 // Return this to mark success.
3398 return this;
3399 }
3400
3401
3402 void JSObject::DeleteHiddenProperty(String* key) {
3403 if (IsJSGlobalProxy()) {
3404 // For a proxy, use the prototype as target object.
3405 Object* proxy_parent = GetPrototype();
3406 // If the proxy is detached, return immediately.
3407 if (proxy_parent->IsNull()) return;
3408 ASSERT(proxy_parent->IsJSGlobalObject());
3409 JSObject::cast(proxy_parent)->DeleteHiddenProperty(key);
3410 return;
3411 }
3412 MaybeObject* hidden_lookup = GetHiddenPropertiesDictionary(false);
3413 ASSERT(!hidden_lookup->IsFailure()); // No failure when passing false as arg.
3414 if (hidden_lookup->ToObjectUnchecked()->IsUndefined()) return;
3415 StringDictionary* dictionary =
3416 StringDictionary::cast(hidden_lookup->ToObjectUnchecked());
3417 int entry = dictionary->FindEntry(key);
3418 if (entry == StringDictionary::kNotFound) {
3419 // Key wasn't in dictionary. Deletion is a success.
3420 return;
3421 }
3422 // Key was in the dictionary. Remove it.
3423 dictionary->DeleteProperty(entry, JSReceiver::FORCE_DELETION);
3424 }
3425
3426
3427 bool JSObject::HasHiddenProperties() {
3428 LookupResult lookup;
3429 LocalLookupRealNamedProperty(GetHeap()->hidden_symbol(), &lookup);
3430 return lookup.IsFound();
3431 }
3432
3433
3434 MaybeObject* JSObject::GetHiddenPropertiesDictionary(bool create_if_absent) {
3435 ASSERT(!IsJSGlobalProxy());
3436 if (HasFastProperties()) {
3437 // If the object has fast properties, check whether the first slot
3438 // in the descriptor array matches the hidden symbol. Since the
3439 // hidden symbols hash code is zero (and no other string has hash
3440 // code zero) it will always occupy the first entry if present.
3441 DescriptorArray* descriptors = this->map()->instance_descriptors();
3442 if ((descriptors->number_of_descriptors() > 0) &&
3443 (descriptors->GetKey(0) == GetHeap()->hidden_symbol()) &&
3444 descriptors->IsProperty(0)) {
3445 ASSERT(descriptors->GetType(0) == FIELD);
3446 Object* hidden_store =
3447 this->FastPropertyAt(descriptors->GetFieldIndex(0));
3448 return StringDictionary::cast(hidden_store);
3449 }
3450 } else {
3451 PropertyAttributes attributes;
3452 // You can't install a getter on a property indexed by the hidden symbol,
3453 // so we can be sure that GetLocalPropertyPostInterceptor returns a real
3454 // object.
3455 Object* lookup =
3456 GetLocalPropertyPostInterceptor(this,
3457 GetHeap()->hidden_symbol(),
3458 &attributes)->ToObjectUnchecked();
3459 if (!lookup->IsUndefined()) {
3460 return StringDictionary::cast(lookup);
3461 }
3462 }
3463 if (!create_if_absent) return GetHeap()->undefined_value();
3464 const int kInitialSize = 5;
3465 MaybeObject* dict_alloc = StringDictionary::Allocate(kInitialSize);
3466 StringDictionary* dictionary;
3467 if (!dict_alloc->To<StringDictionary>(&dictionary)) return dict_alloc;
3468 MaybeObject* store_result =
3469 SetPropertyPostInterceptor(GetHeap()->hidden_symbol(),
3470 dictionary,
3471 DONT_ENUM,
3472 kNonStrictMode);
3473 if (store_result->IsFailure()) return store_result;
3474 return dictionary;
3475 }
3476
3477
3478 MaybeObject* JSObject::SetHiddenPropertiesDictionary(
3479 StringDictionary* dictionary) {
3480 ASSERT(!IsJSGlobalProxy());
3481 ASSERT(HasHiddenProperties());
3482 if (HasFastProperties()) {
3483 // If the object has fast properties, check whether the first slot
3484 // in the descriptor array matches the hidden symbol. Since the
3485 // hidden symbols hash code is zero (and no other string has hash
3486 // code zero) it will always occupy the first entry if present.
3487 DescriptorArray* descriptors = this->map()->instance_descriptors();
3488 if ((descriptors->number_of_descriptors() > 0) &&
3489 (descriptors->GetKey(0) == GetHeap()->hidden_symbol()) &&
3490 descriptors->IsProperty(0)) {
3491 ASSERT(descriptors->GetType(0) == FIELD);
3492 this->FastPropertyAtPut(descriptors->GetFieldIndex(0), dictionary);
3493 return this;
3494 }
3495 }
3496 MaybeObject* store_result =
3497 SetPropertyPostInterceptor(GetHeap()->hidden_symbol(),
3498 dictionary,
3499 DONT_ENUM,
3500 kNonStrictMode);
3501 if (store_result->IsFailure()) return store_result;
3502 return this;
3503 }
3504
3505
3088 MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name, 3506 MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name,
3089 DeleteMode mode) { 3507 DeleteMode mode) {
3090 // Check local property, ignore interceptor. 3508 // Check local property, ignore interceptor.
3091 LookupResult result; 3509 LookupResult result;
3092 LocalLookupRealNamedProperty(name, &result); 3510 LocalLookupRealNamedProperty(name, &result);
3093 if (!result.IsProperty()) return GetHeap()->true_value(); 3511 if (!result.IsProperty()) return GetHeap()->true_value();
3094 3512
3095 // Normalize object if needed. 3513 // Normalize object if needed.
3096 Object* obj; 3514 Object* obj;
3097 { MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); 3515 { MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
3194 mode = JSReceiver::FORCE_DELETION; 3612 mode = JSReceiver::FORCE_DELETION;
3195 } 3613 }
3196 3614
3197 return GetElementsAccessor()->Delete(this, index, mode); 3615 return GetElementsAccessor()->Delete(this, index, mode);
3198 } 3616 }
3199 3617
3200 3618
3201 MaybeObject* JSReceiver::DeleteProperty(String* name, DeleteMode mode) { 3619 MaybeObject* JSReceiver::DeleteProperty(String* name, DeleteMode mode) {
3202 if (IsJSProxy()) { 3620 if (IsJSProxy()) {
3203 return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode); 3621 return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode);
3204 } else {
3205 return JSObject::cast(this)->DeleteProperty(name, mode);
3206 } 3622 }
3623 return JSObject::cast(this)->DeleteProperty(name, mode);
3624 }
3625
3626
3627 MaybeObject* JSReceiver::DeleteElement(uint32_t index, DeleteMode mode) {
3628 if (IsJSProxy()) {
3629 return JSProxy::cast(this)->DeleteElementWithHandler(index, mode);
3630 }
3631 return JSObject::cast(this)->DeleteElement(index, mode);
3207 } 3632 }
3208 3633
3209 3634
3210 MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) { 3635 MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) {
3211 Isolate* isolate = GetIsolate(); 3636 Isolate* isolate = GetIsolate();
3212 // ECMA-262, 3rd, 8.6.2.5 3637 // ECMA-262, 3rd, 8.6.2.5
3213 ASSERT(name->IsString()); 3638 ASSERT(name->IsString());
3214 3639
3215 // Check access rights if needed. 3640 // Check access rights if needed.
3216 if (IsAccessCheckNeeded() && 3641 if (IsAccessCheckNeeded() &&
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
3260 } 3685 }
3261 // Make sure the properties are normalized before removing the entry. 3686 // Make sure the properties are normalized before removing the entry.
3262 return DeleteNormalizedProperty(name, mode); 3687 return DeleteNormalizedProperty(name, mode);
3263 } 3688 }
3264 } 3689 }
3265 3690
3266 3691
3267 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, 3692 bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
3268 ElementsKind kind, 3693 ElementsKind kind,
3269 Object* object) { 3694 Object* object) {
3270 ASSERT(kind == FAST_ELEMENTS || kind == DICTIONARY_ELEMENTS); 3695 ASSERT(kind == FAST_ELEMENTS ||
3696 kind == DICTIONARY_ELEMENTS);
3271 if (kind == FAST_ELEMENTS) { 3697 if (kind == FAST_ELEMENTS) {
3272 int length = IsJSArray() 3698 int length = IsJSArray()
3273 ? Smi::cast(JSArray::cast(this)->length())->value() 3699 ? Smi::cast(JSArray::cast(this)->length())->value()
3274 : elements->length(); 3700 : elements->length();
3275 for (int i = 0; i < length; ++i) { 3701 for (int i = 0; i < length; ++i) {
3276 Object* element = elements->get(i); 3702 Object* element = elements->get(i);
3277 if (!element->IsTheHole() && element == object) return true; 3703 if (!element->IsTheHole() && element == object) return true;
3278 } 3704 }
3279 } else { 3705 } else {
3280 Object* key = NumberDictionary::cast(elements)->SlowReverseLookup(object); 3706 Object* key = NumberDictionary::cast(elements)->SlowReverseLookup(object);
3281 if (!key->IsUndefined()) return true; 3707 if (!key->IsUndefined()) return true;
3282 } 3708 }
3283 return false; 3709 return false;
3284 } 3710 }
3285 3711
3286 3712
3287 // Check whether this object references another object. 3713 // Check whether this object references another object.
3288 bool JSObject::ReferencesObject(Object* obj) { 3714 bool JSObject::ReferencesObject(Object* obj) {
3289 Map* map_of_this = map(); 3715 Map* map_of_this = map();
3290 Heap* heap = map_of_this->heap(); 3716 Heap* heap = GetHeap();
3291 AssertNoAllocation no_alloc; 3717 AssertNoAllocation no_alloc;
3292 3718
3293 // Is the object the constructor for this object? 3719 // Is the object the constructor for this object?
3294 if (map_of_this->constructor() == obj) { 3720 if (map_of_this->constructor() == obj) {
3295 return true; 3721 return true;
3296 } 3722 }
3297 3723
3298 // Is the object the prototype for this object? 3724 // Is the object the prototype for this object?
3299 if (map_of_this->prototype() == obj) { 3725 if (map_of_this->prototype() == obj) {
3300 return true; 3726 return true;
(...skipping 14 matching lines...) Expand all
3315 case EXTERNAL_SHORT_ELEMENTS: 3741 case EXTERNAL_SHORT_ELEMENTS:
3316 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 3742 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3317 case EXTERNAL_INT_ELEMENTS: 3743 case EXTERNAL_INT_ELEMENTS:
3318 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 3744 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
3319 case EXTERNAL_FLOAT_ELEMENTS: 3745 case EXTERNAL_FLOAT_ELEMENTS:
3320 case EXTERNAL_DOUBLE_ELEMENTS: 3746 case EXTERNAL_DOUBLE_ELEMENTS:
3321 case FAST_DOUBLE_ELEMENTS: 3747 case FAST_DOUBLE_ELEMENTS:
3322 // Raw pixels and external arrays do not reference other 3748 // Raw pixels and external arrays do not reference other
3323 // objects. 3749 // objects.
3324 break; 3750 break;
3751 case FAST_SMI_ONLY_ELEMENTS:
3752 break;
3325 case FAST_ELEMENTS: 3753 case FAST_ELEMENTS:
3326 case DICTIONARY_ELEMENTS: { 3754 case DICTIONARY_ELEMENTS: {
3327 FixedArray* elements = FixedArray::cast(this->elements()); 3755 FixedArray* elements = FixedArray::cast(this->elements());
3328 if (ReferencesObjectFromElements(elements, kind, obj)) return true; 3756 if (ReferencesObjectFromElements(elements, kind, obj)) return true;
3329 break; 3757 break;
3330 } 3758 }
3331 case NON_STRICT_ARGUMENTS_ELEMENTS: { 3759 case NON_STRICT_ARGUMENTS_ELEMENTS: {
3332 FixedArray* parameter_map = FixedArray::cast(elements()); 3760 FixedArray* parameter_map = FixedArray::cast(elements());
3333 // Check the mapped parameters. 3761 // Check the mapped parameters.
3334 int length = parameter_map->length(); 3762 int length = parameter_map->length();
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
3502 for (int i = 0; i < descs->number_of_descriptors(); i++) { 3930 for (int i = 0; i < descs->number_of_descriptors(); i++) {
3503 if (name->Equals(descs->GetKey(i)) && descs->GetType(i) == CALLBACKS) { 3931 if (name->Equals(descs->GetKey(i)) && descs->GetType(i) == CALLBACKS) {
3504 return descs->GetCallbacks(i); 3932 return descs->GetCallbacks(i);
3505 } 3933 }
3506 } 3934 }
3507 return NULL; 3935 return NULL;
3508 } 3936 }
3509 3937
3510 3938
3511 void JSReceiver::LocalLookup(String* name, LookupResult* result) { 3939 void JSReceiver::LocalLookup(String* name, LookupResult* result) {
3512 if (IsJSProxy()) {
3513 result->HandlerResult();
3514 } else {
3515 JSObject::cast(this)->LocalLookup(name, result);
3516 }
3517 }
3518
3519
3520 void JSObject::LocalLookup(String* name, LookupResult* result) {
3521 ASSERT(name->IsString()); 3940 ASSERT(name->IsString());
3522 3941
3523 Heap* heap = GetHeap(); 3942 Heap* heap = GetHeap();
3524 3943
3525 if (IsJSGlobalProxy()) { 3944 if (IsJSGlobalProxy()) {
3526 Object* proto = GetPrototype(); 3945 Object* proto = GetPrototype();
3527 if (proto->IsNull()) return result->NotFound(); 3946 if (proto->IsNull()) return result->NotFound();
3528 ASSERT(proto->IsJSGlobalObject()); 3947 ASSERT(proto->IsJSGlobalObject());
3529 return JSObject::cast(proto)->LocalLookup(name, result); 3948 return JSReceiver::cast(proto)->LocalLookup(name, result);
3949 }
3950
3951 if (IsJSProxy()) {
3952 result->HandlerResult(JSProxy::cast(this));
3953 return;
3530 } 3954 }
3531 3955
3532 // Do not use inline caching if the object is a non-global object 3956 // Do not use inline caching if the object is a non-global object
3533 // that requires access checks. 3957 // that requires access checks.
3534 if (!IsJSGlobalProxy() && IsAccessCheckNeeded()) { 3958 if (IsAccessCheckNeeded()) {
3535 result->DisallowCaching(); 3959 result->DisallowCaching();
3536 } 3960 }
3537 3961
3962 JSObject* js_object = JSObject::cast(this);
3963
3538 // Check __proto__ before interceptor. 3964 // Check __proto__ before interceptor.
3539 if (name->Equals(heap->Proto_symbol()) && !IsJSContextExtensionObject()) { 3965 if (name->Equals(heap->Proto_symbol()) && !IsJSContextExtensionObject()) {
3540 result->ConstantResult(this); 3966 result->ConstantResult(js_object);
3541 return; 3967 return;
3542 } 3968 }
3543 3969
3544 // Check for lookup interceptor except when bootstrapping. 3970 // Check for lookup interceptor except when bootstrapping.
3545 if (HasNamedInterceptor() && !heap->isolate()->bootstrapper()->IsActive()) { 3971 if (js_object->HasNamedInterceptor() &&
3546 result->InterceptorResult(this); 3972 !heap->isolate()->bootstrapper()->IsActive()) {
3973 result->InterceptorResult(js_object);
3547 return; 3974 return;
3548 } 3975 }
3549 3976
3550 LocalLookupRealNamedProperty(name, result); 3977 js_object->LocalLookupRealNamedProperty(name, result);
3551 } 3978 }
3552 3979
3553 3980
3554 void JSReceiver::Lookup(String* name, LookupResult* result) { 3981 void JSReceiver::Lookup(String* name, LookupResult* result) {
3555 // Ecma-262 3rd 8.6.2.4 3982 // Ecma-262 3rd 8.6.2.4
3556 Heap* heap = GetHeap(); 3983 Heap* heap = GetHeap();
3557 for (Object* current = this; 3984 for (Object* current = this;
3558 current != heap->null_value(); 3985 current != heap->null_value();
3559 current = JSObject::cast(current)->GetPrototype()) { 3986 current = JSObject::cast(current)->GetPrototype()) {
3560 JSObject::cast(current)->LocalLookup(name, result); 3987 JSReceiver::cast(current)->LocalLookup(name, result);
3561 if (result->IsProperty()) return; 3988 if (result->IsProperty()) return;
3562 } 3989 }
3563 result->NotFound(); 3990 result->NotFound();
3564 } 3991 }
3565 3992
3566 3993
3567 // Search object and it's prototype chain for callback properties. 3994 // Search object and it's prototype chain for callback properties.
3568 void JSObject::LookupCallback(String* name, LookupResult* result) { 3995 void JSObject::LookupCallback(String* name, LookupResult* result) {
3569 Heap* heap = GetHeap(); 3996 Heap* heap = GetHeap();
3570 for (Object* current = this; 3997 for (Object* current = this;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
3607 4034
3608 if (!CanSetCallback(name)) { 4035 if (!CanSetCallback(name)) {
3609 return heap->undefined_value(); 4036 return heap->undefined_value();
3610 } 4037 }
3611 4038
3612 uint32_t index = 0; 4039 uint32_t index = 0;
3613 bool is_element = name->AsArrayIndex(&index); 4040 bool is_element = name->AsArrayIndex(&index);
3614 4041
3615 if (is_element) { 4042 if (is_element) {
3616 switch (GetElementsKind()) { 4043 switch (GetElementsKind()) {
4044 case FAST_SMI_ONLY_ELEMENTS:
3617 case FAST_ELEMENTS: 4045 case FAST_ELEMENTS:
3618 case FAST_DOUBLE_ELEMENTS: 4046 case FAST_DOUBLE_ELEMENTS:
3619 break; 4047 break;
3620 case EXTERNAL_PIXEL_ELEMENTS: 4048 case EXTERNAL_PIXEL_ELEMENTS:
3621 case EXTERNAL_BYTE_ELEMENTS: 4049 case EXTERNAL_BYTE_ELEMENTS:
3622 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 4050 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3623 case EXTERNAL_SHORT_ELEMENTS: 4051 case EXTERNAL_SHORT_ELEMENTS:
3624 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 4052 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3625 case EXTERNAL_INT_ELEMENTS: 4053 case EXTERNAL_INT_ELEMENTS:
3626 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 4054 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
3793 if (!maybe_ok->ToObject(&ok)) return maybe_ok; 4221 if (!maybe_ok->ToObject(&ok)) return maybe_ok;
3794 } 4222 }
3795 } 4223 }
3796 return result; 4224 return result;
3797 } 4225 }
3798 4226
3799 MaybeObject* JSObject::DefineAccessor(String* name, 4227 MaybeObject* JSObject::DefineAccessor(String* name,
3800 bool is_getter, 4228 bool is_getter,
3801 Object* fun, 4229 Object* fun,
3802 PropertyAttributes attributes) { 4230 PropertyAttributes attributes) {
3803 ASSERT(fun->IsJSFunction() || fun->IsUndefined()); 4231 ASSERT(fun->IsSpecFunction() || fun->IsUndefined());
3804 Isolate* isolate = GetIsolate(); 4232 Isolate* isolate = GetIsolate();
3805 // Check access rights if needed. 4233 // Check access rights if needed.
3806 if (IsAccessCheckNeeded() && 4234 if (IsAccessCheckNeeded() &&
3807 !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) { 4235 !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
3808 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); 4236 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
3809 return isolate->heap()->undefined_value(); 4237 return isolate->heap()->undefined_value();
3810 } 4238 }
3811 4239
3812 if (IsJSGlobalProxy()) { 4240 if (IsJSGlobalProxy()) {
3813 Object* proto = GetPrototype(); 4241 Object* proto = GetPrototype();
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
3856 } 4284 }
3857 4285
3858 uint32_t index = 0; 4286 uint32_t index = 0;
3859 bool is_element = name->AsArrayIndex(&index); 4287 bool is_element = name->AsArrayIndex(&index);
3860 4288
3861 if (is_element) { 4289 if (is_element) {
3862 if (IsJSArray()) return isolate->heap()->undefined_value(); 4290 if (IsJSArray()) return isolate->heap()->undefined_value();
3863 4291
3864 // Accessors overwrite previous callbacks (cf. with getters/setters). 4292 // Accessors overwrite previous callbacks (cf. with getters/setters).
3865 switch (GetElementsKind()) { 4293 switch (GetElementsKind()) {
4294 case FAST_SMI_ONLY_ELEMENTS:
3866 case FAST_ELEMENTS: 4295 case FAST_ELEMENTS:
3867 case FAST_DOUBLE_ELEMENTS: 4296 case FAST_DOUBLE_ELEMENTS:
3868 break; 4297 break;
3869 case EXTERNAL_PIXEL_ELEMENTS: 4298 case EXTERNAL_PIXEL_ELEMENTS:
3870 case EXTERNAL_BYTE_ELEMENTS: 4299 case EXTERNAL_BYTE_ELEMENTS:
3871 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 4300 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3872 case EXTERNAL_SHORT_ELEMENTS: 4301 case EXTERNAL_SHORT_ELEMENTS:
3873 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 4302 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3874 case EXTERNAL_INT_ELEMENTS: 4303 case EXTERNAL_INT_ELEMENTS:
3875 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 4304 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
4079 } 4508 }
4080 cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors)); 4509 cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors));
4081 return new_map; 4510 return new_map;
4082 } 4511 }
4083 4512
4084 4513
4085 MaybeObject* Map::UpdateCodeCache(String* name, Code* code) { 4514 MaybeObject* Map::UpdateCodeCache(String* name, Code* code) {
4086 // Allocate the code cache if not present. 4515 // Allocate the code cache if not present.
4087 if (code_cache()->IsFixedArray()) { 4516 if (code_cache()->IsFixedArray()) {
4088 Object* result; 4517 Object* result;
4089 { MaybeObject* maybe_result = code->heap()->AllocateCodeCache(); 4518 { MaybeObject* maybe_result = GetHeap()->AllocateCodeCache();
4090 if (!maybe_result->ToObject(&result)) return maybe_result; 4519 if (!maybe_result->ToObject(&result)) return maybe_result;
4091 } 4520 }
4092 set_code_cache(result); 4521 set_code_cache(result);
4093 } 4522 }
4094 4523
4095 // Update the code cache. 4524 // Update the code cache.
4096 return CodeCache::cast(code_cache())->Update(name, code); 4525 return CodeCache::cast(code_cache())->Update(name, code);
4097 } 4526 }
4098 4527
4099 4528
(...skipping 21 matching lines...) Expand all
4121 // RemoveFromCodeCache so the code cache must be there. 4550 // RemoveFromCodeCache so the code cache must be there.
4122 ASSERT(!code_cache()->IsFixedArray()); 4551 ASSERT(!code_cache()->IsFixedArray());
4123 CodeCache::cast(code_cache())->RemoveByIndex(name, code, index); 4552 CodeCache::cast(code_cache())->RemoveByIndex(name, code, index);
4124 } 4553 }
4125 4554
4126 4555
4127 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) { 4556 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) {
4128 // Traverse the transition tree without using a stack. We do this by 4557 // Traverse the transition tree without using a stack. We do this by
4129 // reversing the pointers in the maps and descriptor arrays. 4558 // reversing the pointers in the maps and descriptor arrays.
4130 Map* current = this; 4559 Map* current = this;
4131 Map* meta_map = heap()->meta_map(); 4560 Map* meta_map = GetHeap()->meta_map();
4132 Object** map_or_index_field = NULL; 4561 Object** map_or_index_field = NULL;
4133 while (current != meta_map) { 4562 while (current != meta_map) {
4134 DescriptorArray* d = reinterpret_cast<DescriptorArray*>( 4563 DescriptorArray* d = reinterpret_cast<DescriptorArray*>(
4135 *RawField(current, Map::kInstanceDescriptorsOrBitField3Offset)); 4564 *RawField(current, Map::kInstanceDescriptorsOrBitField3Offset));
4136 if (!d->IsEmpty()) { 4565 if (!d->IsEmpty()) {
4137 FixedArray* contents = reinterpret_cast<FixedArray*>( 4566 FixedArray* contents = reinterpret_cast<FixedArray*>(
4138 d->get(DescriptorArray::kContentArrayIndex)); 4567 d->get(DescriptorArray::kContentArrayIndex));
4139 map_or_index_field = RawField(contents, HeapObject::kMapOffset); 4568 map_or_index_field = RawField(contents, HeapObject::kMapOffset);
4140 Object* map_or_index = *map_or_index_field; 4569 Object* map_or_index = *map_or_index_field;
4141 bool map_done = true; // Controls a nested continue statement. 4570 bool map_done = true; // Controls a nested continue statement.
4142 for (int i = map_or_index->IsSmi() ? Smi::cast(map_or_index)->value() : 0; 4571 for (int i = map_or_index->IsSmi() ? Smi::cast(map_or_index)->value() : 0;
4143 i < contents->length(); 4572 i < contents->length();
4144 i += 2) { 4573 i += 2) {
4145 PropertyDetails details(Smi::cast(contents->get(i + 1))); 4574 PropertyDetails details(Smi::cast(contents->get(i + 1)));
4146 if (details.IsTransition()) { 4575 if (details.IsTransition()) {
4147 // Found a map in the transition array. We record our progress in 4576 // Found a map in the transition array. We record our progress in
4148 // the transition array by recording the current map in the map field 4577 // the transition array by recording the current map in the map field
4149 // of the next map and recording the index in the transition array in 4578 // of the next map and recording the index in the transition array in
4150 // the map field of the array. 4579 // the map field of the array.
4151 Map* next = Map::cast(contents->get(i)); 4580 Map* next = Map::cast(contents->get(i));
4152 next->set_map(current); 4581 next->set_map_unsafe(current);
4153 *map_or_index_field = Smi::FromInt(i + 2); 4582 *map_or_index_field = Smi::FromInt(i + 2);
4154 current = next; 4583 current = next;
4155 map_done = false; 4584 map_done = false;
4156 break; 4585 break;
4157 } 4586 }
4158 } 4587 }
4159 if (!map_done) continue; 4588 if (!map_done) continue;
4160 } else { 4589 } else {
4161 map_or_index_field = NULL; 4590 map_or_index_field = NULL;
4162 } 4591 }
4163 // That was the regular transitions, now for the prototype transitions. 4592 // That was the regular transitions, now for the prototype transitions.
4164 FixedArray* prototype_transitions = 4593 FixedArray* prototype_transitions =
4165 current->unchecked_prototype_transitions(); 4594 current->unchecked_prototype_transitions();
4166 Object** proto_map_or_index_field = 4595 Object** proto_map_or_index_field =
4167 RawField(prototype_transitions, HeapObject::kMapOffset); 4596 RawField(prototype_transitions, HeapObject::kMapOffset);
4168 Object* map_or_index = *proto_map_or_index_field; 4597 Object* map_or_index = *proto_map_or_index_field;
4169 const int start = kProtoTransitionHeaderSize + kProtoTransitionMapOffset; 4598 const int start = kProtoTransitionHeaderSize + kProtoTransitionMapOffset;
4170 int i = map_or_index->IsSmi() ? Smi::cast(map_or_index)->value() : start; 4599 int i = map_or_index->IsSmi() ? Smi::cast(map_or_index)->value() : start;
4171 if (i < prototype_transitions->length()) { 4600 if (i < prototype_transitions->length()) {
4172 // Found a map in the prototype transition array. Record progress in 4601 // Found a map in the prototype transition array. Record progress in
4173 // an analogous way to the regular transitions array above. 4602 // an analogous way to the regular transitions array above.
4174 Object* perhaps_map = prototype_transitions->get(i); 4603 Object* perhaps_map = prototype_transitions->get(i);
4175 if (perhaps_map->IsMap()) { 4604 if (perhaps_map->IsMap()) {
4176 Map* next = Map::cast(perhaps_map); 4605 Map* next = Map::cast(perhaps_map);
4177 next->set_map(current); 4606 next->set_map_unsafe(current);
4178 *proto_map_or_index_field = 4607 *proto_map_or_index_field =
4179 Smi::FromInt(i + kProtoTransitionElementsPerEntry); 4608 Smi::FromInt(i + kProtoTransitionElementsPerEntry);
4180 current = next; 4609 current = next;
4181 continue; 4610 continue;
4182 } 4611 }
4183 } 4612 }
4184 *proto_map_or_index_field = heap()->fixed_array_map(); 4613 *proto_map_or_index_field = GetHeap()->fixed_array_map();
4185 if (map_or_index_field != NULL) { 4614 if (map_or_index_field != NULL) {
4186 *map_or_index_field = heap()->fixed_array_map(); 4615 *map_or_index_field = GetHeap()->fixed_array_map();
4187 } 4616 }
4188 4617
4189 // The callback expects a map to have a real map as its map, so we save 4618 // The callback expects a map to have a real map as its map, so we save
4190 // the map field, which is being used to track the traversal and put the 4619 // the map field, which is being used to track the traversal and put the
4191 // correct map (the meta_map) in place while we do the callback. 4620 // correct map (the meta_map) in place while we do the callback.
4192 Map* prev = current->map(); 4621 Map* prev = current->map();
4193 current->set_map(meta_map); 4622 current->set_map_unsafe(meta_map);
4194 callback(current, data); 4623 callback(current, data);
4195 current = prev; 4624 current = prev;
4196 } 4625 }
4197 } 4626 }
4198 4627
4199 4628
4200 MaybeObject* CodeCache::Update(String* name, Code* code) { 4629 MaybeObject* CodeCache::Update(String* name, Code* code) {
4201 // The number of monomorphic stubs for normal load/store/call IC's can grow to 4630 // The number of monomorphic stubs for normal load/store/call IC's can grow to
4202 // a large number and therefore they need to go into a hash table. They are 4631 // a large number and therefore they need to go into a hash table. They are
4203 // used to load global properties from cells. 4632 // used to load global properties from cells.
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
4399 uint32_t HashForObject(Object* obj) { 4828 uint32_t HashForObject(Object* obj) {
4400 FixedArray* pair = FixedArray::cast(obj); 4829 FixedArray* pair = FixedArray::cast(obj);
4401 String* name = String::cast(pair->get(0)); 4830 String* name = String::cast(pair->get(0));
4402 Code* code = Code::cast(pair->get(1)); 4831 Code* code = Code::cast(pair->get(1));
4403 return NameFlagsHashHelper(name, code->flags()); 4832 return NameFlagsHashHelper(name, code->flags());
4404 } 4833 }
4405 4834
4406 MUST_USE_RESULT MaybeObject* AsObject() { 4835 MUST_USE_RESULT MaybeObject* AsObject() {
4407 ASSERT(code_ != NULL); 4836 ASSERT(code_ != NULL);
4408 Object* obj; 4837 Object* obj;
4409 { MaybeObject* maybe_obj = code_->heap()->AllocateFixedArray(2); 4838 { MaybeObject* maybe_obj = code_->GetHeap()->AllocateFixedArray(2);
4410 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 4839 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
4411 } 4840 }
4412 FixedArray* pair = FixedArray::cast(obj); 4841 FixedArray* pair = FixedArray::cast(obj);
4413 pair->set(0, name_); 4842 pair->set(0, name_);
4414 pair->set(1, code_); 4843 pair->set(1, code_);
4415 return pair; 4844 return pair;
4416 } 4845 }
4417 4846
4418 private: 4847 private:
4419 String* name_; 4848 String* name_;
(...skipping 1568 matching lines...) Expand 10 before | Expand all | Expand 10 after
5988 return CompareStringContentsPartial(isolate, 6417 return CompareStringContentsPartial(isolate,
5989 isolate->objects_string_compare_buffer_a(), rhs); 6418 isolate->objects_string_compare_buffer_a(), rhs);
5990 } 6419 }
5991 } 6420 }
5992 6421
5993 6422
5994 bool String::MarkAsUndetectable() { 6423 bool String::MarkAsUndetectable() {
5995 if (StringShape(this).IsSymbol()) return false; 6424 if (StringShape(this).IsSymbol()) return false;
5996 6425
5997 Map* map = this->map(); 6426 Map* map = this->map();
5998 Heap* heap = map->heap(); 6427 Heap* heap = GetHeap();
5999 if (map == heap->string_map()) { 6428 if (map == heap->string_map()) {
6000 this->set_map(heap->undetectable_string_map()); 6429 this->set_map(heap->undetectable_string_map());
6001 return true; 6430 return true;
6002 } else if (map == heap->ascii_string_map()) { 6431 } else if (map == heap->ascii_string_map()) {
6003 this->set_map(heap->undetectable_ascii_string_map()); 6432 this->set_map(heap->undetectable_ascii_string_map());
6004 return true; 6433 return true;
6005 } 6434 }
6006 // Rest cannot be marked as undetectable 6435 // Rest cannot be marked as undetectable
6007 return false; 6436 return false;
6008 } 6437 }
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
6191 6620
6192 6621
6193 void String::PrintOn(FILE* file) { 6622 void String::PrintOn(FILE* file) {
6194 int length = this->length(); 6623 int length = this->length();
6195 for (int i = 0; i < length; i++) { 6624 for (int i = 0; i < length; i++) {
6196 fprintf(file, "%c", Get(i)); 6625 fprintf(file, "%c", Get(i));
6197 } 6626 }
6198 } 6627 }
6199 6628
6200 6629
6630 void Map::CreateOneBackPointer(Map* target) {
6631 #ifdef DEBUG
6632 // Verify target.
6633 Object* source_prototype = prototype();
6634 Object* target_prototype = target->prototype();
6635 ASSERT(source_prototype->IsJSReceiver() ||
6636 source_prototype->IsMap() ||
6637 source_prototype->IsNull());
6638 ASSERT(target_prototype->IsJSReceiver() ||
6639 target_prototype->IsNull());
6640 ASSERT(source_prototype->IsMap() ||
6641 source_prototype == target_prototype);
6642 #endif
6643 // Point target back to source. set_prototype() will not let us set
6644 // the prototype to a map, as we do here.
6645 *RawField(target, kPrototypeOffset) = this;
6646 }
6647
6648
6201 void Map::CreateBackPointers() { 6649 void Map::CreateBackPointers() {
6202 DescriptorArray* descriptors = instance_descriptors(); 6650 DescriptorArray* descriptors = instance_descriptors();
6203 for (int i = 0; i < descriptors->number_of_descriptors(); i++) { 6651 for (int i = 0; i < descriptors->number_of_descriptors(); i++) {
6204 if (descriptors->GetType(i) == MAP_TRANSITION || 6652 if (descriptors->GetType(i) == MAP_TRANSITION ||
6205 descriptors->GetType(i) == ELEMENTS_TRANSITION || 6653 descriptors->GetType(i) == ELEMENTS_TRANSITION ||
6206 descriptors->GetType(i) == CONSTANT_TRANSITION) { 6654 descriptors->GetType(i) == CONSTANT_TRANSITION) {
6207 // Get target. 6655 Object* object = reinterpret_cast<Object*>(descriptors->GetValue(i));
6208 Map* target = Map::cast(descriptors->GetValue(i)); 6656 if (object->IsMap()) {
6209 #ifdef DEBUG 6657 CreateOneBackPointer(reinterpret_cast<Map*>(object));
6210 // Verify target. 6658 } else {
6211 Object* source_prototype = prototype(); 6659 ASSERT(object->IsFixedArray());
6212 Object* target_prototype = target->prototype(); 6660 ASSERT(descriptors->GetType(i) == ELEMENTS_TRANSITION);
6213 ASSERT(source_prototype->IsJSObject() || 6661 FixedArray* array = reinterpret_cast<FixedArray*>(object);
6214 source_prototype->IsMap() || 6662 for (int i = 0; i < array->length(); ++i) {
6215 source_prototype->IsNull()); 6663 Map* target = reinterpret_cast<Map*>(array->get(i));
6216 ASSERT(target_prototype->IsJSObject() || 6664 if (!target->IsUndefined()) {
6217 target_prototype->IsNull()); 6665 CreateOneBackPointer(target);
6218 ASSERT(source_prototype->IsMap() || 6666 }
6219 source_prototype == target_prototype); 6667 }
6220 #endif 6668 }
6221 // Point target back to source. set_prototype() will not let us set
6222 // the prototype to a map, as we do here.
6223 *RawField(target, kPrototypeOffset) = this;
6224 } 6669 }
6225 } 6670 }
6226 } 6671 }
6227 6672
6228 6673
6229 void Map::ClearNonLiveTransitions(Heap* heap, Object* real_prototype) { 6674 void Map::ClearNonLiveTransitions(Heap* heap, Object* real_prototype) {
6230 // Live DescriptorArray objects will be marked, so we must use 6675 // Live DescriptorArray objects will be marked, so we must use
6231 // low-level accessors to get and modify their data. 6676 // low-level accessors to get and modify their data.
6232 DescriptorArray* d = reinterpret_cast<DescriptorArray*>( 6677 DescriptorArray* d = reinterpret_cast<DescriptorArray*>(
6233 *RawField(this, Map::kInstanceDescriptorsOrBitField3Offset)); 6678 *RawField(this, Map::kInstanceDescriptorsOrBitField3Offset));
6234 if (d->IsEmpty()) return; 6679 if (d->IsEmpty()) return;
6235 Smi* NullDescriptorDetails = 6680 Smi* NullDescriptorDetails =
6236 PropertyDetails(NONE, NULL_DESCRIPTOR).AsSmi(); 6681 PropertyDetails(NONE, NULL_DESCRIPTOR).AsSmi();
6237 FixedArray* contents = reinterpret_cast<FixedArray*>( 6682 FixedArray* contents = reinterpret_cast<FixedArray*>(
6238 d->get(DescriptorArray::kContentArrayIndex)); 6683 d->get(DescriptorArray::kContentArrayIndex));
6239 ASSERT(contents->length() >= 2); 6684 ASSERT(contents->length() >= 2);
6240 for (int i = 0; i < contents->length(); i += 2) { 6685 for (int i = 0; i < contents->length(); i += 2) {
6241 // If the pair (value, details) is a map transition, 6686 // If the pair (value, details) is a map transition,
6242 // check if the target is live. If not, null the descriptor. 6687 // check if the target is live. If not, null the descriptor.
6243 // Also drop the back pointer for that map transition, so that this 6688 // Also drop the back pointer for that map transition, so that this
6244 // map is not reached again by following a back pointer from a 6689 // map is not reached again by following a back pointer from a
6245 // non-live object. 6690 // non-live object.
6246 PropertyDetails details(Smi::cast(contents->get(i + 1))); 6691 PropertyDetails details(Smi::cast(contents->get(i + 1)));
6247 if (details.type() == MAP_TRANSITION || 6692 if (details.type() == MAP_TRANSITION ||
6248 details.type() == ELEMENTS_TRANSITION || 6693 details.type() == ELEMENTS_TRANSITION ||
6249 details.type() == CONSTANT_TRANSITION) { 6694 details.type() == CONSTANT_TRANSITION) {
6250 Map* target = reinterpret_cast<Map*>(contents->get(i)); 6695 Object* object = reinterpret_cast<Object*>(contents->get(i));
6251 ASSERT(target->IsHeapObject()); 6696 if (object->IsMap()) {
6252 if (!target->IsMarked()) { 6697 Map* target = reinterpret_cast<Map*>(object);
6253 ASSERT(target->IsMap()); 6698 ASSERT(target->IsHeapObject());
6254 contents->set_unchecked(i + 1, NullDescriptorDetails); 6699 MarkBit map_mark = Marking::MarkBitFrom(target);
6255 contents->set_null_unchecked(heap, i); 6700 if (!map_mark.Get()) {
6256 ASSERT(target->prototype() == this || 6701 ASSERT(target->IsMap());
6257 target->prototype() == real_prototype); 6702 contents->set_unchecked(i + 1, NullDescriptorDetails);
6258 // Getter prototype() is read-only, set_prototype() has side effects. 6703 contents->set_null_unchecked(heap, i);
6259 *RawField(target, Map::kPrototypeOffset) = real_prototype; 6704 ASSERT(target->prototype() == this ||
6705 target->prototype() == real_prototype);
6706 // Getter prototype() is read-only, set_prototype() has side effects.
6707 *RawField(target, Map::kPrototypeOffset) = real_prototype;
6708 }
6709 } else {
6710 ASSERT(object->IsFixedArray());
6711 ASSERT(details.type() == ELEMENTS_TRANSITION);
6712 FixedArray* array = reinterpret_cast<FixedArray*>(contents->get(i));
6713 bool reachable_map_found = false;
6714 for (int j = 0; j < array->length(); ++j) {
6715 Map* target = reinterpret_cast<Map*>(array->get(j));
6716 ASSERT(target->IsHeapObject());
6717 MarkBit map_mark = Marking::MarkBitFrom(target);
6718 if (!map_mark.Get()) {
6719 ASSERT(target->IsMap());
6720 array->set_undefined(j);
6721 ASSERT(target->prototype() == this ||
6722 target->prototype() == real_prototype);
6723 // Getter prototype() is read-only, set_prototype() has side
6724 // effects.
6725 *RawField(target, Map::kPrototypeOffset) = real_prototype;
6726 } else {
6727 reachable_map_found = true;
6728 }
6729 }
6730 // If no map was found, make sure the FixedArray also gets collected.
6731 if (!reachable_map_found) {
6732 contents->set_unchecked(i + 1, NullDescriptorDetails);
6733 contents->set_null_unchecked(heap, i);
6734 }
6260 } 6735 }
6261 } 6736 }
6262 } 6737 }
6263 } 6738 }
6264 6739
6265 6740
6266 int Map::Hash() { 6741 int Map::Hash() {
6267 // For performance reasons we only hash the 3 most variable fields of a map: 6742 // For performance reasons we only hash the 3 most variable fields of a map:
6268 // constructor, prototype and bit_field2. 6743 // constructor, prototype and bit_field2.
6269 6744
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
6355 // See ECMA-262 13.2.2. 6830 // See ECMA-262 13.2.2.
6356 if (!value->IsJSObject()) { 6831 if (!value->IsJSObject()) {
6357 // Copy the map so this does not affect unrelated functions. 6832 // Copy the map so this does not affect unrelated functions.
6358 // Remove map transitions because they point to maps with a 6833 // Remove map transitions because they point to maps with a
6359 // different prototype. 6834 // different prototype.
6360 Object* new_object; 6835 Object* new_object;
6361 { MaybeObject* maybe_new_map = map()->CopyDropTransitions(); 6836 { MaybeObject* maybe_new_map = map()->CopyDropTransitions();
6362 if (!maybe_new_map->ToObject(&new_object)) return maybe_new_map; 6837 if (!maybe_new_map->ToObject(&new_object)) return maybe_new_map;
6363 } 6838 }
6364 Map* new_map = Map::cast(new_object); 6839 Map* new_map = Map::cast(new_object);
6365 Heap* heap = new_map->heap(); 6840 Heap* heap = new_map->GetHeap();
6366 set_map(new_map); 6841 set_map(new_map);
6367 new_map->set_constructor(value); 6842 new_map->set_constructor(value);
6368 new_map->set_non_instance_prototype(true); 6843 new_map->set_non_instance_prototype(true);
6369 construct_prototype = 6844 construct_prototype =
6370 heap->isolate()->context()->global_context()-> 6845 heap->isolate()->context()->global_context()->
6371 initial_object_prototype(); 6846 initial_object_prototype();
6372 } else { 6847 } else {
6373 map()->set_non_instance_prototype(false); 6848 map()->set_non_instance_prototype(false);
6374 } 6849 }
6375 6850
(...skipping 10 matching lines...) Expand all
6386 if (map() == no_prototype_map) { 6861 if (map() == no_prototype_map) {
6387 // Be idempotent. 6862 // Be idempotent.
6388 return this; 6863 return this;
6389 } 6864 }
6390 6865
6391 ASSERT(!shared()->strict_mode() || 6866 ASSERT(!shared()->strict_mode() ||
6392 map() == global_context->strict_mode_function_map()); 6867 map() == global_context->strict_mode_function_map());
6393 ASSERT(shared()->strict_mode() || map() == global_context->function_map()); 6868 ASSERT(shared()->strict_mode() || map() == global_context->function_map());
6394 6869
6395 set_map(no_prototype_map); 6870 set_map(no_prototype_map);
6396 set_prototype_or_initial_map(no_prototype_map->heap()->the_hole_value()); 6871 set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
6397 return this; 6872 return this;
6398 } 6873 }
6399 6874
6400 6875
6401 Object* JSFunction::SetInstanceClassName(String* name) { 6876 Object* JSFunction::SetInstanceClassName(String* name) {
6402 shared()->set_instance_class_name(name); 6877 shared()->set_instance_class_name(name);
6403 return this; 6878 return this;
6404 } 6879 }
6405 6880
6406 6881
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after
6694 if (Serializer::enabled()) return; 7169 if (Serializer::enabled()) return;
6695 7170
6696 if (map->unused_property_fields() == 0) return; 7171 if (map->unused_property_fields() == 0) return;
6697 7172
6698 // Nonzero counter is a leftover from the previous attempt interrupted 7173 // Nonzero counter is a leftover from the previous attempt interrupted
6699 // by GC, keep it. 7174 // by GC, keep it.
6700 if (construction_count() == 0) { 7175 if (construction_count() == 0) {
6701 set_construction_count(kGenerousAllocationCount); 7176 set_construction_count(kGenerousAllocationCount);
6702 } 7177 }
6703 set_initial_map(map); 7178 set_initial_map(map);
6704 Builtins* builtins = map->heap()->isolate()->builtins(); 7179 Builtins* builtins = map->GetHeap()->isolate()->builtins();
6705 ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubGeneric), 7180 ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubGeneric),
6706 construct_stub()); 7181 construct_stub());
6707 set_construct_stub(builtins->builtin(Builtins::kJSConstructStubCountdown)); 7182 set_construct_stub(builtins->builtin(Builtins::kJSConstructStubCountdown));
6708 } 7183 }
6709 7184
6710 7185
6711 // Called from GC, hence reinterpret_cast and unchecked accessors. 7186 // Called from GC, hence reinterpret_cast and unchecked accessors.
6712 void SharedFunctionInfo::DetachInitialMap() { 7187 void SharedFunctionInfo::DetachInitialMap() {
6713 Map* map = reinterpret_cast<Map*>(initial_map()); 7188 Map* map = reinterpret_cast<Map*>(initial_map());
6714 7189
6715 // Make the map remember to restore the link if it survives the GC. 7190 // Make the map remember to restore the link if it survives the GC.
6716 map->set_bit_field2( 7191 map->set_bit_field2(
6717 map->bit_field2() | (1 << Map::kAttachedToSharedFunctionInfo)); 7192 map->bit_field2() | (1 << Map::kAttachedToSharedFunctionInfo));
6718 7193
6719 // Undo state changes made by StartInobjectTracking (except the 7194 // Undo state changes made by StartInobjectTracking (except the
6720 // construction_count). This way if the initial map does not survive the GC 7195 // construction_count). This way if the initial map does not survive the GC
6721 // then StartInobjectTracking will be called again the next time the 7196 // then StartInobjectTracking will be called again the next time the
6722 // constructor is called. The countdown will continue and (possibly after 7197 // constructor is called. The countdown will continue and (possibly after
6723 // several more GCs) CompleteInobjectSlackTracking will eventually be called. 7198 // several more GCs) CompleteInobjectSlackTracking will eventually be called.
6724 set_initial_map(map->heap()->raw_unchecked_undefined_value()); 7199 Heap* heap = map->GetHeap();
6725 Builtins* builtins = map->heap()->isolate()->builtins(); 7200 set_initial_map(heap->raw_unchecked_undefined_value());
7201 Builtins* builtins = heap->isolate()->builtins();
6726 ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown), 7202 ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown),
6727 *RawField(this, kConstructStubOffset)); 7203 *RawField(this, kConstructStubOffset));
6728 set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric)); 7204 set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric));
6729 // It is safe to clear the flag: it will be set again if the map is live. 7205 // It is safe to clear the flag: it will be set again if the map is live.
6730 set_live_objects_may_exist(false); 7206 set_live_objects_may_exist(false);
6731 } 7207 }
6732 7208
6733 7209
6734 // Called from GC, hence reinterpret_cast and unchecked accessors. 7210 // Called from GC, hence reinterpret_cast and unchecked accessors.
6735 void SharedFunctionInfo::AttachInitialMap(Map* map) { 7211 void SharedFunctionInfo::AttachInitialMap(Map* map) {
6736 map->set_bit_field2( 7212 map->set_bit_field2(
6737 map->bit_field2() & ~(1 << Map::kAttachedToSharedFunctionInfo)); 7213 map->bit_field2() & ~(1 << Map::kAttachedToSharedFunctionInfo));
6738 7214
6739 // Resume inobject slack tracking. 7215 // Resume inobject slack tracking.
6740 set_initial_map(map); 7216 set_initial_map(map);
6741 Builtins* builtins = map->heap()->isolate()->builtins(); 7217 Builtins* builtins = map->GetHeap()->isolate()->builtins();
6742 ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubGeneric), 7218 ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubGeneric),
6743 *RawField(this, kConstructStubOffset)); 7219 *RawField(this, kConstructStubOffset));
6744 set_construct_stub(builtins->builtin(Builtins::kJSConstructStubCountdown)); 7220 set_construct_stub(builtins->builtin(Builtins::kJSConstructStubCountdown));
6745 // The map survived the gc, so there may be objects referencing it. 7221 // The map survived the gc, so there may be objects referencing it.
6746 set_live_objects_may_exist(true); 7222 set_live_objects_may_exist(true);
6747 } 7223 }
6748 7224
6749 7225
6750 static void GetMinInobjectSlack(Map* map, void* data) { 7226 static void GetMinInobjectSlack(Map* map, void* data) {
6751 int slack = map->unused_property_fields(); 7227 int slack = map->unused_property_fields();
(...skipping 11 matching lines...) Expand all
6763 7239
6764 // Visitor id might depend on the instance size, recalculate it. 7240 // Visitor id might depend on the instance size, recalculate it.
6765 map->set_visitor_id(StaticVisitorBase::GetVisitorId(map)); 7241 map->set_visitor_id(StaticVisitorBase::GetVisitorId(map));
6766 } 7242 }
6767 7243
6768 7244
6769 void SharedFunctionInfo::CompleteInobjectSlackTracking() { 7245 void SharedFunctionInfo::CompleteInobjectSlackTracking() {
6770 ASSERT(live_objects_may_exist() && IsInobjectSlackTrackingInProgress()); 7246 ASSERT(live_objects_may_exist() && IsInobjectSlackTrackingInProgress());
6771 Map* map = Map::cast(initial_map()); 7247 Map* map = Map::cast(initial_map());
6772 7248
6773 Heap* heap = map->heap(); 7249 Heap* heap = map->GetHeap();
6774 set_initial_map(heap->undefined_value()); 7250 set_initial_map(heap->undefined_value());
6775 Builtins* builtins = heap->isolate()->builtins(); 7251 Builtins* builtins = heap->isolate()->builtins();
6776 ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown), 7252 ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown),
6777 construct_stub()); 7253 construct_stub());
6778 set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric)); 7254 set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric));
6779 7255
6780 int slack = map->unused_property_fields(); 7256 int slack = map->unused_property_fields();
6781 map->TraverseTransitionTree(&GetMinInobjectSlack, &slack); 7257 map->TraverseTransitionTree(&GetMinInobjectSlack, &slack);
6782 if (slack != 0) { 7258 if (slack != 0) {
6783 // Resize the initial map and all maps in its transition tree. 7259 // Resize the initial map and all maps in its transition tree.
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
6826 (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && 7302 (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
6827 rinfo->IsPatchedDebugBreakSlotSequence())); 7303 rinfo->IsPatchedDebugBreakSlotSequence()));
6828 Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address()); 7304 Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
6829 Object* old_target = target; 7305 Object* old_target = target;
6830 VisitPointer(&target); 7306 VisitPointer(&target);
6831 CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target. 7307 CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target.
6832 } 7308 }
6833 7309
6834 7310
6835 void Code::InvalidateRelocation() { 7311 void Code::InvalidateRelocation() {
6836 set_relocation_info(heap()->empty_byte_array()); 7312 set_relocation_info(GetHeap()->empty_byte_array());
6837 } 7313 }
6838 7314
6839 7315
6840 void Code::Relocate(intptr_t delta) { 7316 void Code::Relocate(intptr_t delta) {
6841 for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) { 7317 for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
6842 it.rinfo()->apply(delta); 7318 it.rinfo()->apply(delta);
6843 } 7319 }
6844 CPU::FlushICache(instruction_start(), instruction_size()); 7320 CPU::FlushICache(instruction_start(), instruction_size());
6845 } 7321 }
6846 7322
(...skipping 13 matching lines...) Expand all
6860 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | 7336 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
6861 RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) | 7337 RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) |
6862 RelocInfo::kApplyMask; 7338 RelocInfo::kApplyMask;
6863 Assembler* origin = desc.origin; // Needed to find target_object on X64. 7339 Assembler* origin = desc.origin; // Needed to find target_object on X64.
6864 for (RelocIterator it(this, mode_mask); !it.done(); it.next()) { 7340 for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
6865 RelocInfo::Mode mode = it.rinfo()->rmode(); 7341 RelocInfo::Mode mode = it.rinfo()->rmode();
6866 if (mode == RelocInfo::EMBEDDED_OBJECT) { 7342 if (mode == RelocInfo::EMBEDDED_OBJECT) {
6867 Handle<Object> p = it.rinfo()->target_object_handle(origin); 7343 Handle<Object> p = it.rinfo()->target_object_handle(origin);
6868 it.rinfo()->set_target_object(*p); 7344 it.rinfo()->set_target_object(*p);
6869 } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) { 7345 } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
6870 Handle<JSGlobalPropertyCell> cell = it.rinfo()->target_cell_handle(); 7346 Handle<JSGlobalPropertyCell> cell = it.rinfo()->target_cell_handle();
6871 it.rinfo()->set_target_cell(*cell); 7347 it.rinfo()->set_target_cell(*cell);
6872 } else if (RelocInfo::IsCodeTarget(mode)) { 7348 } else if (RelocInfo::IsCodeTarget(mode)) {
6873 // rewrite code handles in inline cache targets to direct 7349 // rewrite code handles in inline cache targets to direct
6874 // pointers to the first instruction in the code object 7350 // pointers to the first instruction in the code object
6875 Handle<Object> p = it.rinfo()->target_object_handle(origin); 7351 Handle<Object> p = it.rinfo()->target_object_handle(origin);
6876 Code* code = Code::cast(*p); 7352 Code* code = Code::cast(*p);
6877 it.rinfo()->set_target_address(code->instruction_start()); 7353 it.rinfo()->set_target_address(code->instruction_start());
6878 } else { 7354 } else {
6879 it.rinfo()->apply(delta); 7355 it.rinfo()->apply(delta);
6880 } 7356 }
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
7263 for (int i = 0; i < source->Capacity(); ++i) { 7739 for (int i = 0; i < source->Capacity(); ++i) {
7264 Object* key = source->KeyAt(i); 7740 Object* key = source->KeyAt(i);
7265 if (key->IsNumber()) { 7741 if (key->IsNumber()) {
7266 uint32_t entry = static_cast<uint32_t>(key->Number()); 7742 uint32_t entry = static_cast<uint32_t>(key->Number());
7267 destination->set(entry, source->ValueAt(i), mode); 7743 destination->set(entry, source->ValueAt(i), mode);
7268 } 7744 }
7269 } 7745 }
7270 } 7746 }
7271 7747
7272 7748
7273 MaybeObject* JSObject::SetFastElementsCapacityAndLength(int capacity, 7749 MaybeObject* JSObject::SetFastElementsCapacityAndLength(
7274 int length) { 7750 int capacity,
7751 int length,
7752 SetFastElementsCapacityMode set_capacity_mode) {
7275 Heap* heap = GetHeap(); 7753 Heap* heap = GetHeap();
7276 // We should never end in here with a pixel or external array. 7754 // We should never end in here with a pixel or external array.
7277 ASSERT(!HasExternalArrayElements()); 7755 ASSERT(!HasExternalArrayElements());
7278 7756
7279 // Allocate a new fast elements backing store. 7757 // Allocate a new fast elements backing store.
7280 FixedArray* new_elements = NULL; 7758 FixedArray* new_elements = NULL;
7281 { Object* object; 7759 { Object* object;
7282 MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity); 7760 MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity);
7283 if (!maybe->ToObject(&object)) return maybe; 7761 if (!maybe->ToObject(&object)) return maybe;
7284 new_elements = FixedArray::cast(object); 7762 new_elements = FixedArray::cast(object);
7285 } 7763 }
7286 7764
7287 // Find the new map to use for this object if there is a map change. 7765 // Find the new map to use for this object if there is a map change.
7288 Map* new_map = NULL; 7766 Map* new_map = NULL;
7289 if (elements()->map() != heap->non_strict_arguments_elements_map()) { 7767 if (elements()->map() != heap->non_strict_arguments_elements_map()) {
7290 Object* object; 7768 Object* object;
7291 MaybeObject* maybe = map()->GetFastElementsMap(); 7769 bool has_fast_smi_only_elements =
7770 FLAG_smi_only_arrays &&
7771 (set_capacity_mode == kAllowSmiOnlyElements) &&
7772 (elements()->map()->has_fast_smi_only_elements() ||
7773 elements() == heap->empty_fixed_array());
7774 ElementsKind elements_kind = has_fast_smi_only_elements
7775 ? FAST_SMI_ONLY_ELEMENTS
7776 : FAST_ELEMENTS;
7777 MaybeObject* maybe = GetElementsTransitionMap(elements_kind);
7292 if (!maybe->ToObject(&object)) return maybe; 7778 if (!maybe->ToObject(&object)) return maybe;
7293 new_map = Map::cast(object); 7779 new_map = Map::cast(object);
7294 } 7780 }
7295 7781
7296 switch (GetElementsKind()) { 7782 ElementsKind elements_kind = GetElementsKind();
7783 switch (elements_kind) {
7784 case FAST_SMI_ONLY_ELEMENTS:
7297 case FAST_ELEMENTS: { 7785 case FAST_ELEMENTS: {
7298 AssertNoAllocation no_gc; 7786 AssertNoAllocation no_gc;
7299 WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc); 7787 WriteBarrierMode mode(new_elements->GetWriteBarrierMode(no_gc));
7300 CopyFastElementsToFast(FixedArray::cast(elements()), new_elements, mode); 7788 CopyFastElementsToFast(FixedArray::cast(elements()), new_elements, mode);
7301 set_map(new_map); 7789 set_map(new_map);
7302 set_elements(new_elements); 7790 set_elements(new_elements);
7303 break; 7791 break;
7304 } 7792 }
7305 case DICTIONARY_ELEMENTS: { 7793 case DICTIONARY_ELEMENTS: {
7306 AssertNoAllocation no_gc; 7794 AssertNoAllocation no_gc;
7307 WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc); 7795 WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc);
7308 CopySlowElementsToFast(NumberDictionary::cast(elements()), 7796 CopySlowElementsToFast(NumberDictionary::cast(elements()),
7309 new_elements, 7797 new_elements,
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
7384 // We should never end in here with a pixel or external array. 7872 // We should never end in here with a pixel or external array.
7385 ASSERT(!HasExternalArrayElements()); 7873 ASSERT(!HasExternalArrayElements());
7386 7874
7387 Object* obj; 7875 Object* obj;
7388 { MaybeObject* maybe_obj = 7876 { MaybeObject* maybe_obj =
7389 heap->AllocateUninitializedFixedDoubleArray(capacity); 7877 heap->AllocateUninitializedFixedDoubleArray(capacity);
7390 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 7878 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7391 } 7879 }
7392 FixedDoubleArray* elems = FixedDoubleArray::cast(obj); 7880 FixedDoubleArray* elems = FixedDoubleArray::cast(obj);
7393 7881
7394 { MaybeObject* maybe_obj = map()->GetFastDoubleElementsMap(); 7882 { MaybeObject* maybe_obj =
7883 GetElementsTransitionMap(FAST_DOUBLE_ELEMENTS);
7395 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 7884 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7396 } 7885 }
7397 Map* new_map = Map::cast(obj); 7886 Map* new_map = Map::cast(obj);
7398 7887
7399 AssertNoAllocation no_gc; 7888 AssertNoAllocation no_gc;
7400 switch (GetElementsKind()) { 7889 switch (GetElementsKind()) {
7890 case FAST_SMI_ONLY_ELEMENTS:
7401 case FAST_ELEMENTS: { 7891 case FAST_ELEMENTS: {
7402 elems->Initialize(FixedArray::cast(elements())); 7892 elems->Initialize(FixedArray::cast(elements()));
7403 break; 7893 break;
7404 } 7894 }
7405 case FAST_DOUBLE_ELEMENTS: { 7895 case FAST_DOUBLE_ELEMENTS: {
7406 elems->Initialize(FixedDoubleArray::cast(elements())); 7896 elems->Initialize(FixedDoubleArray::cast(elements()));
7407 break; 7897 break;
7408 } 7898 }
7409 case DICTIONARY_ELEMENTS: { 7899 case DICTIONARY_ELEMENTS: {
7410 elems->Initialize(NumberDictionary::cast(elements())); 7900 elems->Initialize(NumberDictionary::cast(elements()));
(...skipping 17 matching lines...) Expand all
7428 } 7918 }
7429 7919
7430 7920
7431 MaybeObject* JSObject::SetSlowElements(Object* len) { 7921 MaybeObject* JSObject::SetSlowElements(Object* len) {
7432 // We should never end in here with a pixel or external array. 7922 // We should never end in here with a pixel or external array.
7433 ASSERT(!HasExternalArrayElements()); 7923 ASSERT(!HasExternalArrayElements());
7434 7924
7435 uint32_t new_length = static_cast<uint32_t>(len->Number()); 7925 uint32_t new_length = static_cast<uint32_t>(len->Number());
7436 7926
7437 switch (GetElementsKind()) { 7927 switch (GetElementsKind()) {
7438 case FAST_ELEMENTS: { 7928 case FAST_SMI_ONLY_ELEMENTS:
7439 case FAST_DOUBLE_ELEMENTS: 7929 case FAST_ELEMENTS:
7930 case FAST_DOUBLE_ELEMENTS: {
7440 // Make sure we never try to shrink dense arrays into sparse arrays. 7931 // Make sure we never try to shrink dense arrays into sparse arrays.
7441 ASSERT(static_cast<uint32_t>( 7932 ASSERT(static_cast<uint32_t>(
7442 FixedArrayBase::cast(elements())->length()) <= new_length); 7933 FixedArrayBase::cast(elements())->length()) <= new_length);
7443 MaybeObject* result = NormalizeElements(); 7934 MaybeObject* result = NormalizeElements();
7444 if (result->IsFailure()) return result; 7935 if (result->IsFailure()) return result;
7445 7936
7446 // Update length for JSArrays. 7937 // Update length for JSArrays.
7447 if (IsJSArray()) JSArray::cast(this)->set_length(len); 7938 if (IsJSArray()) JSArray::cast(this)->set_length(len);
7448 break; 7939 break;
7449 } 7940 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
7495 7986
7496 7987
7497 void JSArray::Expand(int required_size) { 7988 void JSArray::Expand(int required_size) {
7498 Handle<JSArray> self(this); 7989 Handle<JSArray> self(this);
7499 Handle<FixedArray> old_backing(FixedArray::cast(elements())); 7990 Handle<FixedArray> old_backing(FixedArray::cast(elements()));
7500 int old_size = old_backing->length(); 7991 int old_size = old_backing->length();
7501 int new_size = required_size > old_size ? required_size : old_size; 7992 int new_size = required_size > old_size ? required_size : old_size;
7502 Handle<FixedArray> new_backing = FACTORY->NewFixedArray(new_size); 7993 Handle<FixedArray> new_backing = FACTORY->NewFixedArray(new_size);
7503 // Can't use this any more now because we may have had a GC! 7994 // Can't use this any more now because we may have had a GC!
7504 for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i)); 7995 for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i));
7505 self->SetContent(*new_backing); 7996 GetIsolate()->factory()->SetContent(self, new_backing);
7506 } 7997 }
7507 7998
7508 7999
7509 static Failure* ArrayLengthRangeError(Heap* heap) { 8000 static Failure* ArrayLengthRangeError(Heap* heap) {
7510 HandleScope scope(heap->isolate()); 8001 HandleScope scope(heap->isolate());
7511 return heap->isolate()->Throw( 8002 return heap->isolate()->Throw(
7512 *FACTORY->NewRangeError("invalid_array_length", 8003 *FACTORY->NewRangeError("invalid_array_length",
7513 HandleVector<Object>(NULL, 0))); 8004 HandleVector<Object>(NULL, 0)));
7514 } 8005 }
7515 8006
7516 8007
7517 MaybeObject* JSObject::SetElementsLength(Object* len) { 8008 MaybeObject* JSObject::SetElementsLength(Object* len) {
7518 // We should never end in here with a pixel or external array. 8009 // We should never end in here with a pixel or external array.
7519 ASSERT(AllowsSetElementsLength()); 8010 ASSERT(AllowsSetElementsLength());
7520 8011
7521 MaybeObject* maybe_smi_length = len->ToSmi(); 8012 MaybeObject* maybe_smi_length = len->ToSmi();
7522 Object* smi_length = Smi::FromInt(0); 8013 Object* smi_length = Smi::FromInt(0);
7523 if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) { 8014 if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) {
7524 const int value = Smi::cast(smi_length)->value(); 8015 const int value = Smi::cast(smi_length)->value();
7525 if (value < 0) return ArrayLengthRangeError(GetHeap()); 8016 if (value < 0) return ArrayLengthRangeError(GetHeap());
7526 ElementsKind elements_kind = GetElementsKind(); 8017 ElementsKind elements_kind = GetElementsKind();
7527 switch (elements_kind) { 8018 switch (elements_kind) {
8019 case FAST_SMI_ONLY_ELEMENTS:
7528 case FAST_ELEMENTS: 8020 case FAST_ELEMENTS:
7529 case FAST_DOUBLE_ELEMENTS: { 8021 case FAST_DOUBLE_ELEMENTS: {
7530 int old_capacity = FixedArrayBase::cast(elements())->length(); 8022 int old_capacity = FixedArrayBase::cast(elements())->length();
7531 if (value <= old_capacity) { 8023 if (value <= old_capacity) {
7532 if (IsJSArray()) { 8024 if (IsJSArray()) {
7533 Object* obj; 8025 Object* obj;
7534 if (elements_kind == FAST_ELEMENTS) { 8026 if (elements_kind == FAST_ELEMENTS ||
8027 elements_kind == FAST_SMI_ONLY_ELEMENTS) {
7535 MaybeObject* maybe_obj = EnsureWritableFastElements(); 8028 MaybeObject* maybe_obj = EnsureWritableFastElements();
7536 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 8029 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7537 } 8030 }
7538 if (2 * value <= old_capacity) { 8031 if (2 * value <= old_capacity) {
7539 // If more than half the elements won't be used, trim the array. 8032 // If more than half the elements won't be used, trim the array.
7540 if (value == 0) { 8033 if (value == 0) {
7541 initialize_elements(); 8034 initialize_elements();
7542 } else { 8035 } else {
7543 Address filler_start; 8036 Address filler_start;
7544 int filler_size; 8037 int filler_size;
7545 if (GetElementsKind() == FAST_ELEMENTS) { 8038 if (elements_kind == FAST_ELEMENTS ||
8039 elements_kind == FAST_SMI_ONLY_ELEMENTS) {
7546 FixedArray* fast_elements = FixedArray::cast(elements()); 8040 FixedArray* fast_elements = FixedArray::cast(elements());
7547 fast_elements->set_length(value); 8041 fast_elements->set_length(value);
7548 filler_start = fast_elements->address() + 8042 filler_start = fast_elements->address() +
7549 FixedArray::OffsetOfElementAt(value); 8043 FixedArray::OffsetOfElementAt(value);
7550 filler_size = (old_capacity - value) * kPointerSize; 8044 filler_size = (old_capacity - value) * kPointerSize;
7551 } else { 8045 } else {
7552 ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS); 8046 ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS);
7553 FixedDoubleArray* fast_double_elements = 8047 FixedDoubleArray* fast_double_elements =
7554 FixedDoubleArray::cast(elements()); 8048 FixedDoubleArray::cast(elements());
7555 fast_double_elements->set_length(value); 8049 fast_double_elements->set_length(value);
7556 filler_start = fast_double_elements->address() + 8050 filler_start = fast_double_elements->address() +
7557 FixedDoubleArray::OffsetOfElementAt(value); 8051 FixedDoubleArray::OffsetOfElementAt(value);
7558 filler_size = (old_capacity - value) * kDoubleSize; 8052 filler_size = (old_capacity - value) * kDoubleSize;
7559 } 8053 }
7560 GetHeap()->CreateFillerObjectAt(filler_start, filler_size); 8054 GetHeap()->CreateFillerObjectAt(filler_start, filler_size);
7561 } 8055 }
7562 } else { 8056 } else {
7563 // Otherwise, fill the unused tail with holes. 8057 // Otherwise, fill the unused tail with holes.
7564 int old_length = FastD2I(JSArray::cast(this)->length()->Number()); 8058 int old_length = FastD2I(JSArray::cast(this)->length()->Number());
7565 if (GetElementsKind() == FAST_ELEMENTS) { 8059 if (elements_kind == FAST_ELEMENTS ||
8060 elements_kind == FAST_SMI_ONLY_ELEMENTS) {
7566 FixedArray* fast_elements = FixedArray::cast(elements()); 8061 FixedArray* fast_elements = FixedArray::cast(elements());
7567 for (int i = value; i < old_length; i++) { 8062 for (int i = value; i < old_length; i++) {
7568 fast_elements->set_the_hole(i); 8063 fast_elements->set_the_hole(i);
7569 } 8064 }
7570 } else { 8065 } else {
7571 ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS); 8066 ASSERT(elements_kind == FAST_DOUBLE_ELEMENTS);
7572 FixedDoubleArray* fast_double_elements = 8067 FixedDoubleArray* fast_double_elements =
7573 FixedDoubleArray::cast(elements()); 8068 FixedDoubleArray::cast(elements());
7574 for (int i = value; i < old_length; i++) { 8069 for (int i = value; i < old_length; i++) {
7575 fast_double_elements->set_the_hole(i); 8070 fast_double_elements->set_the_hole(i);
7576 } 8071 }
7577 } 8072 }
7578 } 8073 }
7579 JSArray::cast(this)->set_length(Smi::cast(smi_length)); 8074 JSArray::cast(this)->set_length(Smi::cast(smi_length));
7580 } 8075 }
7581 return this; 8076 return this;
7582 } 8077 }
7583 int min = NewElementsCapacity(old_capacity); 8078 int min = NewElementsCapacity(old_capacity);
7584 int new_capacity = value > min ? value : min; 8079 int new_capacity = value > min ? value : min;
7585 if (!ShouldConvertToSlowElements(new_capacity)) { 8080 if (!ShouldConvertToSlowElements(new_capacity)) {
7586 MaybeObject* result; 8081 MaybeObject* result;
7587 if (GetElementsKind() == FAST_ELEMENTS) { 8082 if (elements_kind == FAST_ELEMENTS ||
7588 result = SetFastElementsCapacityAndLength(new_capacity, value); 8083 elements_kind == FAST_SMI_ONLY_ELEMENTS) {
8084 SetFastElementsCapacityMode set_capacity_mode =
8085 elements_kind == FAST_SMI_ONLY_ELEMENTS
8086 ? kAllowSmiOnlyElements
8087 : kDontAllowSmiOnlyElements;
8088 result = SetFastElementsCapacityAndLength(new_capacity,
8089 value,
8090 set_capacity_mode);
7589 } else { 8091 } else {
7590 ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS); 8092 ASSERT(elements_kind == FAST_DOUBLE_ELEMENTS);
7591 result = SetFastDoubleElementsCapacityAndLength(new_capacity, 8093 result = SetFastDoubleElementsCapacityAndLength(new_capacity,
7592 value); 8094 value);
7593 } 8095 }
7594 if (result->IsFailure()) return result; 8096 if (result->IsFailure()) return result;
7595 return this; 8097 return this;
7596 } 8098 }
7597 break; 8099 break;
7598 } 8100 }
7599 case DICTIONARY_ELEMENTS: { 8101 case DICTIONARY_ELEMENTS: {
7600 if (IsJSArray()) { 8102 if (IsJSArray()) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
7637 if (len->ToArrayIndex(&length)) { 8139 if (len->ToArrayIndex(&length)) {
7638 return SetSlowElements(len); 8140 return SetSlowElements(len);
7639 } else { 8141 } else {
7640 return ArrayLengthRangeError(GetHeap()); 8142 return ArrayLengthRangeError(GetHeap());
7641 } 8143 }
7642 } 8144 }
7643 8145
7644 // len is not a number so make the array size one and 8146 // len is not a number so make the array size one and
7645 // set only element to len. 8147 // set only element to len.
7646 Object* obj; 8148 Object* obj;
7647 { MaybeObject* maybe_obj = GetHeap()->AllocateFixedArray(1); 8149 MaybeObject* maybe_obj = GetHeap()->AllocateFixedArray(1);
7648 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 8150 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7649 }
7650 FixedArray::cast(obj)->set(0, len); 8151 FixedArray::cast(obj)->set(0, len);
8152
8153 maybe_obj = EnsureCanContainElements(&len, 1);
8154 if (maybe_obj->IsFailure()) return maybe_obj;
8155
7651 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1)); 8156 if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1));
7652 set_elements(FixedArray::cast(obj)); 8157 set_elements(FixedArray::cast(obj));
7653 return this; 8158 return this;
7654 } 8159 }
7655 8160
7656 8161
7657 Object* Map::GetPrototypeTransition(Object* prototype) { 8162 Object* Map::GetPrototypeTransition(Object* prototype) {
7658 FixedArray* cache = prototype_transitions(); 8163 FixedArray* cache = prototype_transitions();
7659 int number_of_transitions = NumberOfProtoTransitions(); 8164 int number_of_transitions = NumberOfProtoTransitions();
7660 const int proto_offset = 8165 const int proto_offset =
(...skipping 25 matching lines...) Expand all
7686 int capacity = (cache->length() - header) / step; 8191 int capacity = (cache->length() - header) / step;
7687 8192
7688 int transitions = NumberOfProtoTransitions() + 1; 8193 int transitions = NumberOfProtoTransitions() + 1;
7689 8194
7690 if (transitions > capacity) { 8195 if (transitions > capacity) {
7691 if (capacity > kMaxCachedPrototypeTransitions) return this; 8196 if (capacity > kMaxCachedPrototypeTransitions) return this;
7692 8197
7693 FixedArray* new_cache; 8198 FixedArray* new_cache;
7694 // Grow array by factor 2 over and above what we need. 8199 // Grow array by factor 2 over and above what we need.
7695 { MaybeObject* maybe_cache = 8200 { MaybeObject* maybe_cache =
7696 heap()->AllocateFixedArray(transitions * 2 * step + header); 8201 GetHeap()->AllocateFixedArray(transitions * 2 * step + header);
7697 if (!maybe_cache->To<FixedArray>(&new_cache)) return maybe_cache; 8202 if (!maybe_cache->To<FixedArray>(&new_cache)) return maybe_cache;
7698 } 8203 }
7699 8204
7700 for (int i = 0; i < capacity * step; i++) { 8205 for (int i = 0; i < capacity * step; i++) {
7701 new_cache->set(i + header, cache->get(i + header)); 8206 new_cache->set(i + header, cache->get(i + header));
7702 } 8207 }
7703 cache = new_cache; 8208 cache = new_cache;
7704 set_prototype_transitions(cache); 8209 set_prototype_transitions(cache);
7705 } 8210 }
7706 8211
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
7739 return heap->isolate()->Throw( 8244 return heap->isolate()->Throw(
7740 *FACTORY->NewTypeError("non_extensible_proto", 8245 *FACTORY->NewTypeError("non_extensible_proto",
7741 HandleVector<Object>(&handle, 1))); 8246 HandleVector<Object>(&handle, 1)));
7742 } 8247 }
7743 8248
7744 // Before we can set the prototype we need to be sure 8249 // Before we can set the prototype we need to be sure
7745 // prototype cycles are prevented. 8250 // prototype cycles are prevented.
7746 // It is sufficient to validate that the receiver is not in the new prototype 8251 // It is sufficient to validate that the receiver is not in the new prototype
7747 // chain. 8252 // chain.
7748 for (Object* pt = value; pt != heap->null_value(); pt = pt->GetPrototype()) { 8253 for (Object* pt = value; pt != heap->null_value(); pt = pt->GetPrototype()) {
7749 if (JSObject::cast(pt) == this) { 8254 if (JSReceiver::cast(pt) == this) {
7750 // Cycle detected. 8255 // Cycle detected.
7751 HandleScope scope(heap->isolate()); 8256 HandleScope scope(heap->isolate());
7752 return heap->isolate()->Throw( 8257 return heap->isolate()->Throw(
7753 *FACTORY->NewError("cyclic_proto", HandleVector<Object>(NULL, 0))); 8258 *FACTORY->NewError("cyclic_proto", HandleVector<Object>(NULL, 0)));
7754 } 8259 }
7755 } 8260 }
7756 8261
7757 JSReceiver* real_receiver = this; 8262 JSReceiver* real_receiver = this;
7758 8263
7759 if (skip_hidden_prototypes) { 8264 if (skip_hidden_prototypes) {
7760 // Find the first object in the chain whose prototype object is not 8265 // Find the first object in the chain whose prototype object is not
7761 // hidden and set the new prototype on that object. 8266 // hidden and set the new prototype on that object.
7762 Object* current_proto = real_receiver->GetPrototype(); 8267 Object* current_proto = real_receiver->GetPrototype();
7763 while (current_proto->IsJSObject() && 8268 while (current_proto->IsJSObject() &&
7764 JSObject::cast(current_proto)->map()->is_hidden_prototype()) { 8269 JSReceiver::cast(current_proto)->map()->is_hidden_prototype()) {
7765 real_receiver = JSObject::cast(current_proto); 8270 real_receiver = JSReceiver::cast(current_proto);
7766 current_proto = current_proto->GetPrototype(); 8271 current_proto = current_proto->GetPrototype();
7767 } 8272 }
7768 } 8273 }
7769 8274
7770 // Set the new prototype of the object. 8275 // Set the new prototype of the object.
7771 Map* map = real_receiver->map(); 8276 Map* map = real_receiver->map();
7772 8277
7773 // Nothing to do if prototype is already set. 8278 // Nothing to do if prototype is already set.
7774 if (map->prototype() == value) return value; 8279 if (map->prototype() == value) return value;
7775 8280
(...skipping 12 matching lines...) Expand all
7788 } 8293 }
7789 ASSERT(Map::cast(new_map)->prototype() == value); 8294 ASSERT(Map::cast(new_map)->prototype() == value);
7790 real_receiver->set_map(Map::cast(new_map)); 8295 real_receiver->set_map(Map::cast(new_map));
7791 8296
7792 heap->ClearInstanceofCache(); 8297 heap->ClearInstanceofCache();
7793 ASSERT(size == Size()); 8298 ASSERT(size == Size());
7794 return value; 8299 return value;
7795 } 8300 }
7796 8301
7797 8302
8303 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args,
8304 uint32_t first_arg,
8305 uint32_t arg_count) {
8306 return EnsureCanContainElements(args->arguments() - first_arg, arg_count);
8307 }
8308
8309
7798 bool JSObject::HasElementPostInterceptor(JSReceiver* receiver, uint32_t index) { 8310 bool JSObject::HasElementPostInterceptor(JSReceiver* receiver, uint32_t index) {
7799 switch (GetElementsKind()) { 8311 switch (GetElementsKind()) {
8312 case FAST_SMI_ONLY_ELEMENTS:
7800 case FAST_ELEMENTS: { 8313 case FAST_ELEMENTS: {
7801 uint32_t length = IsJSArray() ? 8314 uint32_t length = IsJSArray() ?
7802 static_cast<uint32_t> 8315 static_cast<uint32_t>
7803 (Smi::cast(JSArray::cast(this)->length())->value()) : 8316 (Smi::cast(JSArray::cast(this)->length())->value()) :
7804 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 8317 static_cast<uint32_t>(FixedArray::cast(elements())->length());
7805 if ((index < length) && 8318 if ((index < length) &&
7806 !FixedArray::cast(elements())->get(index)->IsTheHole()) { 8319 !FixedArray::cast(elements())->get(index)->IsTheHole()) {
7807 return true; 8320 return true;
7808 } 8321 }
7809 break; 8322 break;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
7850 case NON_STRICT_ARGUMENTS_ELEMENTS: 8363 case NON_STRICT_ARGUMENTS_ELEMENTS:
7851 UNREACHABLE(); 8364 UNREACHABLE();
7852 break; 8365 break;
7853 } 8366 }
7854 8367
7855 // Handle [] on String objects. 8368 // Handle [] on String objects.
7856 if (this->IsStringObjectWithCharacterAt(index)) return true; 8369 if (this->IsStringObjectWithCharacterAt(index)) return true;
7857 8370
7858 Object* pt = GetPrototype(); 8371 Object* pt = GetPrototype();
7859 if (pt->IsNull()) return false; 8372 if (pt->IsNull()) return false;
8373 if (pt->IsJSProxy()) {
8374 // We need to follow the spec and simulate a call to [[GetOwnProperty]].
8375 return JSProxy::cast(pt)->GetElementAttributeWithHandler(
8376 receiver, index) != ABSENT;
8377 }
7860 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); 8378 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index);
7861 } 8379 }
7862 8380
7863 8381
7864 bool JSObject::HasElementWithInterceptor(JSReceiver* receiver, uint32_t index) { 8382 bool JSObject::HasElementWithInterceptor(JSReceiver* receiver, uint32_t index) {
7865 Isolate* isolate = GetIsolate(); 8383 Isolate* isolate = GetIsolate();
7866 // Make sure that the top context does not change when doing 8384 // Make sure that the top context does not change when doing
7867 // callbacks or interceptor calls. 8385 // callbacks or interceptor calls.
7868 AssertNoContextChange ncc; 8386 AssertNoContextChange ncc;
7869 HandleScope scope(isolate); 8387 HandleScope scope(isolate);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
7926 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT 8444 return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT
7927 : UNDEFINED_ELEMENT; 8445 : UNDEFINED_ELEMENT;
7928 } 8446 }
7929 8447
7930 // Handle [] on String objects. 8448 // Handle [] on String objects.
7931 if (this->IsStringObjectWithCharacterAt(index)) { 8449 if (this->IsStringObjectWithCharacterAt(index)) {
7932 return STRING_CHARACTER_ELEMENT; 8450 return STRING_CHARACTER_ELEMENT;
7933 } 8451 }
7934 8452
7935 switch (GetElementsKind()) { 8453 switch (GetElementsKind()) {
8454 case FAST_SMI_ONLY_ELEMENTS:
7936 case FAST_ELEMENTS: { 8455 case FAST_ELEMENTS: {
7937 uint32_t length = IsJSArray() ? 8456 uint32_t length = IsJSArray() ?
7938 static_cast<uint32_t> 8457 static_cast<uint32_t>
7939 (Smi::cast(JSArray::cast(this)->length())->value()) : 8458 (Smi::cast(JSArray::cast(this)->length())->value()) :
7940 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 8459 static_cast<uint32_t>(FixedArray::cast(elements())->length());
7941 if ((index < length) && 8460 if ((index < length) &&
7942 !FixedArray::cast(elements())->get(index)->IsTheHole()) { 8461 !FixedArray::cast(elements())->get(index)->IsTheHole()) {
7943 return FAST_ELEMENT; 8462 return FAST_ELEMENT;
7944 } 8463 }
7945 break; 8464 break;
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
8040 } 8559 }
8041 } 8560 }
8042 8561
8043 // Check for lookup interceptor 8562 // Check for lookup interceptor
8044 if (HasIndexedInterceptor()) { 8563 if (HasIndexedInterceptor()) {
8045 return HasElementWithInterceptor(receiver, index); 8564 return HasElementWithInterceptor(receiver, index);
8046 } 8565 }
8047 8566
8048 ElementsKind kind = GetElementsKind(); 8567 ElementsKind kind = GetElementsKind();
8049 switch (kind) { 8568 switch (kind) {
8569 case FAST_SMI_ONLY_ELEMENTS:
8050 case FAST_ELEMENTS: { 8570 case FAST_ELEMENTS: {
8051 uint32_t length = IsJSArray() ? 8571 uint32_t length = IsJSArray() ?
8052 static_cast<uint32_t> 8572 static_cast<uint32_t>
8053 (Smi::cast(JSArray::cast(this)->length())->value()) : 8573 (Smi::cast(JSArray::cast(this)->length())->value()) :
8054 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 8574 static_cast<uint32_t>(FixedArray::cast(elements())->length());
8055 if ((index < length) && 8575 if ((index < length) &&
8056 !FixedArray::cast(elements())->get(index)->IsTheHole()) return true; 8576 !FixedArray::cast(elements())->get(index)->IsTheHole()) return true;
8057 break; 8577 break;
8058 } 8578 }
8059 case FAST_DOUBLE_ELEMENTS: { 8579 case FAST_DOUBLE_ELEMENTS: {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
8106 if (HasElementInElements(arguments, kind, index)) return true; 8626 if (HasElementInElements(arguments, kind, index)) return true;
8107 break; 8627 break;
8108 } 8628 }
8109 } 8629 }
8110 8630
8111 // Handle [] on String objects. 8631 // Handle [] on String objects.
8112 if (this->IsStringObjectWithCharacterAt(index)) return true; 8632 if (this->IsStringObjectWithCharacterAt(index)) return true;
8113 8633
8114 Object* pt = GetPrototype(); 8634 Object* pt = GetPrototype();
8115 if (pt->IsNull()) return false; 8635 if (pt->IsNull()) return false;
8636 if (pt->IsJSProxy()) {
8637 // We need to follow the spec and simulate a call to [[GetOwnProperty]].
8638 return JSProxy::cast(pt)->GetElementAttributeWithHandler(
8639 receiver, index) != ABSENT;
8640 }
8116 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); 8641 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index);
8117 } 8642 }
8118 8643
8119 8644
8120 MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index, 8645 MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index,
8121 Object* value, 8646 Object* value,
8122 StrictModeFlag strict_mode, 8647 StrictModeFlag strict_mode,
8123 bool check_prototype) { 8648 bool check_prototype) {
8124 Isolate* isolate = GetIsolate(); 8649 Isolate* isolate = GetIsolate();
8125 // Make sure that the top context does not change when doing 8650 // Make sure that the top context does not change when doing
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
8182 result = call_fun(v8::Utils::ToLocal(key), info); 8707 result = call_fun(v8::Utils::ToLocal(key), info);
8183 } 8708 }
8184 RETURN_IF_SCHEDULED_EXCEPTION(isolate); 8709 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
8185 if (result.IsEmpty()) return isolate->heap()->undefined_value(); 8710 if (result.IsEmpty()) return isolate->heap()->undefined_value();
8186 return *v8::Utils::OpenHandle(*result); 8711 return *v8::Utils::OpenHandle(*result);
8187 } 8712 }
8188 8713
8189 // __defineGetter__ callback 8714 // __defineGetter__ callback
8190 if (structure->IsFixedArray()) { 8715 if (structure->IsFixedArray()) {
8191 Object* getter = FixedArray::cast(structure)->get(kGetterIndex); 8716 Object* getter = FixedArray::cast(structure)->get(kGetterIndex);
8192 if (getter->IsJSFunction()) { 8717 if (getter->IsSpecFunction()) {
8193 return Object::GetPropertyWithDefinedGetter(receiver, 8718 // TODO(rossberg): nicer would be to cast to some JSCallable here...
8194 JSFunction::cast(getter)); 8719 return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter));
8195 } 8720 }
8196 // Getter is not a function. 8721 // Getter is not a function.
8197 return isolate->heap()->undefined_value(); 8722 return isolate->heap()->undefined_value();
8198 } 8723 }
8199 8724
8200 UNREACHABLE(); 8725 UNREACHABLE();
8201 return NULL; 8726 return NULL;
8202 } 8727 }
8203 8728
8204 8729
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
8239 call_fun(v8::Utils::ToLocal(key), 8764 call_fun(v8::Utils::ToLocal(key),
8240 v8::Utils::ToLocal(value_handle), 8765 v8::Utils::ToLocal(value_handle),
8241 info); 8766 info);
8242 } 8767 }
8243 RETURN_IF_SCHEDULED_EXCEPTION(isolate); 8768 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
8244 return *value_handle; 8769 return *value_handle;
8245 } 8770 }
8246 8771
8247 if (structure->IsFixedArray()) { 8772 if (structure->IsFixedArray()) {
8248 Handle<Object> setter(FixedArray::cast(structure)->get(kSetterIndex)); 8773 Handle<Object> setter(FixedArray::cast(structure)->get(kSetterIndex));
8249 if (setter->IsJSFunction()) { 8774 if (setter->IsSpecFunction()) {
8250 return SetPropertyWithDefinedSetter(JSFunction::cast(*setter), value); 8775 // TODO(rossberg): nicer would be to cast to some JSCallable here...
8776 return SetPropertyWithDefinedSetter(JSReceiver::cast(*setter), value);
8251 } else { 8777 } else {
8252 if (strict_mode == kNonStrictMode) { 8778 if (strict_mode == kNonStrictMode) {
8253 return value; 8779 return value;
8254 } 8780 }
8255 Handle<Object> holder_handle(holder, isolate); 8781 Handle<Object> holder_handle(holder, isolate);
8256 Handle<Object> key(isolate->factory()->NewNumberFromUint(index)); 8782 Handle<Object> key(isolate->factory()->NewNumberFromUint(index));
8257 Handle<Object> args[2] = { key, holder_handle }; 8783 Handle<Object> args[2] = { key, holder_handle };
8258 return isolate->Throw( 8784 return isolate->Throw(
8259 *isolate->factory()->NewTypeError("no_setter_in_callback", 8785 *isolate->factory()->NewTypeError("no_setter_in_callback",
8260 HandleVector(args, 2))); 8786 HandleVector(args, 2)));
(...skipping 29 matching lines...) Expand all
8290 } 8816 }
8291 8817
8292 8818
8293 // Adding n elements in fast case is O(n*n). 8819 // Adding n elements in fast case is O(n*n).
8294 // Note: revisit design to have dual undefined values to capture absent 8820 // Note: revisit design to have dual undefined values to capture absent
8295 // elements. 8821 // elements.
8296 MaybeObject* JSObject::SetFastElement(uint32_t index, 8822 MaybeObject* JSObject::SetFastElement(uint32_t index,
8297 Object* value, 8823 Object* value,
8298 StrictModeFlag strict_mode, 8824 StrictModeFlag strict_mode,
8299 bool check_prototype) { 8825 bool check_prototype) {
8300 ASSERT(HasFastElements() || HasFastArgumentsElements()); 8826 ASSERT(HasFastTypeElements() ||
8827 HasFastArgumentsElements());
8301 8828
8302 FixedArray* backing_store = FixedArray::cast(elements()); 8829 FixedArray* backing_store = FixedArray::cast(elements());
8303 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) { 8830 if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) {
8304 backing_store = FixedArray::cast(backing_store->get(1)); 8831 backing_store = FixedArray::cast(backing_store->get(1));
8305 } else { 8832 } else {
8306 Object* writable; 8833 Object* writable;
8307 MaybeObject* maybe = EnsureWritableFastElements(); 8834 MaybeObject* maybe = EnsureWritableFastElements();
8308 if (!maybe->ToObject(&writable)) return maybe; 8835 if (!maybe->ToObject(&writable)) return maybe;
8309 backing_store = FixedArray::cast(writable); 8836 backing_store = FixedArray::cast(writable);
8310 } 8837 }
8311 uint32_t length = static_cast<uint32_t>(backing_store->length()); 8838 uint32_t length = static_cast<uint32_t>(backing_store->length());
8312 8839
8313 if (check_prototype && 8840 if (check_prototype &&
8314 (index >= length || backing_store->get(index)->IsTheHole())) { 8841 (index >= length || backing_store->get(index)->IsTheHole())) {
8315 bool found; 8842 bool found;
8316 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index, 8843 MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
8317 value, 8844 value,
8318 &found, 8845 &found,
8319 strict_mode); 8846 strict_mode);
8320 if (found) return result; 8847 if (found) return result;
8321 } 8848 }
8322 8849
8323 // Check whether there is extra space in fixed array. 8850 // Check whether there is extra space in fixed array.
8324 if (index < length) { 8851 if (index < length) {
8852 if (HasFastSmiOnlyElements()) {
8853 if (!value->IsSmi()) {
8854 // If the value is a number, transition from smi-only to
8855 // FastDoubleElements.
8856 if (value->IsNumber()) {
8857 MaybeObject* maybe =
8858 SetFastDoubleElementsCapacityAndLength(length, length);
8859 if (maybe->IsFailure()) return maybe;
8860 FixedDoubleArray::cast(elements())->set(index, value->Number());
8861 return value;
8862 }
8863 // Value is not a number, transition to generic fast elements.
8864 MaybeObject* maybe_new_map = GetElementsTransitionMap(FAST_ELEMENTS);
8865 Map* new_map;
8866 if (!maybe_new_map->To<Map>(&new_map)) return maybe_new_map;
8867 set_map(new_map);
8868 }
8869 }
8325 backing_store->set(index, value); 8870 backing_store->set(index, value);
8326 if (IsJSArray()) { 8871 if (IsJSArray()) {
8327 // Update the length of the array if needed. 8872 // Update the length of the array if needed.
8328 uint32_t array_length = 0; 8873 uint32_t array_length = 0;
8329 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); 8874 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
8330 if (index >= array_length) { 8875 if (index >= array_length) {
8331 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); 8876 JSArray::cast(this)->set_length(Smi::FromInt(index + 1));
8332 } 8877 }
8333 } 8878 }
8334 return value; 8879 return value;
8335 } 8880 }
8336 8881
8337 // Allow gap in fast case. 8882 // Allow gap in fast case.
8338 if ((index - length) < kMaxGap) { 8883 if ((index - length) < kMaxGap) {
8339 // Try allocating extra space. 8884 // Try allocating extra space.
8340 int new_capacity = NewElementsCapacity(index + 1); 8885 int new_capacity = NewElementsCapacity(index + 1);
8341 if (!ShouldConvertToSlowElements(new_capacity)) { 8886 if (!ShouldConvertToSlowElements(new_capacity)) {
8342 ASSERT(static_cast<uint32_t>(new_capacity) > index); 8887 ASSERT(static_cast<uint32_t>(new_capacity) > index);
8343 Object* new_elements; 8888 Object* new_elements;
8889 SetFastElementsCapacityMode set_capacity_mode =
8890 value->IsSmi() && HasFastSmiOnlyElements()
8891 ? kAllowSmiOnlyElements
8892 : kDontAllowSmiOnlyElements;
8344 MaybeObject* maybe = 8893 MaybeObject* maybe =
8345 SetFastElementsCapacityAndLength(new_capacity, index + 1); 8894 SetFastElementsCapacityAndLength(new_capacity,
8895 index + 1,
8896 set_capacity_mode);
8346 if (!maybe->ToObject(&new_elements)) return maybe; 8897 if (!maybe->ToObject(&new_elements)) return maybe;
8347 FixedArray::cast(new_elements)->set(index, value); 8898 FixedArray::cast(new_elements)->set(index, value);
8348 return value; 8899 return value;
8349 } 8900 }
8350 } 8901 }
8351 8902
8352 // Otherwise default to slow case. 8903 // Otherwise default to slow case.
8353 MaybeObject* result = NormalizeElements(); 8904 MaybeObject* result = NormalizeElements();
8354 if (result->IsFailure()) return result; 8905 if (result->IsFailure()) return result;
8355 return SetDictionaryElement(index, value, strict_mode, check_prototype); 8906 return SetDictionaryElement(index, value, strict_mode, check_prototype);
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
8441 // Attempt to put this object back in fast case. 8992 // Attempt to put this object back in fast case.
8442 if (ShouldConvertToFastElements()) { 8993 if (ShouldConvertToFastElements()) {
8443 uint32_t new_length = 0; 8994 uint32_t new_length = 0;
8444 if (IsJSArray()) { 8995 if (IsJSArray()) {
8445 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); 8996 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length));
8446 } else { 8997 } else {
8447 new_length = dictionary->max_number_key() + 1; 8998 new_length = dictionary->max_number_key() + 1;
8448 } 8999 }
8449 MaybeObject* result = CanConvertToFastDoubleElements() 9000 MaybeObject* result = CanConvertToFastDoubleElements()
8450 ? SetFastDoubleElementsCapacityAndLength(new_length, new_length) 9001 ? SetFastDoubleElementsCapacityAndLength(new_length, new_length)
8451 : SetFastElementsCapacityAndLength(new_length, new_length); 9002 : SetFastElementsCapacityAndLength(new_length,
9003 new_length,
9004 kDontAllowSmiOnlyElements);
8452 if (result->IsFailure()) return result; 9005 if (result->IsFailure()) return result;
8453 #ifdef DEBUG 9006 #ifdef DEBUG
8454 if (FLAG_trace_normalization) { 9007 if (FLAG_trace_normalization) {
8455 PrintF("Object elements are fast case again:\n"); 9008 PrintF("Object elements are fast case again:\n");
8456 Print(); 9009 Print();
8457 } 9010 }
8458 #endif 9011 #endif
8459 } 9012 }
8460 return value; 9013 return value;
8461 } 9014 }
(...skipping 23 matching lines...) Expand all
8485 9038
8486 // If the value object is not a heap number, switch to fast elements and try 9039 // If the value object is not a heap number, switch to fast elements and try
8487 // again. 9040 // again.
8488 bool value_is_smi = value->IsSmi(); 9041 bool value_is_smi = value->IsSmi();
8489 if (!value->IsNumber()) { 9042 if (!value->IsNumber()) {
8490 Object* obj; 9043 Object* obj;
8491 uint32_t length = elms_length; 9044 uint32_t length = elms_length;
8492 if (IsJSArray()) { 9045 if (IsJSArray()) {
8493 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); 9046 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
8494 } 9047 }
8495 MaybeObject* maybe_obj = 9048 MaybeObject* maybe_obj = SetFastElementsCapacityAndLength(
8496 SetFastElementsCapacityAndLength(elms_length, length); 9049 elms_length,
9050 length,
9051 kDontAllowSmiOnlyElements);
8497 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 9052 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
8498 return SetFastElement(index, value, strict_mode, check_prototype); 9053 return SetFastElement(index,
9054 value,
9055 strict_mode,
9056 check_prototype);
8499 } 9057 }
8500 9058
8501 double double_value = value_is_smi 9059 double double_value = value_is_smi
8502 ? static_cast<double>(Smi::cast(value)->value()) 9060 ? static_cast<double>(Smi::cast(value)->value())
8503 : HeapNumber::cast(value)->value(); 9061 : HeapNumber::cast(value)->value();
8504 9062
8505 // Check whether there is extra space in the fixed array. 9063 // Check whether there is extra space in the fixed array.
8506 if (index < elms_length) { 9064 if (index < elms_length) {
8507 elms->set(index, double_value); 9065 elms->set(index, double_value);
8508 if (IsJSArray()) { 9066 if (IsJSArray()) {
(...skipping 30 matching lines...) Expand all
8539 ASSERT(elements()->IsFixedDoubleArray()); 9097 ASSERT(elements()->IsFixedDoubleArray());
8540 Object* obj; 9098 Object* obj;
8541 { MaybeObject* maybe_obj = NormalizeElements(); 9099 { MaybeObject* maybe_obj = NormalizeElements();
8542 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 9100 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
8543 } 9101 }
8544 ASSERT(HasDictionaryElements()); 9102 ASSERT(HasDictionaryElements());
8545 return SetElement(index, value, strict_mode, check_prototype); 9103 return SetElement(index, value, strict_mode, check_prototype);
8546 } 9104 }
8547 9105
8548 9106
9107 MaybeObject* JSReceiver::SetElement(uint32_t index,
9108 Object* value,
9109 StrictModeFlag strict_mode,
9110 bool check_proto) {
9111 return IsJSProxy()
9112 ? JSProxy::cast(this)->SetElementWithHandler(index, value, strict_mode)
9113 : JSObject::cast(this)->SetElement(index, value, strict_mode, check_proto)
9114 ;
9115 }
9116
9117
8549 MaybeObject* JSObject::SetElement(uint32_t index, 9118 MaybeObject* JSObject::SetElement(uint32_t index,
8550 Object* value, 9119 Object* value,
8551 StrictModeFlag strict_mode, 9120 StrictModeFlag strict_mode,
8552 bool check_prototype) { 9121 bool check_prototype) {
8553 // Check access rights if needed. 9122 // Check access rights if needed.
8554 if (IsAccessCheckNeeded()) { 9123 if (IsAccessCheckNeeded()) {
8555 Heap* heap = GetHeap(); 9124 Heap* heap = GetHeap();
8556 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_SET)) { 9125 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_SET)) {
8557 HandleScope scope(heap->isolate()); 9126 HandleScope scope(heap->isolate());
8558 Handle<Object> value_handle(value); 9127 Handle<Object> value_handle(value);
(...skipping 26 matching lines...) Expand all
8585 check_prototype); 9154 check_prototype);
8586 } 9155 }
8587 9156
8588 9157
8589 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, 9158 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
8590 Object* value, 9159 Object* value,
8591 StrictModeFlag strict_mode, 9160 StrictModeFlag strict_mode,
8592 bool check_prototype) { 9161 bool check_prototype) {
8593 Isolate* isolate = GetIsolate(); 9162 Isolate* isolate = GetIsolate();
8594 switch (GetElementsKind()) { 9163 switch (GetElementsKind()) {
9164 case FAST_SMI_ONLY_ELEMENTS:
8595 case FAST_ELEMENTS: 9165 case FAST_ELEMENTS:
8596 return SetFastElement(index, value, strict_mode, check_prototype); 9166 return SetFastElement(index, value, strict_mode, check_prototype);
8597 case FAST_DOUBLE_ELEMENTS: 9167 case FAST_DOUBLE_ELEMENTS:
8598 return SetFastDoubleElement(index, value, strict_mode, check_prototype); 9168 return SetFastDoubleElement(index, value, strict_mode, check_prototype);
8599 case EXTERNAL_PIXEL_ELEMENTS: { 9169 case EXTERNAL_PIXEL_ELEMENTS: {
8600 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); 9170 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
8601 return pixels->SetValue(index, value); 9171 return pixels->SetValue(index, value);
8602 } 9172 }
8603 case EXTERNAL_BYTE_ELEMENTS: { 9173 case EXTERNAL_BYTE_ELEMENTS: {
8604 ExternalByteArray* array = ExternalByteArray::cast(elements()); 9174 ExternalByteArray* array = ExternalByteArray::cast(elements());
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
8747 backing_store_base = 9317 backing_store_base =
8748 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); 9318 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1));
8749 backing_store = FixedArray::cast(backing_store_base); 9319 backing_store = FixedArray::cast(backing_store_base);
8750 if (backing_store->IsDictionary()) { 9320 if (backing_store->IsDictionary()) {
8751 NumberDictionary* dictionary = NumberDictionary::cast(backing_store); 9321 NumberDictionary* dictionary = NumberDictionary::cast(backing_store);
8752 *capacity = dictionary->Capacity(); 9322 *capacity = dictionary->Capacity();
8753 *used = dictionary->NumberOfElements(); 9323 *used = dictionary->NumberOfElements();
8754 break; 9324 break;
8755 } 9325 }
8756 // Fall through. 9326 // Fall through.
9327 case FAST_SMI_ONLY_ELEMENTS:
8757 case FAST_ELEMENTS: 9328 case FAST_ELEMENTS:
8758 backing_store = FixedArray::cast(backing_store_base); 9329 backing_store = FixedArray::cast(backing_store_base);
8759 *capacity = backing_store->length(); 9330 *capacity = backing_store->length();
8760 for (int i = 0; i < *capacity; ++i) { 9331 for (int i = 0; i < *capacity; ++i) {
8761 if (!backing_store->get(i)->IsTheHole()) ++(*used); 9332 if (!backing_store->get(i)->IsTheHole()) ++(*used);
8762 } 9333 }
8763 break; 9334 break;
8764 case DICTIONARY_ELEMENTS: { 9335 case DICTIONARY_ELEMENTS: {
8765 NumberDictionary* dictionary = 9336 NumberDictionary* dictionary =
8766 NumberDictionary::cast(FixedArray::cast(elements())); 9337 NumberDictionary::cast(FixedArray::cast(elements()));
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
9022 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { 9593 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
9023 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); 9594 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
9024 return false; 9595 return false;
9025 } 9596 }
9026 } 9597 }
9027 9598
9028 // Handle [] on String objects. 9599 // Handle [] on String objects.
9029 if (this->IsStringObjectWithCharacterAt(index)) return true; 9600 if (this->IsStringObjectWithCharacterAt(index)) return true;
9030 9601
9031 switch (GetElementsKind()) { 9602 switch (GetElementsKind()) {
9603 case FAST_SMI_ONLY_ELEMENTS:
9032 case FAST_ELEMENTS: { 9604 case FAST_ELEMENTS: {
9033 uint32_t length = IsJSArray() ? 9605 uint32_t length = IsJSArray() ?
9034 static_cast<uint32_t>( 9606 static_cast<uint32_t>(
9035 Smi::cast(JSArray::cast(this)->length())->value()) : 9607 Smi::cast(JSArray::cast(this)->length())->value()) :
9036 static_cast<uint32_t>(FixedArray::cast(elements())->length()); 9608 static_cast<uint32_t>(FixedArray::cast(elements())->length());
9037 return (index < length) && 9609 return (index < length) &&
9038 !FixedArray::cast(elements())->get(index)->IsTheHole(); 9610 !FixedArray::cast(elements())->get(index)->IsTheHole();
9039 } 9611 }
9040 case FAST_DOUBLE_ELEMENTS: { 9612 case FAST_DOUBLE_ELEMENTS: {
9041 uint32_t length = IsJSArray() ? 9613 uint32_t length = IsJSArray() ?
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
9261 } 9833 }
9262 // Compute the number of enumerable elements. 9834 // Compute the number of enumerable elements.
9263 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM)); 9835 return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM));
9264 } 9836 }
9265 9837
9266 9838
9267 int JSObject::GetLocalElementKeys(FixedArray* storage, 9839 int JSObject::GetLocalElementKeys(FixedArray* storage,
9268 PropertyAttributes filter) { 9840 PropertyAttributes filter) {
9269 int counter = 0; 9841 int counter = 0;
9270 switch (GetElementsKind()) { 9842 switch (GetElementsKind()) {
9843 case FAST_SMI_ONLY_ELEMENTS:
9271 case FAST_ELEMENTS: { 9844 case FAST_ELEMENTS: {
9272 int length = IsJSArray() ? 9845 int length = IsJSArray() ?
9273 Smi::cast(JSArray::cast(this)->length())->value() : 9846 Smi::cast(JSArray::cast(this)->length())->value() :
9274 FixedArray::cast(elements())->length(); 9847 FixedArray::cast(elements())->length();
9275 for (int i = 0; i < length; i++) { 9848 for (int i = 0; i < length; i++) {
9276 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { 9849 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
9277 if (storage != NULL) { 9850 if (storage != NULL) {
9278 storage->set(counter, Smi::FromInt(i)); 9851 storage->set(counter, Smi::FromInt(i));
9279 } 9852 }
9280 counter++; 9853 counter++;
(...skipping 845 matching lines...) Expand 10 before | Expand all | Expand 10 after
10126 result_double->set_value(static_cast<double>(result)); 10699 result_double->set_value(static_cast<double>(result));
10127 return result_double; 10700 return result_double;
10128 } 10701 }
10129 10702
10130 10703
10131 // Collects all defined (non-hole) and non-undefined (array) elements at 10704 // Collects all defined (non-hole) and non-undefined (array) elements at
10132 // the start of the elements array. 10705 // the start of the elements array.
10133 // If the object is in dictionary mode, it is converted to fast elements 10706 // If the object is in dictionary mode, it is converted to fast elements
10134 // mode. 10707 // mode.
10135 MaybeObject* JSObject::PrepareElementsForSort(uint32_t limit) { 10708 MaybeObject* JSObject::PrepareElementsForSort(uint32_t limit) {
10136 ASSERT(!HasExternalArrayElements());
10137
10138 Heap* heap = GetHeap(); 10709 Heap* heap = GetHeap();
10139 10710
10140 if (HasDictionaryElements()) { 10711 if (HasDictionaryElements()) {
10141 // Convert to fast elements containing only the existing properties. 10712 // Convert to fast elements containing only the existing properties.
10142 // Ordering is irrelevant, since we are going to sort anyway. 10713 // Ordering is irrelevant, since we are going to sort anyway.
10143 NumberDictionary* dict = element_dictionary(); 10714 NumberDictionary* dict = element_dictionary();
10144 if (IsJSArray() || dict->requires_slow_elements() || 10715 if (IsJSArray() || dict->requires_slow_elements() ||
10145 dict->max_number_key() >= limit) { 10716 dict->max_number_key() >= limit) {
10146 return PrepareSlowElementsForSort(limit); 10717 return PrepareSlowElementsForSort(limit);
10147 } 10718 }
10148 // Convert to fast elements. 10719 // Convert to fast elements.
10149 10720
10150 Object* obj; 10721 Object* obj;
10151 { MaybeObject* maybe_obj = map()->GetFastElementsMap(); 10722 { MaybeObject* maybe_obj = GetElementsTransitionMap(FAST_ELEMENTS);
10152 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 10723 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
10153 } 10724 }
10154 Map* new_map = Map::cast(obj); 10725 Map* new_map = Map::cast(obj);
10155 10726
10156 PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED; 10727 PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED;
10157 Object* new_array; 10728 Object* new_array;
10158 { MaybeObject* maybe_new_array = 10729 { MaybeObject* maybe_new_array =
10159 heap->AllocateFixedArray(dict->NumberOfElements(), tenure); 10730 heap->AllocateFixedArray(dict->NumberOfElements(), tenure);
10160 if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array; 10731 if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array;
10161 } 10732 }
10162 FixedArray* fast_elements = FixedArray::cast(new_array); 10733 FixedArray* fast_elements = FixedArray::cast(new_array);
10163 dict->CopyValuesTo(fast_elements); 10734 dict->CopyValuesTo(fast_elements);
10164 10735
10165 set_map(new_map); 10736 set_map(new_map);
10166 set_elements(fast_elements); 10737 set_elements(fast_elements);
10738 } else if (HasExternalArrayElements()) {
10739 // External arrays cannot have holes or undefined elements.
10740 return Smi::FromInt(ExternalArray::cast(elements())->length());
10167 } else if (!HasFastDoubleElements()) { 10741 } else if (!HasFastDoubleElements()) {
10168 Object* obj; 10742 Object* obj;
10169 { MaybeObject* maybe_obj = EnsureWritableFastElements(); 10743 { MaybeObject* maybe_obj = EnsureWritableFastElements();
10170 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 10744 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
10171 } 10745 }
10172 } 10746 }
10173 ASSERT(HasFastElements() || HasFastDoubleElements()); 10747 ASSERT(HasFastTypeElements() || HasFastDoubleElements());
10174 10748
10175 // Collect holes at the end, undefined before that and the rest at the 10749 // Collect holes at the end, undefined before that and the rest at the
10176 // start, and return the number of non-hole, non-undefined values. 10750 // start, and return the number of non-hole, non-undefined values.
10177 10751
10178 FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements()); 10752 FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements());
10179 uint32_t elements_length = static_cast<uint32_t>(elements_base->length()); 10753 uint32_t elements_length = static_cast<uint32_t>(elements_base->length());
10180 if (limit > elements_length) { 10754 if (limit > elements_length) {
10181 limit = elements_length ; 10755 limit = elements_length ;
10182 } 10756 }
10183 if (limit == 0) { 10757 if (limit == 0) {
(...skipping 1103 matching lines...) Expand 10 before | Expand all | Expand 10 after
11287 ASSERT(obj->IsJSObject()); 11861 ASSERT(obj->IsJSObject());
11288 11862
11289 descriptors->SetNextEnumerationIndex(NextEnumerationIndex()); 11863 descriptors->SetNextEnumerationIndex(NextEnumerationIndex());
11290 // Check that it really works. 11864 // Check that it really works.
11291 ASSERT(obj->HasFastProperties()); 11865 ASSERT(obj->HasFastProperties());
11292 11866
11293 return obj; 11867 return obj;
11294 } 11868 }
11295 11869
11296 11870
11297 Object* ObjectHashTable::Lookup(JSObject* key) { 11871 Object* ObjectHashTable::Lookup(JSReceiver* key) {
11298 // If the object does not have an identity hash, it was never used as a key. 11872 // If the object does not have an identity hash, it was never used as a key.
11299 MaybeObject* maybe_hash = key->GetIdentityHash(JSObject::OMIT_CREATION); 11873 MaybeObject* maybe_hash = key->GetIdentityHash(OMIT_CREATION);
11300 if (maybe_hash->IsFailure()) return GetHeap()->undefined_value(); 11874 if (maybe_hash->IsFailure()) return GetHeap()->undefined_value();
11301 int entry = FindEntry(key); 11875 int entry = FindEntry(key);
11302 if (entry == kNotFound) return GetHeap()->undefined_value(); 11876 if (entry == kNotFound) return GetHeap()->undefined_value();
11303 return get(EntryToIndex(entry) + 1); 11877 return get(EntryToIndex(entry) + 1);
11304 } 11878 }
11305 11879
11306 11880
11307 MaybeObject* ObjectHashTable::Put(JSObject* key, Object* value) { 11881 MaybeObject* ObjectHashTable::Put(JSReceiver* key, Object* value) {
11308 // Make sure the key object has an identity hash code. 11882 // Make sure the key object has an identity hash code.
11309 int hash; 11883 int hash;
11310 { MaybeObject* maybe_hash = key->GetIdentityHash(JSObject::ALLOW_CREATION); 11884 { MaybeObject* maybe_hash = key->GetIdentityHash(ALLOW_CREATION);
11311 if (maybe_hash->IsFailure()) return maybe_hash; 11885 if (maybe_hash->IsFailure()) return maybe_hash;
11312 hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value(); 11886 hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value();
11313 } 11887 }
11314 int entry = FindEntry(key); 11888 int entry = FindEntry(key);
11315 11889
11316 // Check whether to perform removal operation. 11890 // Check whether to perform removal operation.
11317 if (value->IsUndefined()) { 11891 if (value->IsUndefined()) {
11318 if (entry == kNotFound) return this; 11892 if (entry == kNotFound) return this;
11319 RemoveEntry(entry); 11893 RemoveEntry(entry);
11320 return Shrink(key); 11894 return Shrink(key);
11321 } 11895 }
11322 11896
11323 // Key is already in table, just overwrite value. 11897 // Key is already in table, just overwrite value.
11324 if (entry != kNotFound) { 11898 if (entry != kNotFound) {
11325 set(EntryToIndex(entry) + 1, value); 11899 set(EntryToIndex(entry) + 1, value);
11326 return this; 11900 return this;
11327 } 11901 }
11328 11902
11329 // Check whether the hash table should be extended. 11903 // Check whether the hash table should be extended.
11330 Object* obj; 11904 Object* obj;
11331 { MaybeObject* maybe_obj = EnsureCapacity(1, key); 11905 { MaybeObject* maybe_obj = EnsureCapacity(1, key);
11332 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 11906 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
11333 } 11907 }
11334 ObjectHashTable* table = ObjectHashTable::cast(obj); 11908 ObjectHashTable* table = ObjectHashTable::cast(obj);
11335 table->AddEntry(table->FindInsertionEntry(hash), key, value); 11909 table->AddEntry(table->FindInsertionEntry(hash), key, value);
11336 return table; 11910 return table;
11337 } 11911 }
11338 11912
11339 11913
11340 void ObjectHashTable::AddEntry(int entry, JSObject* key, Object* value) { 11914 void ObjectHashTable::AddEntry(int entry, JSReceiver* key, Object* value) {
11341 set(EntryToIndex(entry), key); 11915 set(EntryToIndex(entry), key);
11342 set(EntryToIndex(entry) + 1, value); 11916 set(EntryToIndex(entry) + 1, value);
11343 ElementAdded(); 11917 ElementAdded();
11344 } 11918 }
11345 11919
11346 11920
11347 void ObjectHashTable::RemoveEntry(int entry, Heap* heap) { 11921 void ObjectHashTable::RemoveEntry(int entry, Heap* heap) {
11348 set_null(heap, EntryToIndex(entry)); 11922 set_null(heap, EntryToIndex(entry));
11349 set_null(heap, EntryToIndex(entry) + 1); 11923 set_null(heap, EntryToIndex(entry) + 1);
11350 ElementRemoved(); 11924 ElementRemoved();
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
11598 if (break_point_objects()->IsUndefined()) return 0; 12172 if (break_point_objects()->IsUndefined()) return 0;
11599 // Single break point. 12173 // Single break point.
11600 if (!break_point_objects()->IsFixedArray()) return 1; 12174 if (!break_point_objects()->IsFixedArray()) return 1;
11601 // Multiple break points. 12175 // Multiple break points.
11602 return FixedArray::cast(break_point_objects())->length(); 12176 return FixedArray::cast(break_point_objects())->length();
11603 } 12177 }
11604 #endif 12178 #endif
11605 12179
11606 12180
11607 } } // namespace v8::internal 12181 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698