diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog index 874fcba925d..a95f3cc34ad 100644 --- a/deps/v8/ChangeLog +++ b/deps/v8/ChangeLog @@ -1,48 +1,3 @@ -2011-10-26: Version 3.7.1 - - Achieved 33% speedup in debug-mode tests. - - Removed special casing of calls to RegExp test and exec methods with no - argument. Now matches new JSC behaviour. crbug.com/75740. - - Return the empty string on cyclic references in toString (ES5 - conformance). - - Fixed bug triggered by JSBeautifier. crbug.com/100409. - - Made Math.random state per-context instead of per-process (issue 864). - - Fixed stack traces to skip native functions. - - Make snapshots (new contexts) smaller and faster. - - Fixed handling of Function.apply for non-array arguments. - - Fixed evaluation order in defineProperties to match FireFox. - - Fixed handling of non-object receivers for array builtins, - crbug.com/100702. - - Multiple fixes to improve compliance with test262. - - Fixed compatibility with older Android releases. - - Fixed compilation with gcc-4.5.3. - - Improved performance of WriteUtf8, issue 1665. - - Made native syntax an early error in the preparser. - - Fixed issues 793 and 893 relating to Function.prototype.bind. - - Improved let, const, Set and Map support and other Harmony features - (behind the --harmony flag). - - Changed evaluation order for > and <= to match ES5 instead of ES3. - - Bug fixes and performance improvements on all platforms. - - 2011-10-13: Version 3.7.0 Fixed array handling for Object.defineOwnProperty (ES5 conformance). diff --git a/deps/v8/preparser/preparser-process.cc b/deps/v8/preparser/preparser-process.cc index b0aeb81e2a4..e67851cbd4b 100644 --- a/deps/v8/preparser/preparser-process.cc +++ b/deps/v8/preparser/preparser-process.cc @@ -267,22 +267,34 @@ void CheckException(v8::PreParserData* data, ExceptionExpectation ParseExpectation(int argc, const char* argv[]) { - // Parse ["throws" [ [ []]]]. ExceptionExpectation expects; + + // Parse exception expectations from (the remainder of) the command line. int arg_index = 0; - while (argc > arg_index && strncmp("throws", argv[arg_index], 7)) { - arg_index++; - } + // Skip any flags. + while (argc > arg_index && IsFlag(argv[arg_index])) arg_index++; if (argc > arg_index) { + if (strncmp("throws", argv[arg_index], 7)) { + // First argument after filename, if present, must be the verbatim + // "throws", marking that the preparsing should fail with an exception. + fail(NULL, "ERROR: Extra arguments not prefixed by \"throws\".\n"); + } expects.throws = true; - arg_index++; - if (argc > arg_index && !IsFlag(argv[arg_index])) { - expects.type = argv[arg_index]; + do { arg_index++; - if (argc > arg_index && !IsFlag(argv[arg_index])) { - expects.beg_pos = atoi(argv[arg_index]); // NOLINT + } while (argc > arg_index && IsFlag(argv[arg_index])); + if (argc > arg_index) { + // Next argument is the exception type identifier. + expects.type = argv[arg_index]; + do { arg_index++; - if (argc > arg_index && !IsFlag(argv[arg_index])) { + } while (argc > arg_index && IsFlag(argv[arg_index])); + if (argc > arg_index) { + expects.beg_pos = atoi(argv[arg_index]); // NOLINT + do { + arg_index++; + } while (argc > arg_index && IsFlag(argv[arg_index])); + if (argc > arg_index) { expects.end_pos = atoi(argv[arg_index]); // NOLINT } } @@ -296,8 +308,7 @@ int main(int argc, const char* argv[]) { // Parse command line. // Format: preparser ( | -e "") // ["throws" [ [ []]]] - // Any flags (except an initial -e) are ignored. - // Flags must not separate "throws" and its arguments. + // Any flags (except an initial -s) are ignored. // Check for mandatory filename argument. int arg_index = 1; diff --git a/deps/v8/src/SConscript b/deps/v8/src/SConscript index be4a8f01fb0..f3ae8078ba9 100755 --- a/deps/v8/src/SConscript +++ b/deps/v8/src/SConscript @@ -321,7 +321,7 @@ debug-debugger.js EXPERIMENTAL_LIBRARY_FILES = ''' proxy.js -collection.js +weakmap.js '''.split() diff --git a/deps/v8/src/accessors.cc b/deps/v8/src/accessors.cc index 02998f9b8ee..951209d964c 100644 --- a/deps/v8/src/accessors.cc +++ b/deps/v8/src/accessors.cc @@ -527,9 +527,7 @@ MaybeObject* Accessors::FunctionGetLength(Object* object, void*) { // correctly yet. Compile it now and return the right length. HandleScope scope; Handle handle(function); - if (!JSFunction::CompileLazy(handle, KEEP_EXCEPTION)) { - return Failure::Exception(); - } + if (!CompileLazy(handle, KEEP_EXCEPTION)) return Failure::Exception(); return Smi::FromInt(handle->shared()->length()); } else { return Smi::FromInt(function->shared()->length()); @@ -761,12 +759,7 @@ MaybeObject* Accessors::FunctionGetCaller(Object* object, void*) { caller = potential_caller; potential_caller = it.next(); } - // If caller is bound, return null. This is compatible with JSC, and - // allows us to make bound functions use the strict function map - // and its associated throwing caller and arguments. - if (caller->shared()->bound()) { - return isolate->heap()->null_value(); - } + return CheckNonStrictCallerOrThrow(isolate, caller); } diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index ac4f07fd5e1..a03b7411c3c 100644 --- a/deps/v8/src/api.cc +++ b/deps/v8/src/api.cc @@ -2794,7 +2794,7 @@ Local v8::Object::Get(uint32_t index) { ENTER_V8(isolate); i::Handle self = Utils::OpenHandle(this); EXCEPTION_PREAMBLE(isolate); - i::Handle result = i::Object::GetElement(self, index); + i::Handle result = i::GetElement(self, index); has_pending_exception = result.is_null(); EXCEPTION_BAILOUT_CHECK(isolate, Local()); return Utils::ToLocal(result); @@ -2874,10 +2874,8 @@ Local v8::Object::GetPropertyNames() { ENTER_V8(isolate); i::HandleScope scope(isolate); i::Handle self = Utils::OpenHandle(this); - bool threw = false; i::Handle value = - i::GetKeysInFixedArrayFor(self, i::INCLUDE_PROTOS, &threw); - if (threw) return Local(); + i::GetKeysInFixedArrayFor(self, i::INCLUDE_PROTOS); // Because we use caching to speed up enumeration it is important // to never change the result of the basic enumeration function so // we clone the result. @@ -2895,10 +2893,8 @@ Local v8::Object::GetOwnPropertyNames() { ENTER_V8(isolate); i::HandleScope scope(isolate); i::Handle self = Utils::OpenHandle(this); - bool threw = false; i::Handle value = - i::GetKeysInFixedArrayFor(self, i::LOCAL_ONLY, &threw); - if (threw) return Local(); + i::GetKeysInFixedArrayFor(self, i::LOCAL_ONLY); // Because we use caching to speed up enumeration it is important // to never change the result of the basic enumeration function so // we clone the result. @@ -3097,10 +3093,7 @@ static Local GetPropertyByLookup(i::Isolate* isolate, // If the property being looked up is a callback, it can throw // an exception. EXCEPTION_PREAMBLE(isolate); - PropertyAttributes ignored; - i::Handle result = - i::Object::GetProperty(receiver, receiver, lookup, name, - &ignored); + i::Handle result = i::GetProperty(receiver, name, lookup); has_pending_exception = result.is_null(); EXCEPTION_BAILOUT_CHECK(isolate, Local()); @@ -3117,7 +3110,7 @@ Local v8::Object::GetRealNamedPropertyInPrototypeChain( ENTER_V8(isolate); i::Handle self_obj = Utils::OpenHandle(this); i::Handle key_obj = Utils::OpenHandle(*key); - i::LookupResult lookup(isolate); + i::LookupResult lookup; self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup); return GetPropertyByLookup(isolate, self_obj, key_obj, &lookup); } @@ -3130,7 +3123,7 @@ Local v8::Object::GetRealNamedProperty(Handle key) { ENTER_V8(isolate); i::Handle self_obj = Utils::OpenHandle(this); i::Handle key_obj = Utils::OpenHandle(*key); - i::LookupResult lookup(isolate); + i::LookupResult lookup; self_obj->LookupRealNamedProperty(*key_obj, &lookup); return GetPropertyByLookup(isolate, self_obj, key_obj, &lookup); } @@ -3641,30 +3634,13 @@ int String::WriteUtf8(char* buffer, if (IsDeadCheck(isolate, "v8::String::WriteUtf8()")) return 0; LOG_API(isolate, "String::WriteUtf8"); ENTER_V8(isolate); - i::Handle str = Utils::OpenHandle(this); - if (str->IsAsciiRepresentation()) { - int len; - if (capacity == -1) { - capacity = str->length() + 1; - len = str->length(); - } else { - len = i::Min(capacity, str->length()); - } - i::String::WriteToFlat(*str, buffer, 0, len); - if (nchars_ref != NULL) *nchars_ref = len; - if (!(options & NO_NULL_TERMINATION) && capacity > len) { - buffer[len] = '\0'; - return len + 1; - } - return len; - } - i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer(); + i::Handle str = Utils::OpenHandle(this); isolate->string_tracker()->RecordWrite(str); if (options & HINT_MANY_WRITES_EXPECTED) { // Flatten the string for efficiency. This applies whether we are // using StringInputBuffer or Get(i) to access the characters. - FlattenString(str); + str->TryFlatten(); } write_input_buffer.Reset(0, *str); int len = str->length(); @@ -3985,15 +3961,6 @@ HeapStatistics::HeapStatistics(): total_heap_size_(0), void v8::V8::GetHeapStatistics(HeapStatistics* heap_statistics) { - if (!i::Isolate::Current()->IsInitialized()) { - // Isolate is unitialized thus heap is not configured yet. - heap_statistics->set_total_heap_size(0); - heap_statistics->set_total_heap_size_executable(0); - heap_statistics->set_used_heap_size(0); - heap_statistics->set_heap_size_limit(0); - return; - } - i::Heap* heap = i::Isolate::Current()->heap(); heap_statistics->set_total_heap_size(heap->CommittedMemory()); heap_statistics->set_total_heap_size_executable( @@ -4006,15 +3973,14 @@ void v8::V8::GetHeapStatistics(HeapStatistics* heap_statistics) { bool v8::V8::IdleNotification() { // Returning true tells the caller that it need not // continue to call IdleNotification. - i::Isolate* isolate = i::Isolate::Current(); - if (isolate == NULL || !isolate->IsInitialized()) return true; + if (!i::Isolate::Current()->IsInitialized()) return true; return i::V8::IdleNotification(); } void v8::V8::LowMemoryNotification() { i::Isolate* isolate = i::Isolate::Current(); - if (isolate == NULL || !isolate->IsInitialized()) return; + if (!isolate->IsInitialized()) return; isolate->heap()->CollectAllAvailableGarbage(); } @@ -4109,9 +4075,8 @@ Persistent v8::Context::New( } // Leave V8. - if (env.is_null()) { + if (env.is_null()) return Persistent(); - } return Persistent(Utils::ToLocal(env)); } diff --git a/deps/v8/src/arm/assembler-arm-inl.h b/deps/v8/src/arm/assembler-arm-inl.h index 7f9f4cebe2b..93cecf52b68 100644 --- a/deps/v8/src/arm/assembler-arm-inl.h +++ b/deps/v8/src/arm/assembler-arm-inl.h @@ -74,10 +74,10 @@ int RelocInfo::target_address_size() { } -void RelocInfo::set_target_address(Address target, WriteBarrierMode mode) { +void RelocInfo::set_target_address(Address target) { ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY); Assembler::set_target_address_at(pc_, target); - if (mode == UPDATE_WRITE_BARRIER && host() != NULL && IsCodeTarget(rmode_)) { + if (host() != NULL && IsCodeTarget(rmode_)) { Object* target_code = Code::GetCodeFromTargetAddress(target); host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( host(), this, HeapObject::cast(target_code)); @@ -103,12 +103,10 @@ Object** RelocInfo::target_object_address() { } -void RelocInfo::set_target_object(Object* target, WriteBarrierMode mode) { +void RelocInfo::set_target_object(Object* target) { ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); Assembler::set_target_address_at(pc_, reinterpret_cast
(target)); - if (mode == UPDATE_WRITE_BARRIER && - host() != NULL && - target->IsHeapObject()) { + if (host() != NULL && target->IsHeapObject()) { host()->GetHeap()->incremental_marking()->RecordWrite( host(), &Memory::Object_at(pc_), HeapObject::cast(target)); } @@ -138,12 +136,11 @@ JSGlobalPropertyCell* RelocInfo::target_cell() { } -void RelocInfo::set_target_cell(JSGlobalPropertyCell* cell, - WriteBarrierMode mode) { +void RelocInfo::set_target_cell(JSGlobalPropertyCell* cell) { ASSERT(rmode_ == RelocInfo::GLOBAL_PROPERTY_CELL); Address address = cell->address() + JSGlobalPropertyCell::kValueOffset; Memory::Address_at(pc_) = address; - if (mode == UPDATE_WRITE_BARRIER && host() != NULL) { + if (host() != NULL) { // TODO(1550) We are passing NULL as a slot because cell can never be on // evacuation candidate. host()->GetHeap()->incremental_marking()->RecordWrite( diff --git a/deps/v8/src/arm/assembler-arm.h b/deps/v8/src/arm/assembler-arm.h index 247479d730b..d19b64da54a 100644 --- a/deps/v8/src/arm/assembler-arm.h +++ b/deps/v8/src/arm/assembler-arm.h @@ -304,9 +304,9 @@ const DwVfpRegister d14 = { 14 }; const DwVfpRegister d15 = { 15 }; // Aliases for double registers. -static const DwVfpRegister& kFirstCalleeSavedDoubleReg = d8; -static const DwVfpRegister& kLastCalleeSavedDoubleReg = d15; -static const DwVfpRegister& kDoubleRegZero = d14; +const DwVfpRegister kFirstCalleeSavedDoubleReg = d8; +const DwVfpRegister kLastCalleeSavedDoubleReg = d15; +const DwVfpRegister kDoubleRegZero = d14; // Coprocessor register diff --git a/deps/v8/src/arm/builtins-arm.cc b/deps/v8/src/arm/builtins-arm.cc index 29bf19028cb..32b7896a525 100644 --- a/deps/v8/src/arm/builtins-arm.cc +++ b/deps/v8/src/arm/builtins-arm.cc @@ -86,6 +86,12 @@ static void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) { } +// This constant has the same value as JSArray::kPreallocatedArrayElements and +// if JSArray::kPreallocatedArrayElements is changed handling of loop unfolding +// below should be reconsidered. +static const int kLoopUnfoldLimit = 4; + + // Allocate an empty JSArray. The allocated array is put into the result // register. An elements backing store is allocated with size initial_capacity // and filled with the hole values. @@ -95,9 +101,9 @@ static void AllocateEmptyJSArray(MacroAssembler* masm, Register scratch1, Register scratch2, Register scratch3, + int initial_capacity, Label* gc_required) { - const int initial_capacity = JSArray::kPreallocatedArrayElements; - STATIC_ASSERT(initial_capacity >= 0); + ASSERT(initial_capacity > 0); // Load the initial map from the array function. __ ldr(scratch1, FieldMemOperand(array_function, JSFunction::kPrototypeOrInitialMapOffset)); @@ -147,24 +153,12 @@ static void AllocateEmptyJSArray(MacroAssembler* masm, ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset); __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex)); - // Fill the FixedArray with the hole value. Inline the code if short. - if (initial_capacity == 0) return; + // Fill the FixedArray with the hole value. ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize); + ASSERT(initial_capacity <= kLoopUnfoldLimit); __ LoadRoot(scratch3, Heap::kTheHoleValueRootIndex); - static const int kLoopUnfoldLimit = 4; - if (initial_capacity <= kLoopUnfoldLimit) { - for (int i = 0; i < initial_capacity; i++) { - __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex)); - } - } else { - Label loop, entry; - __ add(scratch2, scratch1, Operand(initial_capacity * kPointerSize)); - __ b(&entry); - __ bind(&loop); + for (int i = 0; i < initial_capacity; i++) { __ str(scratch3, MemOperand(scratch1, kPointerSize, PostIndex)); - __ bind(&entry); - __ cmp(scratch1, scratch2); - __ b(lt, &loop); } } @@ -179,7 +173,7 @@ static void AllocateEmptyJSArray(MacroAssembler* masm, // register elements_array_storage is scratched. static void AllocateJSArray(MacroAssembler* masm, Register array_function, // Array function. - Register array_size, // As a smi, cannot be 0. + Register array_size, // As a smi. Register result, Register elements_array_storage, Register elements_array_end, @@ -187,18 +181,32 @@ static void AllocateJSArray(MacroAssembler* masm, Register scratch2, bool fill_with_hole, Label* gc_required) { + Label not_empty, allocated; + // Load the initial map from the array function. __ ldr(elements_array_storage, FieldMemOperand(array_function, JSFunction::kPrototypeOrInitialMapOffset)); - if (FLAG_debug_code) { // Assert that array size is not zero. - __ tst(array_size, array_size); - __ Assert(ne, "array size is unexpectedly 0"); - } + // Check whether an empty sized array is requested. + __ tst(array_size, array_size); + __ b(ne, ¬_empty); + + // If an empty array is requested allocate a small elements array anyway. This + // keeps the code below free of special casing for the empty array. + int size = JSArray::kSize + + FixedArray::SizeFor(JSArray::kPreallocatedArrayElements); + __ AllocateInNewSpace(size, + result, + elements_array_end, + scratch1, + gc_required, + TAG_OBJECT); + __ jmp(&allocated); // Allocate the JSArray object together with space for a FixedArray with the // requested number of elements. + __ bind(¬_empty); STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); __ mov(elements_array_end, Operand((JSArray::kSize + FixedArray::kHeaderSize) / kPointerSize)); @@ -218,6 +226,7 @@ static void AllocateJSArray(MacroAssembler* masm, // result: JSObject // elements_array_storage: initial map // array_size: size of array (smi) + __ bind(&allocated); __ str(elements_array_storage, FieldMemOperand(result, JSObject::kMapOffset)); __ LoadRoot(elements_array_storage, Heap::kEmptyFixedArrayRootIndex); __ str(elements_array_storage, @@ -247,6 +256,14 @@ static void AllocateJSArray(MacroAssembler* masm, ASSERT_EQ(0 * kPointerSize, FixedArray::kMapOffset); __ str(scratch1, MemOperand(elements_array_storage, kPointerSize, PostIndex)); STATIC_ASSERT(kSmiTag == 0); + __ tst(array_size, array_size); + // Length of the FixedArray is the number of pre-allocated elements if + // the actual JSArray has length 0 and the size of the JSArray for non-empty + // JSArrays. The length of a FixedArray is stored as a smi. + __ mov(array_size, + Operand(Smi::FromInt(JSArray::kPreallocatedArrayElements)), + LeaveCC, + eq); ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset); __ str(array_size, MemOperand(elements_array_storage, kPointerSize, PostIndex)); @@ -294,20 +311,20 @@ static void AllocateJSArray(MacroAssembler* masm, static void ArrayNativeCode(MacroAssembler* masm, Label* call_generic_code) { Counters* counters = masm->isolate()->counters(); - Label argc_one_or_more, argc_two_or_more, not_empty_array, empty_array; + Label argc_one_or_more, argc_two_or_more; // Check for array construction with zero arguments or one. __ cmp(r0, Operand(0, RelocInfo::NONE)); __ b(ne, &argc_one_or_more); // Handle construction of an empty array. - __ bind(&empty_array); AllocateEmptyJSArray(masm, r1, r2, r3, r4, r5, + JSArray::kPreallocatedArrayElements, call_generic_code); __ IncrementCounter(counters->array_function_native(), 1, r3, r4); // Setup return value, remove receiver from stack and return. @@ -322,13 +339,6 @@ static void ArrayNativeCode(MacroAssembler* masm, __ b(ne, &argc_two_or_more); STATIC_ASSERT(kSmiTag == 0); __ ldr(r2, MemOperand(sp)); // Get the argument from the stack. - __ tst(r2, r2); - __ b(ne, ¬_empty_array); - __ Drop(1); // Adjust stack. - __ mov(r0, Operand(0)); // Treat this as a call with argc of zero. - __ b(&empty_array); - - __ bind(¬_empty_array); __ and_(r3, r2, Operand(kIntptrSignBit | kSmiTagMask), SetCC); __ b(ne, call_generic_code); @@ -1017,9 +1027,9 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); // Set up the roots register. - ExternalReference roots_array_start = - ExternalReference::roots_array_start(masm->isolate()); - __ mov(r10, Operand(roots_array_start)); + ExternalReference roots_address = + ExternalReference::roots_address(masm->isolate()); + __ mov(r10, Operand(roots_address)); // Push the function and the receiver onto the stack. __ push(r1); diff --git a/deps/v8/src/arm/code-stubs-arm.cc b/deps/v8/src/arm/code-stubs-arm.cc index 412ba00fc88..44923a1843d 100644 --- a/deps/v8/src/arm/code-stubs-arm.cc +++ b/deps/v8/src/arm/code-stubs-arm.cc @@ -263,12 +263,7 @@ void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) { // [sp + (2 * kPointerSize)]: literals array. // All sizes here are multiples of kPointerSize. - int elements_size = 0; - if (length_ > 0) { - elements_size = mode_ == CLONE_DOUBLE_ELEMENTS - ? FixedDoubleArray::SizeFor(length_) - : FixedArray::SizeFor(length_); - } + int elements_size = (length_ > 0) ? FixedArray::SizeFor(length_) : 0; int size = JSArray::kSize + elements_size; // Load boilerplate object into r3 and check if we need to create a @@ -288,9 +283,6 @@ void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) { if (mode_ == CLONE_ELEMENTS) { message = "Expected (writable) fixed array"; expected_map_index = Heap::kFixedArrayMapRootIndex; - } else if (mode_ == CLONE_DOUBLE_ELEMENTS) { - message = "Expected (writable) fixed double array"; - expected_map_index = Heap::kFixedDoubleArrayMapRootIndex; } else { ASSERT(mode_ == COPY_ON_WRITE_ELEMENTS); message = "Expected copy-on-write fixed array"; @@ -330,7 +322,6 @@ void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) { __ str(r2, FieldMemOperand(r0, JSArray::kElementsOffset)); // Copy the elements array. - ASSERT((elements_size % kPointerSize) == 0); __ CopyFields(r2, r3, r1.bit(), elements_size / kPointerSize); } @@ -3922,7 +3913,7 @@ void InstanceofStub::Generate(MacroAssembler* masm) { } // Get the prototype of the function. - __ TryGetFunctionPrototype(function, prototype, scratch, &slow, true); + __ TryGetFunctionPrototype(function, prototype, scratch, &slow); // Check that the function prototype is a JS object. __ JumpIfSmi(prototype, &slow); @@ -6677,82 +6668,7 @@ void DirectCEntryStub::GenerateCall(MacroAssembler* masm, } -void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, - Label* miss, - Label* done, - Register receiver, - Register properties, - Handle name, - Register scratch0) { - // If names of slots in range from 1 to kProbes - 1 for the hash value are - // not equal to the name and kProbes-th slot is not used (its name is the - // undefined value), it guarantees the hash table doesn't contain the - // property. It's true even if some slots represent deleted properties - // (their names are the null value). - for (int i = 0; i < kInlinedProbes; i++) { - // scratch0 points to properties hash. - // Compute the masked index: (hash + i + i * i) & mask. - Register index = scratch0; - // Capacity is smi 2^n. - __ ldr(index, FieldMemOperand(properties, kCapacityOffset)); - __ sub(index, index, Operand(1)); - __ and_(index, index, Operand( - Smi::FromInt(name->Hash() + StringDictionary::GetProbeOffset(i)))); - - // Scale the index by multiplying by the entry size. - ASSERT(StringDictionary::kEntrySize == 3); - __ add(index, index, Operand(index, LSL, 1)); // index *= 3. - - Register entity_name = scratch0; - // Having undefined at this place means the name is not contained. - ASSERT_EQ(kSmiTagSize, 1); - Register tmp = properties; - __ add(tmp, properties, Operand(index, LSL, 1)); - __ ldr(entity_name, FieldMemOperand(tmp, kElementsStartOffset)); - - ASSERT(!tmp.is(entity_name)); - __ LoadRoot(tmp, Heap::kUndefinedValueRootIndex); - __ cmp(entity_name, tmp); - __ b(eq, done); - - if (i != kInlinedProbes - 1) { - // Stop if found the property. - __ cmp(entity_name, Operand(Handle(name))); - __ b(eq, miss); - - // Check if the entry name is not a symbol. - __ ldr(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset)); - __ ldrb(entity_name, - FieldMemOperand(entity_name, Map::kInstanceTypeOffset)); - __ tst(entity_name, Operand(kIsSymbolMask)); - __ b(eq, miss); - - // Restore the properties. - __ ldr(properties, - FieldMemOperand(receiver, JSObject::kPropertiesOffset)); - } - } - - const int spill_mask = - (lr.bit() | r6.bit() | r5.bit() | r4.bit() | r3.bit() | - r2.bit() | r1.bit() | r0.bit()); - - __ stm(db_w, sp, spill_mask); - __ ldr(r0, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); - __ mov(r1, Operand(Handle(name))); - StringDictionaryLookupStub stub(NEGATIVE_LOOKUP); - __ CallStub(&stub); - __ tst(r0, Operand(r0)); - __ ldm(ia_w, sp, spill_mask); - - __ b(eq, done); - __ b(ne, miss); -} - - -// TODO(kmillikin): Eliminate this function when the stub cache is fully -// handlified. -MaybeObject* StringDictionaryLookupStub::TryGenerateNegativeLookup( +MaybeObject* StringDictionaryLookupStub::GenerateNegativeLookup( MacroAssembler* masm, Label* miss, Label* done, @@ -7011,13 +6927,6 @@ struct AheadOfTimeWriteBarrierStubList kAheadOfTime[] = { { r3, r1, r2, EMIT_REMEMBERED_SET }, // KeyedStoreStubCompiler::GenerateStoreFastElement. { r4, r2, r3, EMIT_REMEMBERED_SET }, - // ElementsTransitionGenerator::GenerateSmiOnlyToObject - // and ElementsTransitionGenerator::GenerateSmiOnlyToDouble - // and ElementsTransitionGenerator::GenerateDoubleToObject - { r2, r3, r9, EMIT_REMEMBERED_SET }, - // ElementsTransitionGenerator::GenerateDoubleToObject - { r6, r2, r0, EMIT_REMEMBERED_SET }, - { r2, r6, r9, EMIT_REMEMBERED_SET }, // Null termination. { no_reg, no_reg, no_reg, EMIT_REMEMBERED_SET} }; @@ -7254,6 +7163,7 @@ void RecordWriteStub::CheckNeedsToInformIncrementalMarker( // Fall through when we need to inform the incremental marker. } + #undef __ } } // namespace v8::internal diff --git a/deps/v8/src/arm/code-stubs-arm.h b/deps/v8/src/arm/code-stubs-arm.h index 647fc8d154f..3ba75bab130 100644 --- a/deps/v8/src/arm/code-stubs-arm.h +++ b/deps/v8/src/arm/code-stubs-arm.h @@ -799,17 +799,7 @@ class StringDictionaryLookupStub: public CodeStub { void Generate(MacroAssembler* masm); - static void GenerateNegativeLookup(MacroAssembler* masm, - Label* miss, - Label* done, - Register receiver, - Register properties, - Handle name, - Register scratch0); - - // TODO(kmillikin): Eliminate this function when the stub cache is fully - // handlified. - MUST_USE_RESULT static MaybeObject* TryGenerateNegativeLookup( + MUST_USE_RESULT static MaybeObject* GenerateNegativeLookup( MacroAssembler* masm, Label* miss, Label* done, diff --git a/deps/v8/src/arm/codegen-arm.cc b/deps/v8/src/arm/codegen-arm.cc index 508d830bdfd..3993ed02bed 100644 --- a/deps/v8/src/arm/codegen-arm.cc +++ b/deps/v8/src/arm/codegen-arm.cc @@ -30,13 +30,10 @@ #if defined(V8_TARGET_ARCH_ARM) #include "codegen.h" -#include "macro-assembler.h" namespace v8 { namespace internal { -#define __ ACCESS_MASM(masm) - // ------------------------------------------------------------------------- // Platform-specific RuntimeCallHelper functions. @@ -54,252 +51,6 @@ void StubRuntimeCallHelper::AfterCall(MacroAssembler* masm) const { } -// ------------------------------------------------------------------------- -// Code generators - -void ElementsTransitionGenerator::GenerateSmiOnlyToObject( - MacroAssembler* masm) { - // ----------- S t a t e ------------- - // -- r0 : value - // -- r1 : key - // -- r2 : receiver - // -- lr : return address - // -- r3 : target map, scratch for subsequent call - // -- r4 : scratch (elements) - // ----------------------------------- - // Set transitioned map. - __ str(r3, FieldMemOperand(r2, HeapObject::kMapOffset)); - __ RecordWriteField(r2, - HeapObject::kMapOffset, - r3, - r9, - kLRHasNotBeenSaved, - kDontSaveFPRegs, - EMIT_REMEMBERED_SET, - OMIT_SMI_CHECK); -} - - -void ElementsTransitionGenerator::GenerateSmiOnlyToDouble( - MacroAssembler* masm, Label* fail) { - // ----------- S t a t e ------------- - // -- r0 : value - // -- r1 : key - // -- r2 : receiver - // -- lr : return address - // -- r3 : target map, scratch for subsequent call - // -- r4 : scratch (elements) - // ----------------------------------- - Label loop, entry, convert_hole, gc_required; - bool vfp3_supported = CpuFeatures::IsSupported(VFP3); - __ push(lr); - - __ ldr(r4, FieldMemOperand(r2, JSObject::kElementsOffset)); - __ ldr(r5, FieldMemOperand(r4, FixedArray::kLengthOffset)); - // r4: source FixedArray - // r5: number of elements (smi-tagged) - - // Allocate new FixedDoubleArray. - __ mov(lr, Operand(FixedDoubleArray::kHeaderSize)); - __ add(lr, lr, Operand(r5, LSL, 2)); - __ AllocateInNewSpace(lr, r6, r7, r9, &gc_required, NO_ALLOCATION_FLAGS); - // r6: destination FixedDoubleArray, not tagged as heap object - __ LoadRoot(r9, Heap::kFixedDoubleArrayMapRootIndex); - __ str(r9, MemOperand(r6, HeapObject::kMapOffset)); - // Set destination FixedDoubleArray's length. - __ str(r5, MemOperand(r6, FixedDoubleArray::kLengthOffset)); - // Update receiver's map. - - __ str(r3, FieldMemOperand(r2, HeapObject::kMapOffset)); - __ RecordWriteField(r2, - HeapObject::kMapOffset, - r3, - r9, - kLRHasBeenSaved, - kDontSaveFPRegs, - EMIT_REMEMBERED_SET, - OMIT_SMI_CHECK); - // Replace receiver's backing store with newly created FixedDoubleArray. - __ add(r3, r6, Operand(kHeapObjectTag)); - __ str(r3, FieldMemOperand(r2, JSObject::kElementsOffset)); - __ RecordWriteField(r2, - JSObject::kElementsOffset, - r3, - r9, - kLRHasBeenSaved, - kDontSaveFPRegs, - EMIT_REMEMBERED_SET, - OMIT_SMI_CHECK); - - // Prepare for conversion loop. - __ add(r3, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); - __ add(r7, r6, Operand(FixedDoubleArray::kHeaderSize)); - __ add(r6, r7, Operand(r5, LSL, 2)); - __ mov(r4, Operand(kHoleNanLower32)); - __ mov(r5, Operand(kHoleNanUpper32)); - // r3: begin of source FixedArray element fields, not tagged - // r4: kHoleNanLower32 - // r5: kHoleNanUpper32 - // r6: end of destination FixedDoubleArray, not tagged - // r7: begin of FixedDoubleArray element fields, not tagged - if (!vfp3_supported) __ Push(r1, r0); - - __ b(&entry); - - // Call into runtime if GC is required. - __ bind(&gc_required); - __ pop(lr); - __ b(fail); - - // Convert and copy elements. - __ bind(&loop); - __ ldr(r9, MemOperand(r3, 4, PostIndex)); - // r9: current element - __ JumpIfNotSmi(r9, &convert_hole); - - // Normal smi, convert to double and store. - __ SmiUntag(r9); - if (vfp3_supported) { - CpuFeatures::Scope scope(VFP3); - __ vmov(s0, r9); - __ vcvt_f64_s32(d0, s0); - __ vstr(d0, r7, 0); - __ add(r7, r7, Operand(8)); - } else { - FloatingPointHelper::ConvertIntToDouble(masm, - r9, - FloatingPointHelper::kCoreRegisters, - d0, - r0, - r1, - lr, - s0); - __ Strd(r0, r1, MemOperand(r7, 8, PostIndex)); - } - __ b(&entry); - - // Hole found, store the-hole NaN. - __ bind(&convert_hole); - __ Strd(r4, r5, MemOperand(r7, 8, PostIndex)); - - __ bind(&entry); - __ cmp(r7, r6); - __ b(lt, &loop); - - if (!vfp3_supported) __ Pop(r1, r0); - __ pop(lr); -} - - -void ElementsTransitionGenerator::GenerateDoubleToObject( - MacroAssembler* masm, Label* fail) { - // ----------- S t a t e ------------- - // -- r0 : value - // -- r1 : key - // -- r2 : receiver - // -- lr : return address - // -- r3 : target map, scratch for subsequent call - // -- r4 : scratch (elements) - // ----------------------------------- - Label entry, loop, convert_hole, gc_required; - - __ push(lr); - __ Push(r3, r2, r1, r0); - - __ ldr(r4, FieldMemOperand(r2, JSObject::kElementsOffset)); - __ ldr(r5, FieldMemOperand(r4, FixedArray::kLengthOffset)); - // r4: source FixedDoubleArray - // r5: number of elements (smi-tagged) - - // Allocate new FixedArray. - __ mov(r0, Operand(FixedDoubleArray::kHeaderSize)); - __ add(r0, r0, Operand(r5, LSL, 1)); - __ AllocateInNewSpace(r0, r6, r7, r9, &gc_required, NO_ALLOCATION_FLAGS); - // r6: destination FixedArray, not tagged as heap object - __ LoadRoot(r9, Heap::kFixedArrayMapRootIndex); - __ str(r9, MemOperand(r6, HeapObject::kMapOffset)); - // Set destination FixedDoubleArray's length. - __ str(r5, MemOperand(r6, FixedDoubleArray::kLengthOffset)); - - // Prepare for conversion loop. - __ add(r4, r4, Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag + 4)); - __ add(r3, r6, Operand(FixedArray::kHeaderSize)); - __ add(r6, r6, Operand(kHeapObjectTag)); - __ add(r5, r3, Operand(r5, LSL, 1)); - __ LoadRoot(r7, Heap::kTheHoleValueRootIndex); - __ LoadRoot(r9, Heap::kHeapNumberMapRootIndex); - // Using offsetted addresses in r4 to fully take advantage of post-indexing. - // r3: begin of destination FixedArray element fields, not tagged - // r4: begin of source FixedDoubleArray element fields, not tagged, +4 - // r5: end of destination FixedArray, not tagged - // r6: destination FixedArray - // r7: the-hole pointer - // r9: heap number map - __ b(&entry); - - // Call into runtime if GC is required. - __ bind(&gc_required); - __ Pop(r3, r2, r1, r0); - __ pop(lr); - __ b(fail); - - __ bind(&loop); - __ ldr(r1, MemOperand(r4, 8, PostIndex)); - // lr: current element's upper 32 bit - // r4: address of next element's upper 32 bit - __ cmp(r1, Operand(kHoleNanUpper32)); - __ b(eq, &convert_hole); - - // Non-hole double, copy value into a heap number. - __ AllocateHeapNumber(r2, r0, lr, r9, &gc_required); - // r2: new heap number - __ ldr(r0, MemOperand(r4, 12, NegOffset)); - __ Strd(r0, r1, FieldMemOperand(r2, HeapNumber::kValueOffset)); - __ mov(r0, r3); - __ str(r2, MemOperand(r3, 4, PostIndex)); - __ RecordWrite(r6, - r0, - r2, - kLRHasBeenSaved, - kDontSaveFPRegs, - EMIT_REMEMBERED_SET, - OMIT_SMI_CHECK); - __ b(&entry); - - // Replace the-hole NaN with the-hole pointer. - __ bind(&convert_hole); - __ str(r7, MemOperand(r3, 4, PostIndex)); - - __ bind(&entry); - __ cmp(r3, r5); - __ b(lt, &loop); - - __ Pop(r3, r2, r1, r0); - // Update receiver's map. - __ str(r3, FieldMemOperand(r2, HeapObject::kMapOffset)); - __ RecordWriteField(r2, - HeapObject::kMapOffset, - r3, - r9, - kLRHasBeenSaved, - kDontSaveFPRegs, - EMIT_REMEMBERED_SET, - OMIT_SMI_CHECK); - // Replace receiver's backing store with newly created and filled FixedArray. - __ str(r6, FieldMemOperand(r2, JSObject::kElementsOffset)); - __ RecordWriteField(r2, - JSObject::kElementsOffset, - r6, - r9, - kLRHasBeenSaved, - kDontSaveFPRegs, - EMIT_REMEMBERED_SET, - OMIT_SMI_CHECK); - __ pop(lr); -} - -#undef __ - } } // namespace v8::internal #endif // V8_TARGET_ARCH_ARM diff --git a/deps/v8/src/arm/codegen-arm.h b/deps/v8/src/arm/codegen-arm.h index f54231c9299..1c0d508d2d3 100644 --- a/deps/v8/src/arm/codegen-arm.h +++ b/deps/v8/src/arm/codegen-arm.h @@ -29,6 +29,7 @@ #define V8_ARM_CODEGEN_ARM_H_ #include "ast.h" +#include "code-stubs-arm.h" #include "ic-inl.h" namespace v8 { diff --git a/deps/v8/src/arm/deoptimizer-arm.cc b/deps/v8/src/arm/deoptimizer-arm.cc index 8505c7dfc1c..bb03d740d15 100644 --- a/deps/v8/src/arm/deoptimizer-arm.cc +++ b/deps/v8/src/arm/deoptimizer-arm.cc @@ -100,6 +100,7 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) { } } + #ifdef DEBUG // Destroy the code which is not supposed to be run again. int instructions = @@ -177,13 +178,16 @@ void Deoptimizer::PatchStackCheckCodeAt(Code* unoptimized_code, Memory::uint32_at(stack_check_address_pointer) = reinterpret_cast(replacement_code->entry()); - unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch( - unoptimized_code, pc_after - 2 * kInstrSize, replacement_code); + RelocInfo rinfo(pc_after - 2 * kInstrSize, + RelocInfo::CODE_TARGET, + 0, + unoptimized_code); + unoptimized_code->GetHeap()->incremental_marking()->RecordWriteIntoCode( + unoptimized_code, &rinfo, replacement_code); } -void Deoptimizer::RevertStackCheckCodeAt(Code* unoptimized_code, - Address pc_after, +void Deoptimizer::RevertStackCheckCodeAt(Address pc_after, Code* check_code, Code* replacement_code) { const int kInstrSize = Assembler::kInstrSize; @@ -205,8 +209,8 @@ void Deoptimizer::RevertStackCheckCodeAt(Code* unoptimized_code, Memory::uint32_at(stack_check_address_pointer) = reinterpret_cast(check_code->entry()); - check_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch( - unoptimized_code, pc_after - 2 * kInstrSize, check_code); + check_code->GetHeap()->incremental_marking()-> + RecordCodeTargetPatch(pc_after - 2 * kInstrSize, check_code); } @@ -723,6 +727,7 @@ void Deoptimizer::EntryGenerator::Generate() { __ ldr(r3, MemOperand(r2, FrameDescription::frame_size_offset())); __ bind(&inner_push_loop); __ sub(r3, r3, Operand(sizeof(uint32_t))); + // __ add(r6, r2, Operand(r3, LSL, 1)); __ add(r6, r2, Operand(r3)); __ ldr(r7, MemOperand(r6, FrameDescription::frame_content_offset())); __ push(r7); @@ -756,9 +761,8 @@ void Deoptimizer::EntryGenerator::Generate() { __ pop(ip); // remove lr // Set up the roots register. - ExternalReference roots_array_start = - ExternalReference::roots_array_start(isolate); - __ mov(r10, Operand(roots_array_start)); + ExternalReference roots_address = ExternalReference::roots_address(isolate); + __ mov(r10, Operand(roots_address)); __ pop(ip); // remove pc __ pop(r7); // get continuation, leave pc on stack diff --git a/deps/v8/src/arm/full-codegen-arm.cc b/deps/v8/src/arm/full-codegen-arm.cc index 497a2954644..353ce5b1064 100644 --- a/deps/v8/src/arm/full-codegen-arm.cc +++ b/deps/v8/src/arm/full-codegen-arm.cc @@ -269,10 +269,7 @@ void FullCodeGenerator::Generate(CompilationInfo* info) { // constant. if (scope()->is_function_scope() && scope()->function() != NULL) { int ignored = 0; - VariableProxy* proxy = scope()->function(); - ASSERT(proxy->var()->mode() == CONST || - proxy->var()->mode() == CONST_HARMONY); - EmitDeclaration(proxy, proxy->var()->mode(), NULL, &ignored); + EmitDeclaration(scope()->function(), CONST, NULL, &ignored); } VisitDeclarations(scope()->declarations()); } @@ -721,8 +718,6 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, // need to "declare" it at runtime to make sure it actually exists in the // local context. Variable* variable = proxy->var(); - bool binding_needs_init = - mode == CONST || mode == CONST_HARMONY || mode == LET; switch (variable->location()) { case Variable::UNALLOCATED: ++(*global_count); @@ -734,7 +729,7 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, Comment cmnt(masm_, "[ Declaration"); VisitForAccumulatorValue(function); __ str(result_register(), StackOperand(variable)); - } else if (binding_needs_init) { + } else if (mode == CONST || mode == LET) { Comment cmnt(masm_, "[ Declaration"); __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); __ str(ip, StackOperand(variable)); @@ -768,7 +763,7 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); PrepareForBailoutForId(proxy->id(), NO_REGISTERS); - } else if (binding_needs_init) { + } else if (mode == CONST || mode == LET) { Comment cmnt(masm_, "[ Declaration"); __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); __ str(ip, ContextOperand(cp, variable->index())); @@ -780,13 +775,9 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, case Variable::LOOKUP: { Comment cmnt(masm_, "[ Declaration"); __ mov(r2, Operand(variable->name())); - // Declaration nodes are always introduced in one of four modes. - ASSERT(mode == VAR || - mode == CONST || - mode == CONST_HARMONY || - mode == LET); - PropertyAttributes attr = (mode == CONST || mode == CONST_HARMONY) - ? READ_ONLY : NONE; + // Declaration nodes are always introduced in one of three modes. + ASSERT(mode == VAR || mode == CONST || mode == LET); + PropertyAttributes attr = (mode == CONST) ? READ_ONLY : NONE; __ mov(r1, Operand(Smi::FromInt(attr))); // Push initial value, if any. // Note: For variables we must not push an initial value (such as @@ -796,7 +787,7 @@ void FullCodeGenerator::EmitDeclaration(VariableProxy* proxy, __ Push(cp, r2, r1); // Push initial value for function declaration. VisitForStackValue(function); - } else if (binding_needs_init) { + } else if (mode == CONST || mode == LET) { __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); __ Push(cp, r2, r1, r0); } else { @@ -938,17 +929,11 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ bind(&done_convert); __ push(r0); - // Check for proxies. - Label call_runtime; - STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); - __ CompareObjectType(r0, r1, r1, LAST_JS_PROXY_TYPE); - __ b(le, &call_runtime); - // Check cache validity in generated code. This is a fast case for // the JSObject::IsSimpleEnum cache validity checks. If we cannot // guarantee cache validity, call the runtime system to check cache // validity or get the property names in a fixed array. - Label next; + Label next, call_runtime; // Preload a couple of values used in the loop. Register empty_fixed_array_value = r6; __ LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex); @@ -1027,16 +1012,9 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ jmp(&loop); // We got a fixed array in register r0. Iterate through that. - Label non_proxy; __ bind(&fixed_array); - __ mov(r1, Operand(Smi::FromInt(1))); // Smi indicates slow check - __ ldr(r2, MemOperand(sp, 0 * kPointerSize)); // Get enumerated object - STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); - __ CompareObjectType(r2, r3, r3, LAST_JS_PROXY_TYPE); - __ b(gt, &non_proxy); - __ mov(r1, Operand(Smi::FromInt(0))); // Zero indicates proxy - __ bind(&non_proxy); - __ Push(r1, r0); // Smi and array + __ mov(r1, Operand(Smi::FromInt(0))); // Map (0) - force slow check. + __ Push(r1, r0); __ ldr(r1, FieldMemOperand(r0, FixedArray::kLengthOffset)); __ mov(r0, Operand(Smi::FromInt(0))); __ Push(r1, r0); // Fixed array length (as smi) and initial index. @@ -1053,23 +1031,18 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); __ ldr(r3, MemOperand(r2, r0, LSL, kPointerSizeLog2 - kSmiTagSize)); - // Get the expected map from the stack or a smi in the + // Get the expected map from the stack or a zero map in the // permanent slow case into register r2. __ ldr(r2, MemOperand(sp, 3 * kPointerSize)); // Check if the expected map still matches that of the enumerable. - // If not, we may have to filter the key. + // If not, we have to filter the key. Label update_each; __ ldr(r1, MemOperand(sp, 4 * kPointerSize)); __ ldr(r4, FieldMemOperand(r1, HeapObject::kMapOffset)); __ cmp(r4, Operand(r2)); __ b(eq, &update_each); - // For proxies, no filtering is done. - // TODO(rossberg): What if only a prototype is a proxy? Not specified yet. - __ cmp(r2, Operand(Smi::FromInt(0))); - __ b(eq, &update_each); - // Convert the entry to a string or (smi) 0 if it isn't a property // any more. If the property has been removed while iterating, we // just skip it. @@ -1124,7 +1097,7 @@ void FullCodeGenerator::EmitNewClosure(Handle info, !pretenure && scope()->is_function_scope() && info->num_literals() == 0) { - FastNewClosureStub stub(info->strict_mode_flag()); + FastNewClosureStub stub(info->strict_mode() ? kStrictMode : kNonStrictMode); __ mov(r0, Operand(info)); __ push(r0); __ CallStub(&stub); @@ -1155,7 +1128,7 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, Scope* s = scope(); while (s != NULL) { if (s->num_heap_slots() > 0) { - if (s->calls_non_strict_eval()) { + if (s->calls_eval()) { // Check that extension is NULL. __ ldr(temp, ContextOperand(current, Context::EXTENSION_INDEX)); __ tst(temp, temp); @@ -1168,7 +1141,7 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, } // If no outer scope calls eval, we do not need to check more // context extensions. - if (!s->outer_scope_calls_non_strict_eval() || s->is_eval_scope()) break; + if (!s->outer_scope_calls_eval() || s->is_eval_scope()) break; s = s->outer_scope(); } @@ -1212,7 +1185,7 @@ MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { if (s->num_heap_slots() > 0) { - if (s->calls_non_strict_eval()) { + if (s->calls_eval()) { // Check that extension is NULL. __ ldr(temp, ContextOperand(context, Context::EXTENSION_INDEX)); __ tst(temp, temp); @@ -1251,12 +1224,11 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var, Variable* local = var->local_if_not_shadowed(); __ ldr(r0, ContextSlotOperandCheckExtensions(local, slow)); if (local->mode() == CONST || - local->mode() == CONST_HARMONY || local->mode() == LET) { __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); if (local->mode() == CONST) { __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); - } else { // LET || CONST_HARMONY + } else { // LET __ b(ne, done); __ mov(r0, Operand(var->name())); __ push(r0); @@ -1294,15 +1266,13 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { Comment cmnt(masm_, var->IsContextSlot() ? "Context variable" : "Stack variable"); - if (!var->binding_needs_init()) { + if (var->mode() != LET && var->mode() != CONST) { context()->Plug(var); } else { // Let and const need a read barrier. GetVar(r0, var); __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); - if (var->mode() == LET || var->mode() == CONST_HARMONY) { - // Throw a reference error when using an uninitialized let/const - // binding in harmony mode. + if (var->mode() == LET) { Label done; __ b(ne, &done); __ mov(r0, Operand(var->name())); @@ -1310,8 +1280,6 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { __ CallRuntime(Runtime::kThrowReferenceError, 1); __ bind(&done); } else { - // Uninitalized const bindings outside of harmony mode are unholed. - ASSERT(var->mode() == CONST); __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq); } context()->Plug(r0); @@ -1499,19 +1467,13 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { ZoneList* subexprs = expr->values(); int length = subexprs->length(); - Handle constant_elements = expr->constant_elements(); - ASSERT_EQ(2, constant_elements->length()); - ElementsKind constant_elements_kind = - static_cast(Smi::cast(constant_elements->get(0))->value()); - Handle constant_elements_values( - FixedArrayBase::cast(constant_elements->get(1))); __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); - __ mov(r1, Operand(constant_elements)); + __ mov(r1, Operand(expr->constant_elements())); __ Push(r3, r2, r1); - if (constant_elements_values->map() == + if (expr->constant_elements()->map() == isolate()->heap()->fixed_cow_array_map()) { FastCloneShallowArrayStub stub( FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length); @@ -1523,14 +1485,8 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); } else { - ASSERT(constant_elements_kind == FAST_ELEMENTS || - constant_elements_kind == FAST_SMI_ONLY_ELEMENTS || - FLAG_smi_only_arrays); - FastCloneShallowArrayStub::Mode mode = - constant_elements_kind == FAST_DOUBLE_ELEMENTS - ? FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS - : FastCloneShallowArrayStub::CLONE_ELEMENTS; - FastCloneShallowArrayStub stub(mode, length); + FastCloneShallowArrayStub stub( + FastCloneShallowArrayStub::CLONE_ELEMENTS, length); __ CallStub(&stub); } @@ -1553,56 +1509,24 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { } VisitForAccumulatorValue(subexpr); + // Store the subexpression value in the array's elements. __ ldr(r6, MemOperand(sp)); // Copy of array literal. __ ldr(r1, FieldMemOperand(r6, JSObject::kElementsOffset)); - __ ldr(r2, FieldMemOperand(r6, JSObject::kMapOffset)); int offset = FixedArray::kHeaderSize + (i * kPointerSize); - - Label element_done; - Label double_elements; - Label smi_element; - Label slow_elements; - Label fast_elements; - __ CheckFastElements(r2, r3, &double_elements); - - // FAST_SMI_ONLY_ELEMENTS or FAST_ELEMENTS - __ JumpIfSmi(result_register(), &smi_element); - __ CheckFastSmiOnlyElements(r2, r3, &fast_elements); - - // Store into the array literal requires a elements transition. Call into - // the runtime. - __ bind(&slow_elements); - __ push(r6); // Copy of array literal. - __ mov(r1, Operand(Smi::FromInt(i))); - __ mov(r2, Operand(Smi::FromInt(NONE))); // PropertyAttributes - __ mov(r3, Operand(Smi::FromInt(strict_mode_flag()))); // Strict mode. - __ Push(r1, result_register(), r2, r3); - __ CallRuntime(Runtime::kSetProperty, 5); - __ b(&element_done); - - // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS. - __ bind(&double_elements); - __ mov(r3, Operand(Smi::FromInt(i))); - __ StoreNumberToDoubleElements(result_register(), r3, r6, r1, r4, r5, r9, - r7, &slow_elements); - __ b(&element_done); - - // Array literal has ElementsKind of FAST_ELEMENTS and value is an object. - __ bind(&fast_elements); __ str(result_register(), FieldMemOperand(r1, offset)); - // Update the write barrier for the array store. + + Label no_map_change; + __ JumpIfSmi(result_register(), &no_map_change); + // Update the write barrier for the array store with r0 as the scratch + // register. __ RecordWriteField( r1, offset, result_register(), r2, kLRHasBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); - __ b(&element_done); - - // Array literal has ElementsKind of FAST_SMI_ONLY_ELEMENTS or - // FAST_ELEMENTS, and value is Smi. - __ bind(&smi_element); - __ str(result_register(), FieldMemOperand(r1, offset)); - // Fall through - - __ bind(&element_done); + __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); + __ CheckFastSmiOnlyElements(r3, r2, &no_map_change); + __ push(r6); // Copy of array literal. + __ CallRuntime(Runtime::kNonSmiElementStored, 1); + __ bind(&no_map_change); PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); } @@ -1979,9 +1903,8 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, } } - } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) { - // Assignment to var or initializing assignment to let/const - // in harmony mode. + } else if (var->mode() != CONST) { + // Assignment to var or initializing assignment to let. if (var->IsStackAllocated() || var->IsContextSlot()) { MemOperand location = VarOperand(var, r1); if (FLAG_debug_code && op == Token::INIT_LET) { @@ -2861,8 +2784,7 @@ void FullCodeGenerator::EmitRandomHeapNumber(ZoneList* args) { // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). if (CpuFeatures::IsSupported(VFP3)) { __ PrepareCallCFunction(1, r0); - __ ldr(r0, ContextOperand(context_register(), Context::GLOBAL_INDEX)); - __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalContextOffset)); + __ mov(r0, Operand(ExternalReference::isolate_address())); __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); CpuFeatures::Scope scope(VFP3); @@ -2882,9 +2804,8 @@ void FullCodeGenerator::EmitRandomHeapNumber(ZoneList* args) { __ mov(r0, r4); } else { __ PrepareCallCFunction(2, r0); - __ ldr(r1, ContextOperand(context_register(), Context::GLOBAL_INDEX)); __ mov(r0, Operand(r4)); - __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalContextOffset)); + __ mov(r1, Operand(ExternalReference::isolate_address())); __ CallCFunction( ExternalReference::fill_heap_number_with_random_function(isolate()), 2); } @@ -4150,25 +4071,33 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { case Token::EQ_STRICT: case Token::EQ: cond = eq; + __ pop(r1); break; case Token::LT: cond = lt; + __ pop(r1); break; case Token::GT: - cond = gt; + // Reverse left and right sides to obtain ECMA-262 conversion order. + cond = lt; + __ mov(r1, result_register()); + __ pop(r0); break; case Token::LTE: - cond = le; + // Reverse left and right sides to obtain ECMA-262 conversion order. + cond = ge; + __ mov(r1, result_register()); + __ pop(r0); break; case Token::GTE: cond = ge; + __ pop(r1); break; case Token::IN: case Token::INSTANCEOF: default: UNREACHABLE(); } - __ pop(r1); bool inline_smi_code = ShouldInlineSmiCase(op); JumpPatchSite patch_site(masm_); diff --git a/deps/v8/src/arm/ic-arm.cc b/deps/v8/src/arm/ic-arm.cc index 18d4a9fa8b5..6e0badca1d7 100644 --- a/deps/v8/src/arm/ic-arm.cc +++ b/deps/v8/src/arm/ic-arm.cc @@ -382,10 +382,10 @@ Object* CallIC_Miss(Arguments args); // The generated code does not accept smi keys. // The generated code falls through if both probes miss. -void CallICBase::GenerateMonomorphicCacheProbe(MacroAssembler* masm, - int argc, - Code::Kind kind, - Code::ExtraICState extra_state) { +static void GenerateMonomorphicCacheProbe(MacroAssembler* masm, + int argc, + Code::Kind kind, + Code::ExtraICState extra_ic_state) { // ----------- S t a t e ------------- // -- r1 : receiver // -- r2 : name @@ -395,7 +395,7 @@ void CallICBase::GenerateMonomorphicCacheProbe(MacroAssembler* masm, // Probe the stub cache. Code::Flags flags = Code::ComputeFlags(kind, MONOMORPHIC, - extra_state, + extra_ic_state, NORMAL, argc); Isolate::Current()->stub_cache()->GenerateProbe( @@ -464,7 +464,7 @@ static void GenerateFunctionTailCall(MacroAssembler* masm, } -void CallICBase::GenerateNormal(MacroAssembler* masm, int argc) { +static void GenerateCallNormal(MacroAssembler* masm, int argc) { // ----------- S t a t e ------------- // -- r2 : name // -- lr : return address @@ -486,10 +486,10 @@ void CallICBase::GenerateNormal(MacroAssembler* masm, int argc) { } -void CallICBase::GenerateMiss(MacroAssembler* masm, - int argc, - IC::UtilityId id, - Code::ExtraICState extra_state) { +static void GenerateCallMiss(MacroAssembler* masm, + int argc, + IC::UtilityId id, + Code::ExtraICState extra_ic_state) { // ----------- S t a t e ------------- // -- r2 : name // -- lr : return address @@ -541,7 +541,7 @@ void CallICBase::GenerateMiss(MacroAssembler* masm, } // Invoke the function. - CallKind call_kind = CallICBase::Contextual::decode(extra_state) + CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state) ? CALL_AS_FUNCTION : CALL_AS_METHOD; ParameterCount actual(argc); @@ -553,6 +553,18 @@ void CallICBase::GenerateMiss(MacroAssembler* masm, } +void CallIC::GenerateMiss(MacroAssembler* masm, + int argc, + Code::ExtraICState extra_ic_state) { + // ----------- S t a t e ------------- + // -- r2 : name + // -- lr : return address + // ----------------------------------- + + GenerateCallMiss(masm, argc, IC::kCallIC_Miss, extra_ic_state); +} + + void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc, Code::ExtraICState extra_ic_state) { @@ -568,6 +580,27 @@ void CallIC::GenerateMegamorphic(MacroAssembler* masm, } +void CallIC::GenerateNormal(MacroAssembler* masm, int argc) { + // ----------- S t a t e ------------- + // -- r2 : name + // -- lr : return address + // ----------------------------------- + + GenerateCallNormal(masm, argc); + GenerateMiss(masm, argc, Code::kNoExtraICState); +} + + +void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) { + // ----------- S t a t e ------------- + // -- r2 : name + // -- lr : return address + // ----------------------------------- + + GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss, Code::kNoExtraICState); +} + + void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { // ----------- S t a t e ------------- // -- r2 : name @@ -685,7 +718,7 @@ void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { __ JumpIfSmi(r2, &miss); __ IsObjectJSStringType(r2, r0, &miss); - CallICBase::GenerateNormal(masm, argc); + GenerateCallNormal(masm, argc); __ bind(&miss); GenerateMiss(masm, argc); } @@ -1211,47 +1244,6 @@ void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) { } -void KeyedStoreIC::GenerateTransitionElementsSmiToDouble(MacroAssembler* masm) { - // ---------- S t a t e -------------- - // -- r2 : receiver - // -- r3 : target map - // -- lr : return address - // ----------------------------------- - // Must return the modified receiver in r0. - if (!FLAG_trace_elements_transitions) { - Label fail; - ElementsTransitionGenerator::GenerateSmiOnlyToDouble(masm, &fail); - __ mov(r0, r2); - __ Ret(); - __ bind(&fail); - } - - __ push(r2); - __ TailCallRuntime(Runtime::kTransitionElementsSmiToDouble, 1, 1); -} - - -void KeyedStoreIC::GenerateTransitionElementsDoubleToObject( - MacroAssembler* masm) { - // ---------- S t a t e -------------- - // -- r2 : receiver - // -- r3 : target map - // -- lr : return address - // ----------------------------------- - // Must return the modified receiver in r0. - if (!FLAG_trace_elements_transitions) { - Label fail; - ElementsTransitionGenerator::GenerateDoubleToObject(masm, &fail); - __ mov(r0, r2); - __ Ret(); - __ bind(&fail); - } - - __ push(r2); - __ TailCallRuntime(Runtime::kTransitionElementsDoubleToObject, 1, 1); -} - - void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm, StrictModeFlag strict_mode) { // ---------- S t a t e -------------- @@ -1567,9 +1559,11 @@ Condition CompareIC::ComputeCondition(Token::Value op) { case Token::LT: return lt; case Token::GT: - return gt; + // Reverse left and right operands to obtain ECMA-262 conversion order. + return lt; case Token::LTE: - return le; + // Reverse left and right operands to obtain ECMA-262 conversion order. + return ge; case Token::GTE: return ge; default: diff --git a/deps/v8/src/arm/lithium-arm.cc b/deps/v8/src/arm/lithium-arm.cc index 51978421d88..84959397b65 100644 --- a/deps/v8/src/arm/lithium-arm.cc +++ b/deps/v8/src/arm/lithium-arm.cc @@ -391,12 +391,6 @@ void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) { } -void LTransitionElementsKind::PrintDataTo(StringStream* stream) { - object()->PrintTo(stream); - stream->Add(" %p -> %p", *original_map(), *transitioned_map()); -} - - LChunk::LChunk(CompilationInfo* info, HGraph* graph) : spill_slot_count_(0), info_(info), @@ -1410,10 +1404,12 @@ LInstruction* LChunkBuilder::DoPower(HPower* instr) { LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) { + Token::Value op = instr->token(); ASSERT(instr->left()->representation().IsTagged()); ASSERT(instr->right()->representation().IsTagged()); - LOperand* left = UseFixed(instr->left(), r1); - LOperand* right = UseFixed(instr->right(), r0); + bool reversed = (op == Token::GT || op == Token::LTE); + LOperand* left = UseFixed(instr->left(), reversed ? r0 : r1); + LOperand* right = UseFixed(instr->right(), reversed ? r1 : r0); LCmpT* result = new LCmpT(left, right); return MarkAsCall(DefineFixed(result, r0), instr); } @@ -1425,8 +1421,8 @@ LInstruction* LChunkBuilder::DoCompareIDAndBranch( if (r.IsInteger32()) { ASSERT(instr->left()->representation().IsInteger32()); ASSERT(instr->right()->representation().IsInteger32()); - LOperand* left = UseRegisterOrConstantAtStart(instr->left()); - LOperand* right = UseRegisterOrConstantAtStart(instr->right()); + LOperand* left = UseRegisterAtStart(instr->left()); + LOperand* right = UseRegisterAtStart(instr->right()); return new LCmpIDAndBranch(left, right); } else { ASSERT(r.IsDouble()); @@ -1974,26 +1970,6 @@ LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) { } -LInstruction* LChunkBuilder::DoTransitionElementsKind( - HTransitionElementsKind* instr) { - if (instr->original_map()->elements_kind() == FAST_SMI_ONLY_ELEMENTS && - instr->transitioned_map()->elements_kind() == FAST_ELEMENTS) { - LOperand* object = UseRegister(instr->object()); - LOperand* new_map_reg = TempRegister(); - LTransitionElementsKind* result = - new LTransitionElementsKind(object, new_map_reg, NULL); - return DefineSameAsFirst(result); - } else { - LOperand* object = UseFixed(instr->object(), r0); - LOperand* fixed_object_reg = FixedTemp(r2); - LOperand* new_map_reg = FixedTemp(r3); - LTransitionElementsKind* result = - new LTransitionElementsKind(object, new_map_reg, fixed_object_reg); - return MarkAsCall(DefineFixed(result, r0), instr); - } -} - - LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) { bool needs_write_barrier = instr->NeedsWriteBarrier(); diff --git a/deps/v8/src/arm/lithium-arm.h b/deps/v8/src/arm/lithium-arm.h index 5733bd08da8..73c7e459c3d 100644 --- a/deps/v8/src/arm/lithium-arm.h +++ b/deps/v8/src/arm/lithium-arm.h @@ -162,7 +162,6 @@ class LCodeGen; V(ThisFunction) \ V(Throw) \ V(ToFastProperties) \ - V(TransitionElementsKind) \ V(Typeof) \ V(TypeofIsAndBranch) \ V(UnaryMathOperation) \ @@ -1261,6 +1260,7 @@ class LStoreContextSlot: public LTemplateInstruction<0, 2, 0> { LOperand* context() { return InputAt(0); } LOperand* value() { return InputAt(1); } int slot_index() { return hydrogen()->slot_index(); } + int needs_write_barrier() { return hydrogen()->NeedsWriteBarrier(); } virtual void PrintDataTo(StringStream* stream); }; @@ -1277,9 +1277,7 @@ class LPushArgument: public LTemplateInstruction<0, 1, 0> { class LThisFunction: public LTemplateInstruction<1, 0, 0> { - public: DECLARE_CONCRETE_INSTRUCTION(ThisFunction, "this-function") - DECLARE_HYDROGEN_ACCESSOR(ThisFunction) }; @@ -1563,6 +1561,7 @@ class LStoreNamedField: public LTemplateInstruction<0, 2, 0> { Handle name() const { return hydrogen()->name(); } bool is_in_object() { return hydrogen()->is_in_object(); } int offset() { return hydrogen()->offset(); } + bool needs_write_barrier() { return hydrogen()->NeedsWriteBarrier(); } Handle transition() const { return hydrogen()->transition(); } }; @@ -1582,8 +1581,7 @@ class LStoreNamedGeneric: public LTemplateInstruction<0, 2, 0> { LOperand* object() { return inputs_[0]; } LOperand* value() { return inputs_[1]; } Handle name() const { return hydrogen()->name(); } - StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); } - bool strict_mode() { return strict_mode_flag() == kStrictMode; } + bool strict_mode() { return hydrogen()->strict_mode(); } }; @@ -1671,30 +1669,6 @@ class LStoreKeyedSpecializedArrayElement: public LTemplateInstruction<0, 3, 0> { }; -class LTransitionElementsKind: public LTemplateInstruction<1, 1, 2> { - public: - LTransitionElementsKind(LOperand* object, - LOperand* new_map_temp, - LOperand* temp_reg) { - inputs_[0] = object; - temps_[0] = new_map_temp; - temps_[1] = temp_reg; - } - - DECLARE_CONCRETE_INSTRUCTION(TransitionElementsKind, - "transition-elements-kind") - DECLARE_HYDROGEN_ACCESSOR(TransitionElementsKind) - - virtual void PrintDataTo(StringStream* stream); - - LOperand* object() { return inputs_[0]; } - LOperand* new_map_reg() { return temps_[0]; } - LOperand* temp_reg() { return temps_[1]; } - Handle original_map() { return hydrogen()->original_map(); } - Handle transitioned_map() { return hydrogen()->transitioned_map(); } -}; - - class LStringAdd: public LTemplateInstruction<1, 2, 0> { public: LStringAdd(LOperand* left, LOperand* right) { diff --git a/deps/v8/src/arm/lithium-codegen-arm.cc b/deps/v8/src/arm/lithium-codegen-arm.cc index 4cf7df4c78d..70ef8848167 100644 --- a/deps/v8/src/arm/lithium-codegen-arm.cc +++ b/deps/v8/src/arm/lithium-codegen-arm.cc @@ -410,12 +410,6 @@ int LCodeGen::ToInteger32(LConstantOperand* op) const { } -double LCodeGen::ToDouble(LConstantOperand* op) const { - Handle value = chunk_->LookupLiteral(op); - return value->Number(); -} - - Operand LCodeGen::ToOperand(LOperand* op) { if (op->IsConstantOperand()) { LConstantOperand* const_op = LConstantOperand::cast(op); @@ -1711,44 +1705,30 @@ Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { } +void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) { + __ cmp(ToRegister(left), ToRegister(right)); +} + + void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { LOperand* left = instr->InputAt(0); LOperand* right = instr->InputAt(1); int false_block = chunk_->LookupDestination(instr->false_block_id()); int true_block = chunk_->LookupDestination(instr->true_block_id()); - Condition cond = TokenToCondition(instr->op(), false); - - if (left->IsConstantOperand() && right->IsConstantOperand()) { - // We can statically evaluate the comparison. - double left_val = ToDouble(LConstantOperand::cast(left)); - double right_val = ToDouble(LConstantOperand::cast(right)); - int next_block = - EvalComparison(instr->op(), left_val, right_val) ? true_block - : false_block; - EmitGoto(next_block); + + if (instr->is_double()) { + // Compare left and right as doubles and load the + // resulting flags into the normal status register. + __ VFPCompareAndSetFlags(ToDoubleRegister(left), ToDoubleRegister(right)); + // If a NaN is involved, i.e. the result is unordered (V set), + // jump to false block label. + __ b(vs, chunk_->GetAssemblyLabel(false_block)); } else { - if (instr->is_double()) { - // Compare left and right operands as doubles and load the - // resulting flags into the normal status register. - __ VFPCompareAndSetFlags(ToDoubleRegister(left), ToDoubleRegister(right)); - // If a NaN is involved, i.e. the result is unordered (V set), - // jump to false block label. - __ b(vs, chunk_->GetAssemblyLabel(false_block)); - } else { - if (right->IsConstantOperand()) { - __ cmp(ToRegister(left), - Operand(ToInteger32(LConstantOperand::cast(right)))); - } else if (left->IsConstantOperand()) { - __ cmp(ToRegister(right), - Operand(ToInteger32(LConstantOperand::cast(left)))); - // We transposed the operands. Reverse the condition. - cond = ReverseCondition(cond); - } else { - __ cmp(ToRegister(left), ToRegister(right)); - } - } - EmitBranch(true_block, false_block, cond); + EmitCmpI(left, right); } + + Condition cc = TokenToCondition(instr->op(), instr->is_double()); + EmitBranch(true_block, false_block, cc); } @@ -2196,6 +2176,9 @@ void LCodeGen::DoCmpT(LCmpT* instr) { __ cmp(r0, Operand(0)); // This instruction also signals no smi code inlined. Condition condition = ComputeCompareCondition(op); + if (op == Token::GT || op == Token::LTE) { + condition = ReverseCondition(condition); + } __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex, condition); @@ -2268,19 +2251,13 @@ void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { __ str(value, FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); // Cells are always in the remembered set. - if (instr->hydrogen()->NeedsWriteBarrier()) { - HType type = instr->hydrogen()->value()->type(); - SmiCheck check_needed = - type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; - __ RecordWriteField(scratch, - JSGlobalPropertyCell::kValueOffset, - value, - scratch2, - kLRHasBeenSaved, - kSaveFPRegs, - OMIT_REMEMBERED_SET, - check_needed); - } + __ RecordWriteField(scratch, + JSGlobalPropertyCell::kValueOffset, + value, + scratch2, + kLRHasBeenSaved, + kSaveFPRegs, + OMIT_REMEMBERED_SET); } @@ -2308,18 +2285,13 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { Register value = ToRegister(instr->value()); MemOperand target = ContextOperand(context, instr->slot_index()); __ str(value, target); - if (instr->hydrogen()->NeedsWriteBarrier()) { - HType type = instr->hydrogen()->value()->type(); - SmiCheck check_needed = - type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; + if (instr->needs_write_barrier()) { __ RecordWriteContextSlot(context, target.offset(), value, scratch0(), kLRHasBeenSaved, - kSaveFPRegs, - EMIT_REMEMBERED_SET, - check_needed); + kSaveFPRegs); } } @@ -2340,7 +2312,7 @@ void LCodeGen::EmitLoadFieldOrConstantFunction(Register result, Register object, Handle type, Handle name) { - LookupResult lookup(isolate()); + LookupResult lookup; type->LookupInDescriptors(NULL, *name, &lookup); ASSERT(lookup.IsProperty() && (lookup.type() == FIELD || lookup.type() == CONSTANT_FUNCTION)); @@ -2806,7 +2778,7 @@ void LCodeGen::DoPushArgument(LPushArgument* instr) { void LCodeGen::DoThisFunction(LThisFunction* instr) { Register result = ToRegister(instr->result()); - LoadHeapObject(result, instr->hydrogen()->closure()); + __ ldr(result, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); } @@ -3325,36 +3297,21 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { } // Do the store. - HType type = instr->hydrogen()->value()->type(); - SmiCheck check_needed = - type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; if (instr->is_in_object()) { __ str(value, FieldMemOperand(object, offset)); - if (instr->hydrogen()->NeedsWriteBarrier()) { + if (instr->needs_write_barrier()) { // Update the write barrier for the object for in-object properties. - __ RecordWriteField(object, - offset, - value, - scratch, - kLRHasBeenSaved, - kSaveFPRegs, - EMIT_REMEMBERED_SET, - check_needed); + __ RecordWriteField( + object, offset, value, scratch, kLRHasBeenSaved, kSaveFPRegs); } } else { __ ldr(scratch, FieldMemOperand(object, JSObject::kPropertiesOffset)); __ str(value, FieldMemOperand(scratch, offset)); - if (instr->hydrogen()->NeedsWriteBarrier()) { + if (instr->needs_write_barrier()) { // Update the write barrier for the properties array. // object is used as a scratch register. - __ RecordWriteField(scratch, - offset, - value, - object, - kLRHasBeenSaved, - kSaveFPRegs, - EMIT_REMEMBERED_SET, - check_needed); + __ RecordWriteField( + scratch, offset, value, object, kLRHasBeenSaved, kSaveFPRegs); } } } @@ -3405,18 +3362,9 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) { } if (instr->hydrogen()->NeedsWriteBarrier()) { - HType type = instr->hydrogen()->value()->type(); - SmiCheck check_needed = - type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; // Compute address of modified element and store it into key register. __ add(key, scratch, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); - __ RecordWrite(elements, - key, - value, - kLRHasBeenSaved, - kSaveFPRegs, - EMIT_REMEMBERED_SET, - check_needed); + __ RecordWrite(elements, key, value, kLRHasBeenSaved, kSaveFPRegs); } } @@ -3539,48 +3487,6 @@ void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { } -void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { - Register object_reg = ToRegister(instr->object()); - Register new_map_reg = ToRegister(instr->new_map_reg()); - Register scratch = scratch0(); - - Handle from_map = instr->original_map(); - Handle to_map = instr->transitioned_map(); - ElementsKind from_kind = from_map->elements_kind(); - ElementsKind to_kind = to_map->elements_kind(); - - Label not_applicable; - __ ldr(scratch, FieldMemOperand(object_reg, HeapObject::kMapOffset)); - __ cmp(scratch, Operand(from_map)); - __ b(ne, ¬_applicable); - __ mov(new_map_reg, Operand(to_map)); - if (from_kind == FAST_SMI_ONLY_ELEMENTS && to_kind == FAST_ELEMENTS) { - __ str(new_map_reg, FieldMemOperand(object_reg, HeapObject::kMapOffset)); - // Write barrier. - __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, - scratch, kLRHasBeenSaved, kDontSaveFPRegs); - } else if (from_kind == FAST_SMI_ONLY_ELEMENTS && - to_kind == FAST_DOUBLE_ELEMENTS) { - Register fixed_object_reg = ToRegister(instr->temp_reg()); - ASSERT(fixed_object_reg.is(r2)); - ASSERT(new_map_reg.is(r3)); - __ mov(fixed_object_reg, object_reg); - CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), - RelocInfo::CODE_TARGET, instr); - } else if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) { - Register fixed_object_reg = ToRegister(instr->temp_reg()); - ASSERT(fixed_object_reg.is(r2)); - ASSERT(new_map_reg.is(r3)); - __ mov(fixed_object_reg, object_reg); - CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), - RelocInfo::CODE_TARGET, instr); - } else { - UNREACHABLE(); - } - __ bind(¬_applicable); -} - - void LCodeGen::DoStringAdd(LStringAdd* instr) { __ push(ToRegister(instr->left())); __ push(ToRegister(instr->right())); @@ -4297,15 +4203,10 @@ void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { - Handle constant_elements = instr->hydrogen()->constant_elements(); - ASSERT_EQ(2, constant_elements->length()); - ElementsKind constant_elements_kind = - static_cast(Smi::cast(constant_elements->get(0))->value()); - __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); __ mov(r2, Operand(Smi::FromInt(instr->hydrogen()->literal_index()))); - __ mov(r1, Operand(constant_elements)); + __ mov(r1, Operand(instr->hydrogen()->constant_elements())); __ Push(r3, r2, r1); // Pick the right runtime function or stub to call. @@ -4322,9 +4223,7 @@ void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr); } else { FastCloneShallowArrayStub::Mode mode = - constant_elements_kind == FAST_DOUBLE_ELEMENTS - ? FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS - : FastCloneShallowArrayStub::CLONE_ELEMENTS; + FastCloneShallowArrayStub::CLONE_ELEMENTS; FastCloneShallowArrayStub stub(mode, length); CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); } @@ -4416,7 +4315,8 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { Handle shared_info = instr->shared_info(); bool pretenure = instr->hydrogen()->pretenure(); if (!pretenure && shared_info->num_literals() == 0) { - FastNewClosureStub stub(shared_info->strict_mode_flag()); + FastNewClosureStub stub( + shared_info->strict_mode() ? kStrictMode : kNonStrictMode); __ mov(r1, Operand(shared_info)); __ push(r1); CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); @@ -4449,9 +4349,8 @@ void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { false_label, input, instr->type_literal()); - if (final_branch_condition != kNoCondition) { - EmitBranch(true_block, false_block, final_branch_condition); - } + + EmitBranch(true_block, false_block, final_branch_condition); } @@ -4521,7 +4420,9 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label, final_branch_condition = eq; } else { + final_branch_condition = ne; __ b(false_label); + // A dead branch instruction will be generated after this point. } return final_branch_condition; diff --git a/deps/v8/src/arm/lithium-codegen-arm.h b/deps/v8/src/arm/lithium-codegen-arm.h index b01e4967d77..711e4595e7a 100644 --- a/deps/v8/src/arm/lithium-codegen-arm.h +++ b/deps/v8/src/arm/lithium-codegen-arm.h @@ -86,7 +86,6 @@ class LCodeGen BASE_EMBEDDED { SwVfpRegister flt_scratch, DoubleRegister dbl_scratch); int ToInteger32(LConstantOperand* op) const; - double ToDouble(LConstantOperand* op) const; Operand ToOperand(LOperand* op); MemOperand ToMemOperand(LOperand* op) const; // Returns a MemOperand pointing to the high word of a DoubleStackSlot. @@ -140,8 +139,8 @@ class LCodeGen BASE_EMBEDDED { bool is_done() const { return status_ == DONE; } bool is_aborted() const { return status_ == ABORTED; } - StrictModeFlag strict_mode_flag() const { - return info()->strict_mode_flag(); + int strict_mode_flag() const { + return info()->is_strict_mode() ? kStrictMode : kNonStrictMode; } LChunk* chunk() const { return chunk_; } @@ -207,7 +206,7 @@ class LCodeGen BASE_EMBEDDED { LInstruction* instr); // Generate a direct call to a known function. Expects the function - // to be in r1. + // to be in edi. void CallKnownFunction(Handle function, int arity, LInstruction* instr, @@ -264,6 +263,7 @@ class LCodeGen BASE_EMBEDDED { static Condition TokenToCondition(Token::Value op, bool is_unsigned); void EmitGoto(int block); void EmitBranch(int left_block, int right_block, Condition cc); + void EmitCmpI(LOperand* left, LOperand* right); void EmitNumberUntagD(Register input, DoubleRegister result, bool deoptimize_on_undefined, @@ -272,10 +272,8 @@ class LCodeGen BASE_EMBEDDED { // Emits optimized code for typeof x == "y". Modifies input register. // Returns the condition on which a final split to // true and false label should be made, to optimize fallthrough. - Condition EmitTypeofIs(Label* true_label, - Label* false_label, - Register input, - Handle type_name); + Condition EmitTypeofIs(Label* true_label, Label* false_label, + Register input, Handle type_name); // Emits optimized code for %_IsObject(x). Preserves input register. // Returns the condition on which a final split to diff --git a/deps/v8/src/arm/macro-assembler-arm.cc b/deps/v8/src/arm/macro-assembler-arm.cc index cf4258c83a2..918f9ebe060 100644 --- a/deps/v8/src/arm/macro-assembler-arm.cc +++ b/deps/v8/src/arm/macro-assembler-arm.cc @@ -1101,16 +1101,24 @@ void MacroAssembler::InvokeFunction(JSFunction* function, // You can't call a function without a valid frame. ASSERT(flag == JUMP_FUNCTION || has_frame()); + ASSERT(function->is_compiled()); + // Get the function and setup the context. mov(r1, Operand(Handle(function))); ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); + // Invoke the cached code. + Handle code(function->code()); ParameterCount expected(function->shared()->formal_parameter_count()); - // We call indirectly through the code field in the function to - // allow recompilation to take effect without changing any of the - // call sites. - ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); - InvokeCode(r3, expected, actual, flag, NullCallWrapper(), call_kind); + if (V8::UseCrankshaft()) { + // TODO(kasperl): For now, we always call indirectly through the + // code field in the function to allow recompilation to take effect + // without changing any of the call sites. + ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); + InvokeCode(r3, expected, actual, flag, NullCallWrapper(), call_kind); + } else { + InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET, flag, call_kind); + } } @@ -1594,7 +1602,6 @@ void MacroAssembler::AllocateInNewSpace(Register object_size, ASSERT(!result.is(scratch1)); ASSERT(!result.is(scratch2)); ASSERT(!scratch1.is(scratch2)); - ASSERT(!object_size.is(ip)); ASSERT(!result.is(ip)); ASSERT(!scratch1.is(ip)); ASSERT(!scratch2.is(ip)); @@ -2023,8 +2030,7 @@ void MacroAssembler::DispatchMap(Register obj, void MacroAssembler::TryGetFunctionPrototype(Register function, Register result, Register scratch, - Label* miss, - bool miss_on_bound_function) { + Label* miss) { // Check that the receiver isn't a smi. JumpIfSmi(function, miss); @@ -2032,16 +2038,6 @@ void MacroAssembler::TryGetFunctionPrototype(Register function, CompareObjectType(function, result, scratch, JS_FUNCTION_TYPE); b(ne, miss); - if (miss_on_bound_function) { - ldr(scratch, - FieldMemOperand(function, JSFunction::kSharedFunctionInfoOffset)); - ldr(scratch, - FieldMemOperand(scratch, SharedFunctionInfo::kCompilerHintsOffset)); - tst(scratch, - Operand(Smi::FromInt(1 << SharedFunctionInfo::kBoundFunction))); - b(ne, miss); - } - // Make sure that the function has an instance prototype. Label non_instance; ldrb(scratch, FieldMemOperand(result, Map::kBitFieldOffset)); @@ -3151,10 +3147,8 @@ void MacroAssembler::CountLeadingZeros(Register zeros, // Answer. #ifdef CAN_USE_ARMV5_INSTRUCTIONS clz(zeros, source); // This instruction is only supported after ARM5. #else - // Order of the next two lines is important: zeros register - // can be the same as source register. - Move(scratch, source); mov(zeros, Operand(0, RelocInfo::NONE)); + Move(scratch, source); // Top 16. tst(scratch, Operand(0xffff0000)); add(zeros, zeros, Operand(16), LeaveCC, eq); diff --git a/deps/v8/src/arm/macro-assembler-arm.h b/deps/v8/src/arm/macro-assembler-arm.h index 90c4b375491..8ee468a9170 100644 --- a/deps/v8/src/arm/macro-assembler-arm.h +++ b/deps/v8/src/arm/macro-assembler-arm.h @@ -320,11 +320,8 @@ class MacroAssembler: public Assembler { } // Push four registers. Pushes leftmost register first (to highest address). - void Push(Register src1, - Register src2, - Register src3, - Register src4, - Condition cond = al) { + void Push(Register src1, Register src2, + Register src3, Register src4, Condition cond = al) { ASSERT(!src1.is(src2)); ASSERT(!src2.is(src3)); ASSERT(!src1.is(src3)); @@ -363,57 +360,6 @@ class MacroAssembler: public Assembler { } } - // Pop three registers. Pops rightmost register first (from lower address). - void Pop(Register src1, Register src2, Register src3, Condition cond = al) { - ASSERT(!src1.is(src2)); - ASSERT(!src2.is(src3)); - ASSERT(!src1.is(src3)); - if (src1.code() > src2.code()) { - if (src2.code() > src3.code()) { - ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond); - } else { - ldr(src3, MemOperand(sp, 4, PostIndex), cond); - ldm(ia_w, sp, src1.bit() | src2.bit(), cond); - } - } else { - Pop(src2, src3, cond); - str(src1, MemOperand(sp, 4, PostIndex), cond); - } - } - - // Pop four registers. Pops rightmost register first (from lower address). - void Pop(Register src1, - Register src2, - Register src3, - Register src4, - Condition cond = al) { - ASSERT(!src1.is(src2)); - ASSERT(!src2.is(src3)); - ASSERT(!src1.is(src3)); - ASSERT(!src1.is(src4)); - ASSERT(!src2.is(src4)); - ASSERT(!src3.is(src4)); - if (src1.code() > src2.code()) { - if (src2.code() > src3.code()) { - if (src3.code() > src4.code()) { - ldm(ia_w, - sp, - src1.bit() | src2.bit() | src3.bit() | src4.bit(), - cond); - } else { - ldr(src4, MemOperand(sp, 4, PostIndex), cond); - ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond); - } - } else { - Pop(src3, src4, cond); - ldm(ia_w, sp, src1.bit() | src2.bit(), cond); - } - } else { - Pop(src2, src3, src4, cond); - ldr(src1, MemOperand(sp, 4, PostIndex), cond); - } - } - // Push and pop the registers that can hold pointers, as defined by the // RegList constant kSafepointSavedRegisters. void PushSafepointRegisters(); @@ -726,8 +672,7 @@ class MacroAssembler: public Assembler { void TryGetFunctionPrototype(Register function, Register result, Register scratch, - Label* miss, - bool miss_on_bound_function = false); + Label* miss); // Compare object type for heap object. heap_object contains a non-Smi // whose object type should be compared with the given type. This both diff --git a/deps/v8/src/arm/regexp-macro-assembler-arm.cc b/deps/v8/src/arm/regexp-macro-assembler-arm.cc index b212f9f6e6a..c8764679383 100644 --- a/deps/v8/src/arm/regexp-macro-assembler-arm.cc +++ b/deps/v8/src/arm/regexp-macro-assembler-arm.cc @@ -1111,11 +1111,6 @@ int RegExpMacroAssemblerARM::CheckStackGuardState(Address* return_address, frame_entry(re_frame, kInputString) = *subject; frame_entry(re_frame, kInputStart) = new_address; frame_entry(re_frame, kInputEnd) = new_address + byte_length; - } else if (frame_entry(re_frame, kInputString) != *subject) { - // Subject string might have been a ConsString that underwent - // short-circuiting during GC. That will not change start_address but - // will change pointer inside the subject handle. - frame_entry(re_frame, kInputString) = *subject; } return 0; diff --git a/deps/v8/src/arm/simulator-arm.cc b/deps/v8/src/arm/simulator-arm.cc index 542cc302d30..57042026223 100644 --- a/deps/v8/src/arm/simulator-arm.cc +++ b/deps/v8/src/arm/simulator-arm.cc @@ -1268,9 +1268,9 @@ void Simulator::WriteDW(int32_t addr, int32_t value1, int32_t value2) { // Returns the limit of the stack area to enable checking for stack overflows. uintptr_t Simulator::StackLimit() const { - // Leave a safety margin of 512 bytes to prevent overrunning the stack when + // Leave a safety margin of 256 bytes to prevent overrunning the stack when // pushing values. - return reinterpret_cast(stack_) + 512; + return reinterpret_cast(stack_) + 256; } diff --git a/deps/v8/src/arm/stub-cache-arm.cc b/deps/v8/src/arm/stub-cache-arm.cc index f9a10c4f253..4558afe68aa 100644 --- a/deps/v8/src/arm/stub-cache-arm.cc +++ b/deps/v8/src/arm/stub-cache-arm.cc @@ -95,63 +95,7 @@ static void ProbeTable(Isolate* isolate, // must always call a backup property check that is complete. // This function is safe to call if the receiver has fast properties. // Name must be a symbol and receiver must be a heap object. -static void GenerateDictionaryNegativeLookup(MacroAssembler* masm, - Label* miss_label, - Register receiver, - Handle name, - Register scratch0, - Register scratch1) { - ASSERT(name->IsSymbol()); - Counters* counters = masm->isolate()->counters(); - __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); - __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); - - Label done; - - const int kInterceptorOrAccessCheckNeededMask = - (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); - - // Bail out if the receiver has a named interceptor or requires access checks. - Register map = scratch1; - __ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); - __ ldrb(scratch0, FieldMemOperand(map, Map::kBitFieldOffset)); - __ tst(scratch0, Operand(kInterceptorOrAccessCheckNeededMask)); - __ b(ne, miss_label); - - // Check that receiver is a JSObject. - __ ldrb(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); - __ cmp(scratch0, Operand(FIRST_SPEC_OBJECT_TYPE)); - __ b(lt, miss_label); - - // Load properties array. - Register properties = scratch0; - __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); - // Check that the properties array is a dictionary. - __ ldr(map, FieldMemOperand(properties, HeapObject::kMapOffset)); - Register tmp = properties; - __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); - __ cmp(map, tmp); - __ b(ne, miss_label); - - // Restore the temporarily used register. - __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); - - - StringDictionaryLookupStub::GenerateNegativeLookup(masm, - miss_label, - &done, - receiver, - properties, - name, - scratch1); - __ bind(&done); - __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); -} - - -// TODO(kmillikin): Eliminate this function when the stub cache is fully -// handlified. -MUST_USE_RESULT static MaybeObject* TryGenerateDictionaryNegativeLookup( +MUST_USE_RESULT static MaybeObject* GenerateDictionaryNegativeLookup( MacroAssembler* masm, Label* miss_label, Register receiver, @@ -194,7 +138,7 @@ MUST_USE_RESULT static MaybeObject* TryGenerateDictionaryNegativeLookup( __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); - MaybeObject* result = StringDictionaryLookupStub::TryGenerateNegativeLookup( + MaybeObject* result = StringDictionaryLookupStub::GenerateNegativeLookup( masm, miss_label, &done, @@ -315,10 +259,8 @@ void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( // are loaded directly otherwise the property is loaded from the properties // fixed array. void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, - Register dst, - Register src, - Handle holder, - int index) { + Register dst, Register src, + JSObject* holder, int index) { // Adjust for the number of properties stored in the holder. index -= holder->map()->inobject_properties(); if (index < 0) { @@ -425,9 +367,9 @@ void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, // may be clobbered. Upon branch to miss_label, the receiver and name // registers have their original values. void StubCompiler::GenerateStoreField(MacroAssembler* masm, - Handle object, + JSObject* object, int index, - Handle transition, + Map* transition, Register receiver_reg, Register name_reg, Register scratch, @@ -453,11 +395,11 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm, ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); // Perform map transition for the receiver if necessary. - if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) { + if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) { // The properties must be extended before we can store the value. // We jump to a runtime call that extends the properties array. __ push(receiver_reg); - __ mov(r2, Operand(transition)); + __ mov(r2, Operand(Handle(transition))); __ Push(r2, r0); __ TailCallExternalReference( ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), @@ -467,10 +409,10 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm, return; } - if (!transition.is_null()) { + if (transition != NULL) { // Update the map of the object; no write barrier updating is // needed because the map is never in new space. - __ mov(ip, Operand(transition)); + __ mov(ip, Operand(Handle(transition))); __ str(ip, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); } @@ -525,15 +467,20 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm, void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); - Handle code = (kind == Code::LOAD_IC) - ? masm->isolate()->builtins()->LoadIC_Miss() - : masm->isolate()->builtins()->KeyedLoadIC_Miss(); - __ Jump(code, RelocInfo::CODE_TARGET); + Code* code = NULL; + if (kind == Code::LOAD_IC) { + code = masm->isolate()->builtins()->builtin(Builtins::kLoadIC_Miss); + } else { + code = masm->isolate()->builtins()->builtin(Builtins::kKeyedLoadIC_Miss); + } + + Handle ic(code); + __ Jump(ic, RelocInfo::CODE_TARGET); } static void GenerateCallFunction(MacroAssembler* masm, - Handle object, + Object* object, const ParameterCount& arguments, Label* miss, Code::ExtraICState extra_ic_state) { @@ -921,26 +868,7 @@ class CallInterceptorCompiler BASE_EMBEDDED { // Generate code to check that a global property cell is empty. Create // the property cell at compilation time if no cell exists for the // property. -static void GenerateCheckPropertyCell(MacroAssembler* masm, - Handle global, - Handle name, - Register scratch, - Label* miss) { - Handle cell = - GlobalObject::EnsurePropertyCell(global, name); - ASSERT(cell->value()->IsTheHole()); - __ mov(scratch, Operand(cell)); - __ ldr(scratch, - FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); - __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); - __ cmp(scratch, ip); - __ b(ne, miss); -} - - -// TODO(kmillikin): Eliminate this function when the stub cache is fully -// handlified. -MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCell( +MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCell( MacroAssembler* masm, GlobalObject* global, String* name, @@ -961,32 +889,9 @@ MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCell( return cell; } - // Calls GenerateCheckPropertyCell for each global object in the prototype chain // from object to (but not including) holder. -static void GenerateCheckPropertyCells(MacroAssembler* masm, - Handle object, - Handle holder, - Handle name, - Register scratch, - Label* miss) { - Handle current = object; - while (!current.is_identical_to(holder)) { - if (current->IsGlobalObject()) { - GenerateCheckPropertyCell(masm, - Handle::cast(current), - name, - scratch, - miss); - } - current = Handle(JSObject::cast(current->GetPrototype())); - } -} - - -// TODO(kmillikin): Eliminate this function when the stub cache is fully -// handlified. -MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCells( +MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCells( MacroAssembler* masm, JSObject* object, JSObject* holder, @@ -997,7 +902,7 @@ MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCells( while (current != holder) { if (current->IsGlobalObject()) { // Returns a cell or a failure. - MaybeObject* result = TryGenerateCheckPropertyCell( + MaybeObject* result = GenerateCheckPropertyCell( masm, GlobalObject::cast(current), name, @@ -1122,112 +1027,6 @@ static void GenerateUInt2Double(MacroAssembler* masm, #define __ ACCESS_MASM(masm()) -Register StubCompiler::CheckPrototypes(Handle object, - Register object_reg, - Handle holder, - Register holder_reg, - Register scratch1, - Register scratch2, - Handle name, - int save_at_depth, - Label* miss) { - // Make sure there's no overlap between holder and object registers. - ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); - ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) - && !scratch2.is(scratch1)); - - // Keep track of the current object in register reg. - Register reg = object_reg; - int depth = 0; - - if (save_at_depth == depth) { - __ str(reg, MemOperand(sp)); - } - - // Check the maps in the prototype chain. - // Traverse the prototype chain from the object and do map checks. - Handle current = object; - while (!current.is_identical_to(holder)) { - ++depth; - - // Only global objects and objects that do not require access - // checks are allowed in stubs. - ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); - - Handle prototype(JSObject::cast(current->GetPrototype())); - if (!current->HasFastProperties() && - !current->IsJSGlobalObject() && - !current->IsJSGlobalProxy()) { - if (!name->IsSymbol()) { - name = factory()->LookupSymbol(name); - } - ASSERT(current->property_dictionary()->FindEntry(*name) == - StringDictionary::kNotFound); - - GenerateDictionaryNegativeLookup(masm(), miss, reg, name, - scratch1, scratch2); - - __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); - reg = holder_reg; // From now on the object will be in holder_reg. - __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); - } else { - Handle current_map(current->map()); - __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); - __ cmp(scratch1, Operand(current_map)); - // Branch on the result of the map check. - __ b(ne, miss); - // Check access rights to the global object. This has to happen after - // the map check so that we know that the object is actually a global - // object. - if (current->IsJSGlobalProxy()) { - __ CheckAccessGlobalProxy(reg, scratch2, miss); - } - reg = holder_reg; // From now on the object will be in holder_reg. - - if (heap()->InNewSpace(*prototype)) { - // The prototype is in new space; we cannot store a reference to it - // in the code. Load it from the map. - __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); - } else { - // The prototype is in old space; load it directly. - __ mov(reg, Operand(prototype)); - } - } - - if (save_at_depth == depth) { - __ str(reg, MemOperand(sp)); - } - - // Go to the next object in the prototype chain. - current = prototype; - } - - // Log the check depth. - LOG(masm()->isolate(), IntEvent("check-maps-depth", depth + 1)); - - // Check the holder map. - __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); - __ cmp(scratch1, Operand(Handle(current->map()))); - __ b(ne, miss); - - // Perform security check for access to the global object. - ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); - if (holder->IsJSGlobalProxy()) { - __ CheckAccessGlobalProxy(reg, scratch1, miss); - } - - // If we've skipped any global objects, it's not enough to verify that - // their maps haven't changed. We also need to check that the property - // cell for the property is still empty. - GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); - - // Return the register containing the holder. - return reg; -} - - -// TODO(kmillikin): Eliminate this function when the stub cache is fully -// handlified. Register StubCompiler::CheckPrototypes(JSObject* object, Register object_reg, JSObject* holder, @@ -1277,13 +1076,12 @@ Register StubCompiler::CheckPrototypes(JSObject* object, ASSERT(current->property_dictionary()->FindEntry(name) == StringDictionary::kNotFound); - MaybeObject* negative_lookup = - TryGenerateDictionaryNegativeLookup(masm(), - miss, - reg, - name, - scratch1, - scratch2); + MaybeObject* negative_lookup = GenerateDictionaryNegativeLookup(masm(), + miss, + reg, + name, + scratch1, + scratch2); if (negative_lookup->IsFailure()) { set_failure(Failure::cast(negative_lookup)); return reg; @@ -1352,17 +1150,17 @@ Register StubCompiler::CheckPrototypes(JSObject* object, ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); if (holder->IsJSGlobalProxy()) { __ CheckAccessGlobalProxy(reg, scratch1, miss); - } + }; // If we've skipped any global objects, it's not enough to verify // that their maps haven't changed. We also need to check that the // property cell for the property is still empty. - MaybeObject* result = TryGenerateCheckPropertyCells(masm(), - object, - holder, - name, - scratch1, - miss); + MaybeObject* result = GenerateCheckPropertyCells(masm(), + object, + holder, + name, + scratch1, + miss); if (result->IsFailure()) set_failure(Failure::cast(result)); // Return the register containing the holder. @@ -1370,44 +1168,45 @@ Register StubCompiler::CheckPrototypes(JSObject* object, } -void StubCompiler::GenerateLoadField(Handle object, - Handle holder, +void StubCompiler::GenerateLoadField(JSObject* object, + JSObject* holder, Register receiver, Register scratch1, Register scratch2, Register scratch3, int index, - Handle name, + String* name, Label* miss) { // Check that the receiver isn't a smi. __ JumpIfSmi(receiver, miss); // Check that the maps haven't changed. - Register reg = CheckPrototypes( - object, receiver, holder, scratch1, scratch2, scratch3, name, miss); + Register reg = + CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3, + name, miss); GenerateFastPropertyLoad(masm(), r0, reg, holder, index); __ Ret(); } -void StubCompiler::GenerateLoadConstant(Handle object, - Handle holder, +void StubCompiler::GenerateLoadConstant(JSObject* object, + JSObject* holder, Register receiver, Register scratch1, Register scratch2, Register scratch3, - Handle value, - Handle name, + Object* value, + String* name, Label* miss) { // Check that the receiver isn't a smi. __ JumpIfSmi(receiver, miss); // Check that the maps haven't changed. - CheckPrototypes( - object, receiver, holder, scratch1, scratch2, scratch3, name, miss); + CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3, name, + miss); // Return the constant value. - __ mov(r0, Operand(value)); + __ mov(r0, Operand(Handle(value))); __ Ret(); } @@ -1566,8 +1365,7 @@ void StubCompiler::GenerateLoadInterceptor(JSObject* object, // We found FIELD property in prototype chain of interceptor's holder. // Retrieve a field from field's holder. GenerateFastPropertyLoad(masm(), r0, holder_reg, - Handle(lookup->holder()), - lookup->GetFieldIndex()); + lookup->holder(), lookup->GetFieldIndex()); __ Ret(); } else { // We found CALLBACKS property in prototype chain of interceptor's @@ -1618,9 +1416,9 @@ void StubCompiler::GenerateLoadInterceptor(JSObject* object, } -void CallStubCompiler::GenerateNameCheck(Handle name, Label* miss) { +void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) { if (kind_ == Code::KEYED_CALL_IC) { - __ cmp(r2, Operand(name)); + __ cmp(r2, Operand(Handle(name))); __ b(ne, miss); } } @@ -1680,22 +1478,11 @@ void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, } -void CallStubCompiler::GenerateMissBranch() { - Handle code = +MaybeObject* CallStubCompiler::GenerateMissBranch() { + MaybeObject* maybe_obj = isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), kind_, - extra_state_); - __ Jump(code, RelocInfo::CODE_TARGET); -} - - -// TODO(kmillikin): Eliminate this function when the stub cache is fully -// handlified. -MaybeObject* CallStubCompiler::TryGenerateMissBranch() { - MaybeObject* maybe_obj = - isolate()->stub_cache()->TryComputeCallMiss(arguments().immediate(), - kind_, - extra_state_); + extra_ic_state_); Object* obj; if (!maybe_obj->ToObject(&obj)) return maybe_obj; __ Jump(Handle(Code::cast(obj)), RelocInfo::CODE_TARGET); @@ -1703,10 +1490,10 @@ MaybeObject* CallStubCompiler::TryGenerateMissBranch() { } -Handle CallStubCompiler::CompileCallField(Handle object, - Handle holder, +MaybeObject* CallStubCompiler::CompileCallField(JSObject* object, + JSObject* holder, int index, - Handle name) { + String* name) { // ----------- S t a t e ------------- // -- r2 : name // -- lr : return address @@ -1726,11 +1513,12 @@ Handle CallStubCompiler::CompileCallField(Handle object, Register reg = CheckPrototypes(object, r0, holder, r1, r3, r4, name, &miss); GenerateFastPropertyLoad(masm(), r1, reg, holder, index); - GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); + GenerateCallFunction(masm(), object, arguments(), &miss, extra_ic_state_); // Handle call cache miss. __ bind(&miss); - GenerateMissBranch(); + MaybeObject* maybe_result = GenerateMissBranch(); + if (maybe_result->IsFailure()) return maybe_result; // Return the generated code. return GetCode(FIELD, name); @@ -1755,7 +1543,7 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, Label miss; - GenerateNameCheck(Handle(name), &miss); + GenerateNameCheck(name, &miss); Register receiver = r1; @@ -1831,7 +1619,7 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, __ bind(&with_write_barrier); __ ldr(r6, FieldMemOperand(receiver, HeapObject::kMapOffset)); - __ CheckFastObjectElements(r6, r6, &call_builtin); + __ CheckFastSmiOnlyElements(r6, r6, &call_builtin); // Save new length. __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); @@ -1921,11 +1709,11 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, // Handle call cache miss. __ bind(&miss); - MaybeObject* maybe_result = TryGenerateMissBranch(); + MaybeObject* maybe_result = GenerateMissBranch(); if (maybe_result->IsFailure()) return maybe_result; // Return the generated code. - return TryGetCode(function); + return GetCode(function); } @@ -1950,7 +1738,7 @@ MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, Register receiver = r1; Register elements = r3; - GenerateNameCheck(Handle(name), &miss); + GenerateNameCheck(name, &miss); // Get the receiver from the stack const int argc = arguments().immediate(); @@ -2010,11 +1798,11 @@ MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, // Handle call cache miss. __ bind(&miss); - MaybeObject* maybe_result = TryGenerateMissBranch(); + MaybeObject* maybe_result = GenerateMissBranch(); if (maybe_result->IsFailure()) return maybe_result; // Return the generated code. - return TryGetCode(function); + return GetCode(function); } @@ -2043,12 +1831,12 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( Label* index_out_of_range_label = &index_out_of_range; if (kind_ == Code::CALL_IC && - (CallICBase::StringStubState::decode(extra_state_) == + (CallICBase::StringStubState::decode(extra_ic_state_) == DEFAULT_STRING_STUB)) { index_out_of_range_label = &miss; } - GenerateNameCheck(Handle(name), &name_miss); + GenerateNameCheck(name, &name_miss); // Check that the maps starting from the prototype haven't changed. GenerateDirectLoadGlobalFunctionPrototype(masm(), @@ -2096,11 +1884,11 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( // Restore function name in r2. __ Move(r2, Handle(name)); __ bind(&name_miss); - MaybeObject* maybe_result = TryGenerateMissBranch(); + MaybeObject* maybe_result = GenerateMissBranch(); if (maybe_result->IsFailure()) return maybe_result; // Return the generated code. - return TryGetCode(function); + return GetCode(function); } @@ -2129,12 +1917,12 @@ MaybeObject* CallStubCompiler::CompileStringCharAtCall( Label* index_out_of_range_label = &index_out_of_range; if (kind_ == Code::CALL_IC && - (CallICBase::StringStubState::decode(extra_state_) == + (CallICBase::StringStubState::decode(extra_ic_state_) == DEFAULT_STRING_STUB)) { index_out_of_range_label = &miss; } - GenerateNameCheck(Handle(name), &name_miss); + GenerateNameCheck(name, &name_miss); // Check that the maps starting from the prototype haven't changed. GenerateDirectLoadGlobalFunctionPrototype(masm(), @@ -2184,11 +1972,11 @@ MaybeObject* CallStubCompiler::CompileStringCharAtCall( // Restore function name in r2. __ Move(r2, Handle(name)); __ bind(&name_miss); - MaybeObject* maybe_result = TryGenerateMissBranch(); + MaybeObject* maybe_result = GenerateMissBranch(); if (maybe_result->IsFailure()) return maybe_result; // Return the generated code. - return TryGetCode(function); + return GetCode(function); } @@ -2213,7 +2001,7 @@ MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall( if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); Label miss; - GenerateNameCheck(Handle(name), &miss); + GenerateNameCheck(name, &miss); if (cell == NULL) { __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); @@ -2256,11 +2044,11 @@ MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall( __ bind(&miss); // r2: function name. - MaybeObject* maybe_result = TryGenerateMissBranch(); + MaybeObject* maybe_result = GenerateMissBranch(); if (maybe_result->IsFailure()) return maybe_result; // Return the generated code. - return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); + return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); } @@ -2290,7 +2078,7 @@ MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object, if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); Label miss, slow; - GenerateNameCheck(Handle(name), &miss); + GenerateNameCheck(name, &miss); if (cell == NULL) { __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); @@ -2404,11 +2192,11 @@ MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object, __ bind(&miss); // r2: function name. - MaybeObject* maybe_result = TryGenerateMissBranch(); + MaybeObject* maybe_result = GenerateMissBranch(); if (maybe_result->IsFailure()) return maybe_result; // Return the generated code. - return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); + return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); } @@ -2432,7 +2220,7 @@ MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object, if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); Label miss; - GenerateNameCheck(Handle(name), &miss); + GenerateNameCheck(name, &miss); if (cell == NULL) { __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); @@ -2505,11 +2293,11 @@ MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object, __ bind(&miss); // r2: function name. - MaybeObject* maybe_result = TryGenerateMissBranch(); + MaybeObject* maybe_result = GenerateMissBranch(); if (maybe_result->IsFailure()) return maybe_result; // Return the generated code. - return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name); + return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); } @@ -2534,7 +2322,7 @@ MaybeObject* CallStubCompiler::CompileFastApiCall( Label miss, miss_before_stack_reserved; - GenerateNameCheck(Handle(name), &miss_before_stack_reserved); + GenerateNameCheck(name, &miss_before_stack_reserved); // Get the receiver from the stack. const int argc = arguments().immediate(); @@ -2559,11 +2347,11 @@ MaybeObject* CallStubCompiler::CompileFastApiCall( FreeSpaceForFastApiCall(masm()); __ bind(&miss_before_stack_reserved); - MaybeObject* maybe_result = TryGenerateMissBranch(); + MaybeObject* maybe_result = GenerateMissBranch(); if (maybe_result->IsFailure()) return maybe_result; // Return the generated code. - return TryGetCode(function); + return GetCode(function); } @@ -2587,7 +2375,7 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, Label miss; - GenerateNameCheck(Handle(name), &miss); + GenerateNameCheck(name, &miss); // Get the receiver from the stack const int argc = arguments().immediate(); @@ -2686,18 +2474,18 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, UNREACHABLE(); } - CallKind call_kind = CallICBase::Contextual::decode(extra_state_) + CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) ? CALL_AS_FUNCTION : CALL_AS_METHOD; __ InvokeFunction(function, arguments(), JUMP_FUNCTION, call_kind); // Handle call cache miss. __ bind(&miss); - MaybeObject* maybe_result = TryGenerateMissBranch(); + MaybeObject* maybe_result = GenerateMissBranch(); if (maybe_result->IsFailure()) return maybe_result; // Return the generated code. - return TryGetCode(function); + return GetCode(function); } @@ -2711,18 +2499,18 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, Label miss; - GenerateNameCheck(Handle(name), &miss); + GenerateNameCheck(name, &miss); // Get the number of arguments. const int argc = arguments().immediate(); - LookupResult lookup(isolate()); + LookupResult lookup; LookupPostInterceptor(holder, name, &lookup); // Get the receiver from the stack. __ ldr(r1, MemOperand(sp, argc * kPointerSize)); - CallInterceptorCompiler compiler(this, arguments(), r2, extra_state_); + CallInterceptorCompiler compiler(this, arguments(), r2, extra_ic_state_); MaybeObject* result = compiler.Compile(masm(), object, holder, @@ -2742,16 +2530,15 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, // Restore receiver. __ ldr(r0, MemOperand(sp, argc * kPointerSize)); - GenerateCallFunction(masm(), Handle(object), arguments(), &miss, - extra_state_); + GenerateCallFunction(masm(), object, arguments(), &miss, extra_ic_state_); // Handle call cache miss. __ bind(&miss); - MaybeObject* maybe_result = TryGenerateMissBranch(); + MaybeObject* maybe_result = GenerateMissBranch(); if (maybe_result->IsFailure()) return maybe_result; // Return the generated code. - return TryGetCode(INTERCEPTOR, name); + return GetCode(INTERCEPTOR, name); } @@ -2776,7 +2563,7 @@ MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object, Label miss; - GenerateNameCheck(Handle(name), &miss); + GenerateNameCheck(name, &miss); // Get the number of arguments. const int argc = arguments().immediate(); @@ -2798,33 +2585,39 @@ MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object, // Jump to the cached code (tail call). Counters* counters = masm()->isolate()->counters(); __ IncrementCounter(counters->call_global_inline(), 1, r3, r4); + ASSERT(function->is_compiled()); Handle code(function->code()); ParameterCount expected(function->shared()->formal_parameter_count()); - CallKind call_kind = CallICBase::Contextual::decode(extra_state_) + CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) ? CALL_AS_FUNCTION : CALL_AS_METHOD; - // We call indirectly through the code field in the function to - // allow recompilation to take effect without changing any of the - // call sites. - __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); - __ InvokeCode(r3, expected, arguments(), JUMP_FUNCTION, - NullCallWrapper(), call_kind); + if (V8::UseCrankshaft()) { + // TODO(kasperl): For now, we always call indirectly through the + // code field in the function to allow recompilation to take effect + // without changing any of the call sites. + __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); + __ InvokeCode(r3, expected, arguments(), JUMP_FUNCTION, + NullCallWrapper(), call_kind); + } else { + __ InvokeCode(code, expected, arguments(), RelocInfo::CODE_TARGET, + JUMP_FUNCTION, call_kind); + } // Handle call cache miss. __ bind(&miss); __ IncrementCounter(counters->call_global_inline_miss(), 1, r1, r3); - MaybeObject* maybe_result = TryGenerateMissBranch(); + MaybeObject* maybe_result = GenerateMissBranch(); if (maybe_result->IsFailure()) return maybe_result; // Return the generated code. - return TryGetCode(NORMAL, name); + return GetCode(NORMAL, name); } -Handle StoreStubCompiler::CompileStoreField(Handle object, +MaybeObject* StoreStubCompiler::CompileStoreField(JSObject* object, int index, - Handle transition, - Handle name) { + Map* transition, + String* name) { // ----------- S t a t e ------------- // -- r0 : value // -- r1 : receiver @@ -2833,20 +2626,24 @@ Handle StoreStubCompiler::CompileStoreField(Handle object, // ----------------------------------- Label miss; - GenerateStoreField(masm(), object, index, transition, r1, r2, r3, &miss); + GenerateStoreField(masm(), + object, + index, + transition, + r1, r2, r3, + &miss); __ bind(&miss); Handle ic = masm()->isolate()->builtins()->StoreIC_Miss(); __ Jump(ic, RelocInfo::CODE_TARGET); // Return the generated code. - return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); + return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); } -Handle StoreStubCompiler::CompileStoreCallback( - Handle object, - Handle callback, - Handle name) { +MaybeObject* StoreStubCompiler::CompileStoreCallback(JSObject* object, + AccessorInfo* callback, + String* name) { // ----------- S t a t e ------------- // -- r0 : value // -- r1 : receiver @@ -2873,7 +2670,7 @@ Handle StoreStubCompiler::CompileStoreCallback( ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); __ push(r1); // receiver - __ mov(ip, Operand(callback)); // callback info + __ mov(ip, Operand(Handle(callback))); // callback info __ Push(ip, r2, r0); // Do tail-call to the runtime system. @@ -2892,9 +2689,8 @@ Handle StoreStubCompiler::CompileStoreCallback( } -Handle StoreStubCompiler::CompileStoreInterceptor( - Handle receiver, - Handle name) { +MaybeObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, + String* name) { // ----------- S t a t e ------------- // -- r0 : value // -- r1 : receiver @@ -2941,10 +2737,9 @@ Handle StoreStubCompiler::CompileStoreInterceptor( } -Handle StoreStubCompiler::CompileStoreGlobal( - Handle object, - Handle cell, - Handle name) { +MaybeObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, + JSGlobalPropertyCell* cell, + String* name) { // ----------- S t a t e ------------- // -- r0 : value // -- r1 : receiver @@ -2962,7 +2757,7 @@ Handle StoreStubCompiler::CompileStoreGlobal( // cell could have been deleted and reintroducing the global needs // to update the property details in the property dictionary of the // global object. We bail out to the runtime system to do that. - __ mov(r4, Operand(cell)); + __ mov(r4, Operand(Handle(cell))); __ LoadRoot(r5, Heap::kTheHoleValueRootIndex); __ ldr(r6, FieldMemOperand(r4, JSGlobalPropertyCell::kValueOffset)); __ cmp(r5, r6); @@ -2995,9 +2790,9 @@ Handle StoreStubCompiler::CompileStoreGlobal( } -Handle LoadStubCompiler::CompileLoadNonexistent(Handle name, - Handle object, - Handle last) { +MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, + JSObject* object, + JSObject* last) { // ----------- S t a t e ------------- // -- r0 : receiver // -- lr : return address @@ -3013,8 +2808,15 @@ Handle LoadStubCompiler::CompileLoadNonexistent(Handle name, // If the last object in the prototype chain is a global object, // check that the global property cell is empty. if (last->IsGlobalObject()) { - GenerateCheckPropertyCell( - masm(), Handle::cast(last), name, r1, &miss); + MaybeObject* cell = GenerateCheckPropertyCell(masm(), + GlobalObject::cast(last), + name, + r1, + &miss); + if (cell->IsFailure()) { + miss.Unuse(); + return cell; + } } // Return undefined if maps of the full prototype chain are still the @@ -3026,14 +2828,14 @@ Handle LoadStubCompiler::CompileLoadNonexistent(Handle name, GenerateLoadMiss(masm(), Code::LOAD_IC); // Return the generated code. - return GetCode(NONEXISTENT, factory()->empty_string()); + return GetCode(NONEXISTENT, heap()->empty_string()); } -Handle LoadStubCompiler::CompileLoadField(Handle object, - Handle holder, +MaybeObject* LoadStubCompiler::CompileLoadField(JSObject* object, + JSObject* holder, int index, - Handle name) { + String* name) { // ----------- S t a t e ------------- // -- r0 : receiver // -- r2 : name @@ -3072,14 +2874,14 @@ MaybeObject* LoadStubCompiler::CompileLoadCallback(String* name, GenerateLoadMiss(masm(), Code::LOAD_IC); // Return the generated code. - return TryGetCode(CALLBACKS, name); + return GetCode(CALLBACKS, name); } -Handle LoadStubCompiler::CompileLoadConstant(Handle object, - Handle holder, - Handle value, - Handle name) { +MaybeObject* LoadStubCompiler::CompileLoadConstant(JSObject* object, + JSObject* holder, + Object* value, + String* name) { // ----------- S t a t e ------------- // -- r0 : receiver // -- r2 : name @@ -3106,7 +2908,7 @@ MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* object, // ----------------------------------- Label miss; - LookupResult lookup(isolate()); + LookupResult lookup; LookupPostInterceptor(holder, name, &lookup); GenerateLoadInterceptor(object, holder, @@ -3122,16 +2924,15 @@ MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* object, GenerateLoadMiss(masm(), Code::LOAD_IC); // Return the generated code. - return TryGetCode(INTERCEPTOR, name); + return GetCode(INTERCEPTOR, name); } -Handle LoadStubCompiler::CompileLoadGlobal( - Handle object, - Handle holder, - Handle cell, - Handle name, - bool is_dont_delete) { +MaybeObject* LoadStubCompiler::CompileLoadGlobal(JSObject* object, + GlobalObject* holder, + JSGlobalPropertyCell* cell, + String* name, + bool is_dont_delete) { // ----------- S t a t e ------------- // -- r0 : receiver // -- r2 : name @@ -3142,7 +2943,7 @@ Handle LoadStubCompiler::CompileLoadGlobal( // If the object is the holder then we know that it's a global // object which can only happen for contextual calls. In this case, // the receiver cannot be a smi. - if (!object.is_identical_to(holder)) { + if (object != holder) { __ JumpIfSmi(r0, &miss); } @@ -3150,7 +2951,7 @@ Handle LoadStubCompiler::CompileLoadGlobal( CheckPrototypes(object, r0, holder, r3, r4, r1, name, &miss); // Get the value from the cell. - __ mov(r3, Operand(cell)); + __ mov(r3, Operand(Handle(cell))); __ ldr(r4, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); // Check for deleted property if property can actually be deleted. @@ -3174,9 +2975,9 @@ Handle LoadStubCompiler::CompileLoadGlobal( } -Handle KeyedLoadStubCompiler::CompileLoadField(Handle name, - Handle receiver, - Handle holder, +MaybeObject* KeyedLoadStubCompiler::CompileLoadField(String* name, + JSObject* receiver, + JSObject* holder, int index) { // ----------- S t a t e ------------- // -- lr : return address @@ -3186,7 +2987,7 @@ Handle KeyedLoadStubCompiler::CompileLoadField(Handle name, Label miss; // Check the key is the cached one. - __ cmp(r0, Operand(name)); + __ cmp(r0, Operand(Handle(name))); __ b(ne, &miss); GenerateLoadField(receiver, holder, r1, r2, r3, r4, index, name, &miss); @@ -3223,15 +3024,14 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback( __ bind(&miss); GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); - return TryGetCode(CALLBACKS, name); + return GetCode(CALLBACKS, name); } -Handle KeyedLoadStubCompiler::CompileLoadConstant( - Handle name, - Handle receiver, - Handle holder, - Handle value) { +MaybeObject* KeyedLoadStubCompiler::CompileLoadConstant(String* name, + JSObject* receiver, + JSObject* holder, + Object* value) { // ----------- S t a t e ------------- // -- lr : return address // -- r0 : key @@ -3240,7 +3040,7 @@ Handle KeyedLoadStubCompiler::CompileLoadConstant( Label miss; // Check the key is the cached one. - __ cmp(r0, Operand(name)); + __ cmp(r0, Operand(Handle(name))); __ b(ne, &miss); GenerateLoadConstant(receiver, holder, r1, r2, r3, r4, value, name, &miss); @@ -3266,7 +3066,7 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, __ cmp(r0, Operand(Handle(name))); __ b(ne, &miss); - LookupResult lookup(isolate()); + LookupResult lookup; LookupPostInterceptor(holder, name, &lookup); GenerateLoadInterceptor(receiver, holder, @@ -3281,12 +3081,11 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, __ bind(&miss); GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); - return TryGetCode(INTERCEPTOR, name); + return GetCode(INTERCEPTOR, name); } -Handle KeyedLoadStubCompiler::CompileLoadArrayLength( - Handle name) { +MaybeObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) { // ----------- S t a t e ------------- // -- lr : return address // -- r0 : key @@ -3295,7 +3094,7 @@ Handle KeyedLoadStubCompiler::CompileLoadArrayLength( Label miss; // Check the key is the cached one. - __ cmp(r0, Operand(name)); + __ cmp(r0, Operand(Handle(name))); __ b(ne, &miss); GenerateLoadArrayLength(masm(), r1, r2, &miss); @@ -3306,8 +3105,7 @@ Handle KeyedLoadStubCompiler::CompileLoadArrayLength( } -Handle KeyedLoadStubCompiler::CompileLoadStringLength( - Handle name) { +MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { // ----------- S t a t e ------------- // -- lr : return address // -- r0 : key @@ -3319,7 +3117,7 @@ Handle KeyedLoadStubCompiler::CompileLoadStringLength( __ IncrementCounter(counters->keyed_load_string_length(), 1, r2, r3); // Check the key is the cached one. - __ cmp(r0, Operand(name)); + __ cmp(r0, Operand(Handle(name))); __ b(ne, &miss); GenerateLoadStringLength(masm(), r1, r2, r3, &miss, true); @@ -3332,8 +3130,7 @@ Handle KeyedLoadStubCompiler::CompileLoadStringLength( } -Handle KeyedLoadStubCompiler::CompileLoadFunctionPrototype( - Handle name) { +MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { // ----------- S t a t e ------------- // -- lr : return address // -- r0 : key @@ -3345,7 +3142,7 @@ Handle KeyedLoadStubCompiler::CompileLoadFunctionPrototype( __ IncrementCounter(counters->keyed_load_function_prototype(), 1, r2, r3); // Check the name hasn't changed. - __ cmp(r0, Operand(name)); + __ cmp(r0, Operand(Handle(name))); __ b(ne, &miss); GenerateLoadFunctionPrototype(masm(), r1, r2, r3, &miss); @@ -3357,29 +3154,33 @@ Handle KeyedLoadStubCompiler::CompileLoadFunctionPrototype( } -Handle KeyedLoadStubCompiler::CompileLoadElement( - Handle receiver_map) { +MaybeObject* KeyedLoadStubCompiler::CompileLoadElement(Map* receiver_map) { // ----------- S t a t e ------------- // -- lr : return address // -- r0 : key // -- r1 : receiver // ----------------------------------- + Code* stub; ElementsKind elements_kind = receiver_map->elements_kind(); - Handle stub = KeyedLoadElementStub(elements_kind).GetCode(); - - __ DispatchMap(r1, r2, receiver_map, stub, DO_SMI_CHECK); + MaybeObject* maybe_stub = KeyedLoadElementStub(elements_kind).TryGetCode(); + if (!maybe_stub->To(&stub)) return maybe_stub; + __ DispatchMap(r1, + r2, + Handle(receiver_map), + Handle(stub), + DO_SMI_CHECK); Handle ic = isolate()->builtins()->KeyedLoadIC_Miss(); __ Jump(ic, RelocInfo::CODE_TARGET); // Return the generated code. - return GetCode(NORMAL, factory()->empty_string()); + return GetCode(NORMAL, NULL); } -Handle KeyedLoadStubCompiler::CompileLoadPolymorphic( - MapHandleList* receiver_maps, - CodeHandleList* handler_ics) { +MaybeObject* KeyedLoadStubCompiler::CompileLoadPolymorphic( + MapList* receiver_maps, + CodeList* handler_ics) { // ----------- S t a t e ------------- // -- lr : return address // -- r0 : key @@ -3391,9 +3192,11 @@ Handle KeyedLoadStubCompiler::CompileLoadPolymorphic( int receiver_count = receiver_maps->length(); __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); for (int current = 0; current < receiver_count; ++current) { - __ mov(ip, Operand(receiver_maps->at(current))); + Handle map(receiver_maps->at(current)); + Handle code(handler_ics->at(current)); + __ mov(ip, Operand(map)); __ cmp(r2, ip); - __ Jump(handler_ics->at(current), RelocInfo::CODE_TARGET, eq); + __ Jump(code, RelocInfo::CODE_TARGET, eq); } __ bind(&miss); @@ -3401,14 +3204,14 @@ Handle KeyedLoadStubCompiler::CompileLoadPolymorphic( __ Jump(miss_ic, RelocInfo::CODE_TARGET, al); // Return the generated code. - return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); + return GetCode(NORMAL, NULL, MEGAMORPHIC); } -Handle KeyedStoreStubCompiler::CompileStoreField(Handle object, +MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, int index, - Handle transition, - Handle name) { + Map* transition, + String* name) { // ----------- S t a t e ------------- // -- r0 : value // -- r1 : name @@ -3421,12 +3224,17 @@ Handle KeyedStoreStubCompiler::CompileStoreField(Handle object, __ IncrementCounter(counters->keyed_store_field(), 1, r3, r4); // Check that the name has not changed. - __ cmp(r1, Operand(name)); + __ cmp(r1, Operand(Handle(name))); __ b(ne, &miss); // r3 is used as scratch register. r1 and r2 keep their values if a jump to // the miss label is generated. - GenerateStoreField(masm(), object, index, transition, r2, r1, r3, &miss); + GenerateStoreField(masm(), + object, + index, + transition, + r2, r1, r3, + &miss); __ bind(&miss); __ DecrementCounter(counters->keyed_store_field(), 1, r3, r4); @@ -3434,12 +3242,11 @@ Handle KeyedStoreStubCompiler::CompileStoreField(Handle object, __ Jump(ic, RelocInfo::CODE_TARGET); // Return the generated code. - return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); + return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); } -Handle KeyedStoreStubCompiler::CompileStoreElement( - Handle receiver_map) { +MaybeObject* KeyedStoreStubCompiler::CompileStoreElement(Map* receiver_map) { // ----------- S t a t e ------------- // -- r0 : value // -- r1 : key @@ -3447,25 +3254,30 @@ Handle KeyedStoreStubCompiler::CompileStoreElement( // -- lr : return address // -- r3 : scratch // ----------------------------------- + Code* stub; ElementsKind elements_kind = receiver_map->elements_kind(); bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; - Handle stub = - KeyedStoreElementStub(is_js_array, elements_kind).GetCode(); - - __ DispatchMap(r2, r3, receiver_map, stub, DO_SMI_CHECK); + MaybeObject* maybe_stub = + KeyedStoreElementStub(is_js_array, elements_kind).TryGetCode(); + if (!maybe_stub->To(&stub)) return maybe_stub; + __ DispatchMap(r2, + r3, + Handle(receiver_map), + Handle(stub), + DO_SMI_CHECK); Handle ic = isolate()->builtins()->KeyedStoreIC_Miss(); __ Jump(ic, RelocInfo::CODE_TARGET); // Return the generated code. - return GetCode(NORMAL, factory()->empty_string()); + return GetCode(NORMAL, NULL); } -Handle KeyedStoreStubCompiler::CompileStorePolymorphic( - MapHandleList* receiver_maps, - CodeHandleList* handler_stubs, - MapHandleList* transitioned_maps) { +MaybeObject* KeyedStoreStubCompiler::CompileStorePolymorphic( + MapList* receiver_maps, + CodeList* handler_stubs, + MapList* transitioned_maps) { // ----------- S t a t e ------------- // -- r0 : value // -- r1 : key @@ -3479,15 +3291,17 @@ Handle KeyedStoreStubCompiler::CompileStorePolymorphic( int receiver_count = receiver_maps->length(); __ ldr(r3, FieldMemOperand(r2, HeapObject::kMapOffset)); for (int i = 0; i < receiver_count; ++i) { - __ mov(ip, Operand(receiver_maps->at(i))); + Handle map(receiver_maps->at(i)); + Handle code(handler_stubs->at(i)); + __ mov(ip, Operand(map)); __ cmp(r3, ip); - if (transitioned_maps->at(i).is_null()) { - __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, eq); + if (transitioned_maps->at(i) == NULL) { + __ Jump(code, RelocInfo::CODE_TARGET, eq); } else { Label next_map; - __ b(ne, &next_map); - __ mov(r3, Operand(transitioned_maps->at(i))); - __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, al); + __ b(eq, &next_map); + __ mov(r4, Operand(Handle(transitioned_maps->at(i)))); + __ Jump(code, RelocInfo::CODE_TARGET, al); __ bind(&next_map); } } @@ -3497,7 +3311,7 @@ Handle KeyedStoreStubCompiler::CompileStorePolymorphic( __ Jump(miss_ic, RelocInfo::CODE_TARGET, al); // Return the generated code. - return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); + return GetCode(NORMAL, NULL, MEGAMORPHIC); } diff --git a/deps/v8/src/array.js b/deps/v8/src/array.js index 214065c7bf3..e1d7c2064e5 100644 --- a/deps/v8/src/array.js +++ b/deps/v8/src/array.js @@ -1013,22 +1013,18 @@ function ArrayFilter(f, receiver) { } if (IS_NULL_OR_UNDEFINED(receiver)) { receiver = %GetDefaultReceiver(f) || receiver; - } else if (!IS_SPEC_OBJECT(receiver)) { - receiver = ToObject(receiver); } - var result = new $Array(); - var accumulator = new InternalArray(); - var accumulator_length = 0; + var result = []; + var result_length = 0; for (var i = 0; i < length; i++) { var current = array[i]; if (!IS_UNDEFINED(current) || i in array) { if (%_CallFunction(receiver, current, i, array, f)) { - accumulator[accumulator_length++] = current; + result[result_length++] = current; } } } - %MoveArrayContents(accumulator, result); return result; } @@ -1049,8 +1045,6 @@ function ArrayForEach(f, receiver) { } if (IS_NULL_OR_UNDEFINED(receiver)) { receiver = %GetDefaultReceiver(f) || receiver; - } else if (!IS_SPEC_OBJECT(receiver)) { - receiver = ToObject(receiver); } for (var i = 0; i < length; i++) { @@ -1080,8 +1074,6 @@ function ArraySome(f, receiver) { } if (IS_NULL_OR_UNDEFINED(receiver)) { receiver = %GetDefaultReceiver(f) || receiver; - } else if (!IS_SPEC_OBJECT(receiver)) { - receiver = ToObject(receiver); } for (var i = 0; i < length; i++) { @@ -1110,8 +1102,6 @@ function ArrayEvery(f, receiver) { } if (IS_NULL_OR_UNDEFINED(receiver)) { receiver = %GetDefaultReceiver(f) || receiver; - } else if (!IS_SPEC_OBJECT(receiver)) { - receiver = ToObject(receiver); } for (var i = 0; i < length; i++) { @@ -1139,8 +1129,6 @@ function ArrayMap(f, receiver) { } if (IS_NULL_OR_UNDEFINED(receiver)) { receiver = %GetDefaultReceiver(f) || receiver; - } else if (!IS_SPEC_OBJECT(receiver)) { - receiver = ToObject(receiver); } var result = new $Array(); diff --git a/deps/v8/src/assembler.cc b/deps/v8/src/assembler.cc index 4dc2394b060..bda85e69dec 100644 --- a/deps/v8/src/assembler.cc +++ b/deps/v8/src/assembler.cc @@ -834,8 +834,8 @@ ExternalReference ExternalReference::keyed_lookup_cache_field_offsets( } -ExternalReference ExternalReference::roots_array_start(Isolate* isolate) { - return ExternalReference(isolate->heap()->roots_array_start()); +ExternalReference ExternalReference::roots_address(Isolate* isolate) { + return ExternalReference(isolate->heap()->roots_address()); } @@ -1137,23 +1137,6 @@ static int native_compare_doubles(double y, double x) { } -bool EvalComparison(Token::Value op, double op1, double op2) { - ASSERT(Token::IsCompareOp(op)); - switch (op) { - case Token::EQ: - case Token::EQ_STRICT: return (op1 == op2); - case Token::NE: return (op1 != op2); - case Token::LT: return (op1 < op2); - case Token::GT: return (op1 > op2); - case Token::LTE: return (op1 <= op2); - case Token::GTE: return (op1 >= op2); - default: - UNREACHABLE(); - return false; - } -} - - ExternalReference ExternalReference::double_fp_operation( Token::Value operation, Isolate* isolate) { typedef double BinaryFPOperation(double x, double y); diff --git a/deps/v8/src/assembler.h b/deps/v8/src/assembler.h index 5b713637591..e5661c9f126 100644 --- a/deps/v8/src/assembler.h +++ b/deps/v8/src/assembler.h @@ -279,17 +279,14 @@ class RelocInfo BASE_EMBEDDED { // this relocation applies to; // can only be called if IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY INLINE(Address target_address()); - INLINE(void set_target_address(Address target, - WriteBarrierMode mode = UPDATE_WRITE_BARRIER)); + INLINE(void set_target_address(Address target)); INLINE(Object* target_object()); INLINE(Handle target_object_handle(Assembler* origin)); INLINE(Object** target_object_address()); - INLINE(void set_target_object(Object* target, - WriteBarrierMode mode = UPDATE_WRITE_BARRIER)); + INLINE(void set_target_object(Object* target)); INLINE(JSGlobalPropertyCell* target_cell()); INLINE(Handle target_cell_handle()); - INLINE(void set_target_cell(JSGlobalPropertyCell* cell, - WriteBarrierMode mode = UPDATE_WRITE_BARRIER)); + INLINE(void set_target_cell(JSGlobalPropertyCell* cell)); // Read the address of the word containing the target_address in an @@ -596,8 +593,8 @@ class ExternalReference BASE_EMBEDDED { static ExternalReference keyed_lookup_cache_keys(Isolate* isolate); static ExternalReference keyed_lookup_cache_field_offsets(Isolate* isolate); - // Static variable Heap::roots_array_start() - static ExternalReference roots_array_start(Isolate* isolate); + // Static variable Heap::roots_address() + static ExternalReference roots_address(Isolate* isolate); // Static variable StackGuard::address_of_jslimit() static ExternalReference address_of_stack_limit(Isolate* isolate); @@ -850,8 +847,6 @@ static inline int NumberOfBitsSet(uint32_t x) { return num_bits_set; } -bool EvalComparison(Token::Value op, double op1, double op2); - // Computes pow(x, y) with the special cases in the spec for Math.pow. double power_double_int(double x, int y); double power_double_double(double x, double y); diff --git a/deps/v8/src/ast-inl.h b/deps/v8/src/ast-inl.h index f8b460d3241..731ad2ff3f2 100644 --- a/deps/v8/src/ast-inl.h +++ b/deps/v8/src/ast-inl.h @@ -111,18 +111,8 @@ ForInStatement::ForInStatement(Isolate* isolate, ZoneStringList* labels) } -int FunctionLiteral::start_position() const { - return scope()->start_position(); -} - - -int FunctionLiteral::end_position() const { - return scope()->end_position(); -} - - -StrictModeFlag FunctionLiteral::strict_mode_flag() const { - return scope()->strict_mode_flag(); +bool FunctionLiteral::strict_mode() const { + return scope()->is_strict_mode(); } diff --git a/deps/v8/src/ast.cc b/deps/v8/src/ast.cc index 9e34bc0e815..d493814544a 100644 --- a/deps/v8/src/ast.cc +++ b/deps/v8/src/ast.cc @@ -66,6 +66,7 @@ VariableProxy::VariableProxy(Isolate* isolate, Variable* var) name_(var->name()), var_(NULL), // Will be set by the call to BindTo. is_this_(var->is_this()), + inside_with_(false), is_trivial_(false), position_(RelocInfo::kNoPosition) { BindTo(var); @@ -75,11 +76,13 @@ VariableProxy::VariableProxy(Isolate* isolate, Variable* var) VariableProxy::VariableProxy(Isolate* isolate, Handle name, bool is_this, + bool inside_with, int position) : Expression(isolate), name_(name), var_(NULL), is_this_(is_this), + inside_with_(inside_with), is_trivial_(false), position_(position) { // Names must be canonicalized for fast equality checks. @@ -465,7 +468,7 @@ bool FunctionLiteral::IsInlineable() const { bool ThisFunction::IsInlineable() const { - return true; + return false; } @@ -720,7 +723,7 @@ bool Call::ComputeTarget(Handle type, Handle name) { holder_ = Handle::null(); } while (true) { - LookupResult lookup(type->GetIsolate()); + LookupResult lookup; type->LookupInDescriptors(NULL, *name, &lookup); // If the function wasn't found directly in the map, we start // looking upwards through the prototype chain. diff --git a/deps/v8/src/ast.h b/deps/v8/src/ast.h index 3de00ef5d30..0efc4835c4f 100644 --- a/deps/v8/src/ast.h +++ b/deps/v8/src/ast.h @@ -405,10 +405,7 @@ class Declaration: public AstNode { mode_(mode), fun_(fun), scope_(scope) { - ASSERT(mode == VAR || - mode == CONST || - mode == CONST_HARMONY || - mode == LET); + ASSERT(mode == VAR || mode == CONST || mode == LET); // At the moment there are no "const functions"'s in JavaScript... ASSERT(fun == NULL || mode == VAR || mode == LET); } @@ -1131,6 +1128,7 @@ class VariableProxy: public Expression { Handle name() const { return name_; } Variable* var() const { return var_; } bool is_this() const { return is_this_; } + bool inside_with() const { return inside_with_; } int position() const { return position_; } void MarkAsTrivial() { is_trivial_ = true; } @@ -1142,12 +1140,14 @@ class VariableProxy: public Expression { Handle name_; Variable* var_; // resolved variable, or NULL bool is_this_; + bool inside_with_; bool is_trivial_; int position_; VariableProxy(Isolate* isolate, Handle name, bool is_this, + bool inside_with, int position = RelocInfo::kNoPosition); friend class Scope; @@ -1620,6 +1620,8 @@ class FunctionLiteral: public Expression { bool has_only_simple_this_property_assignments, Handle this_property_assignments, int num_parameters, + int start_position, + int end_position, Type type, bool has_duplicate_parameters) : Expression(isolate), @@ -1632,6 +1634,8 @@ class FunctionLiteral: public Expression { has_only_simple_this_property_assignments), this_property_assignments_(this_property_assignments), num_parameters_(num_parameters), + start_position_(start_position), + end_position_(end_position), function_token_position_(RelocInfo::kNoPosition), inferred_name_(HEAP->empty_string()), is_expression_(type != DECLARATION), @@ -1647,12 +1651,11 @@ class FunctionLiteral: public Expression { ZoneList* body() const { return body_; } void set_function_token_position(int pos) { function_token_position_ = pos; } int function_token_position() const { return function_token_position_; } - int start_position() const; - int end_position() const; + int start_position() const { return start_position_; } + int end_position() const { return end_position_; } bool is_expression() const { return is_expression_; } bool is_anonymous() const { return is_anonymous_; } - bool strict_mode() const { return strict_mode_flag() == kStrictMode; } - StrictModeFlag strict_mode_flag() const; + bool strict_mode() const; int materialized_literal_count() { return materialized_literal_count_; } int expected_property_count() { return expected_property_count_; } diff --git a/deps/v8/src/bootstrapper.cc b/deps/v8/src/bootstrapper.cc index 6735ff45493..dc722cb7493 100644 --- a/deps/v8/src/bootstrapper.cc +++ b/deps/v8/src/bootstrapper.cc @@ -38,7 +38,6 @@ #include "macro-assembler.h" #include "natives.h" #include "objects-visiting.h" -#include "platform.h" #include "snapshot.h" #include "extensions/externalize-string-extension.h" #include "extensions/gc-extension.h" @@ -363,7 +362,6 @@ static Handle InstallFunction(Handle target, if (is_ecma_native) { function->shared()->set_instance_class_name(*symbol); } - function->shared()->set_native(true); return function; } @@ -377,28 +375,26 @@ Handle Genesis::ComputeFunctionInstanceDescriptor( PropertyAttributes attributes = static_cast(DONT_ENUM | DONT_DELETE | READ_ONLY); - DescriptorArray::WhitenessWitness witness(*descriptors); - { // Add length. Handle foreign = factory()->NewForeign(&Accessors::FunctionLength); CallbacksDescriptor d(*factory()->length_symbol(), *foreign, attributes); - descriptors->Set(0, &d, witness); + descriptors->Set(0, &d); } { // Add name. Handle foreign = factory()->NewForeign(&Accessors::FunctionName); CallbacksDescriptor d(*factory()->name_symbol(), *foreign, attributes); - descriptors->Set(1, &d, witness); + descriptors->Set(1, &d); } { // Add arguments. Handle foreign = factory()->NewForeign(&Accessors::FunctionArguments); CallbacksDescriptor d(*factory()->arguments_symbol(), *foreign, attributes); - descriptors->Set(2, &d, witness); + descriptors->Set(2, &d); } { // Add caller. Handle foreign = factory()->NewForeign(&Accessors::FunctionCaller); CallbacksDescriptor d(*factory()->caller_symbol(), *foreign, attributes); - descriptors->Set(3, &d, witness); + descriptors->Set(3, &d); } if (prototypeMode != DONT_ADD_PROTOTYPE) { // Add prototype. @@ -408,9 +404,9 @@ Handle Genesis::ComputeFunctionInstanceDescriptor( Handle foreign = factory()->NewForeign(&Accessors::FunctionPrototype); CallbacksDescriptor d(*factory()->prototype_symbol(), *foreign, attributes); - descriptors->Set(4, &d, witness); + descriptors->Set(4, &d); } - descriptors->Sort(witness); + descriptors->Sort(); return descriptors; } @@ -526,43 +522,41 @@ Handle Genesis::ComputeStrictFunctionInstanceDescriptor( ? 4 : 5); PropertyAttributes attributes = static_cast( - DONT_ENUM | DONT_DELETE); - - DescriptorArray::WhitenessWitness witness(*descriptors); + DONT_ENUM | DONT_DELETE | READ_ONLY); { // length Handle foreign = factory()->NewForeign(&Accessors::FunctionLength); CallbacksDescriptor d(*factory()->length_symbol(), *foreign, attributes); - descriptors->Set(0, &d, witness); + descriptors->Set(0, &d); } { // name Handle foreign = factory()->NewForeign(&Accessors::FunctionName); CallbacksDescriptor d(*factory()->name_symbol(), *foreign, attributes); - descriptors->Set(1, &d, witness); + descriptors->Set(1, &d); } { // arguments CallbacksDescriptor d(*factory()->arguments_symbol(), *arguments, attributes); - descriptors->Set(2, &d, witness); + descriptors->Set(2, &d); } { // caller CallbacksDescriptor d(*factory()->caller_symbol(), *caller, attributes); - descriptors->Set(3, &d, witness); + descriptors->Set(3, &d); } // prototype if (prototypeMode != DONT_ADD_PROTOTYPE) { - if (prototypeMode != ADD_WRITEABLE_PROTOTYPE) { - attributes = static_cast(attributes | READ_ONLY); + if (prototypeMode == ADD_WRITEABLE_PROTOTYPE) { + attributes = static_cast(attributes & ~READ_ONLY); } Handle foreign = factory()->NewForeign(&Accessors::FunctionPrototype); CallbacksDescriptor d(*factory()->prototype_symbol(), *foreign, attributes); - descriptors->Set(4, &d, witness); + descriptors->Set(4, &d); } - descriptors->Sort(witness); + descriptors->Sort(); return descriptors; } @@ -947,7 +941,6 @@ void Genesis::InitializeGlobal(Handle inner_global, ASSERT_EQ(0, initial_map->inobject_properties()); Handle descriptors = factory->NewDescriptorArray(5); - DescriptorArray::WhitenessWitness witness(*descriptors); PropertyAttributes final = static_cast(DONT_ENUM | DONT_DELETE | READ_ONLY); int enum_index = 0; @@ -957,7 +950,7 @@ void Genesis::InitializeGlobal(Handle inner_global, JSRegExp::kSourceFieldIndex, final, enum_index++); - descriptors->Set(0, &field, witness); + descriptors->Set(0, &field); } { // ECMA-262, section 15.10.7.2. @@ -965,7 +958,7 @@ void Genesis::InitializeGlobal(Handle inner_global, JSRegExp::kGlobalFieldIndex, final, enum_index++); - descriptors->Set(1, &field, witness); + descriptors->Set(1, &field); } { // ECMA-262, section 15.10.7.3. @@ -973,7 +966,7 @@ void Genesis::InitializeGlobal(Handle inner_global, JSRegExp::kIgnoreCaseFieldIndex, final, enum_index++); - descriptors->Set(2, &field, witness); + descriptors->Set(2, &field); } { // ECMA-262, section 15.10.7.4. @@ -981,7 +974,7 @@ void Genesis::InitializeGlobal(Handle inner_global, JSRegExp::kMultilineFieldIndex, final, enum_index++); - descriptors->Set(3, &field, witness); + descriptors->Set(3, &field); } { // ECMA-262, section 15.10.7.5. @@ -991,10 +984,10 @@ void Genesis::InitializeGlobal(Handle inner_global, JSRegExp::kLastIndexFieldIndex, writable, enum_index++); - descriptors->Set(4, &field, witness); + descriptors->Set(4, &field); } descriptors->SetNextEnumerationIndex(enum_index); - descriptors->Sort(witness); + descriptors->Sort(); initial_map->set_inobject_properties(5); initial_map->set_pre_allocated_property_fields(5); @@ -1072,7 +1065,7 @@ void Genesis::InitializeGlobal(Handle inner_global, DONT_ENUM); #ifdef DEBUG - LookupResult lookup(isolate); + LookupResult lookup; result->LocalLookup(heap->callee_symbol(), &lookup); ASSERT(lookup.IsProperty() && (lookup.type() == FIELD)); ASSERT(lookup.GetFieldIndex() == Heap::kArgumentsCalleeIndex); @@ -1091,6 +1084,11 @@ void Genesis::InitializeGlobal(Handle inner_global, } { // --- aliased_arguments_boilerplate_ + Handle old_map(global_context()->arguments_boilerplate()->map()); + Handle new_map = factory->CopyMapDropTransitions(old_map); + new_map->set_pre_allocated_property_fields(2); + Handle result = factory->NewJSObjectFromMap(new_map); + new_map->set_elements_kind(NON_STRICT_ARGUMENTS_ELEMENTS); // Set up a well-formed parameter map to make assertions happy. Handle elements = factory->NewFixedArray(2); elements->set_map(heap->non_strict_arguments_elements_map()); @@ -1099,16 +1097,12 @@ void Genesis::InitializeGlobal(Handle inner_global, elements->set(0, *array); array = factory->NewFixedArray(0); elements->set(1, *array); - - Handle old_map(global_context()->arguments_boilerplate()->map()); - Handle new_map = factory->CopyMapDropTransitions(old_map); - new_map->set_pre_allocated_property_fields(2); - Handle result = factory->NewJSObjectFromMap(new_map); - // Set elements kind after allocating the object because - // NewJSObjectFromMap assumes a fast elements map. - new_map->set_elements_kind(NON_STRICT_ARGUMENTS_ELEMENTS); - result->set_elements(*elements); + Handle non_strict_arguments_elements_map = + factory->GetElementsTransitionMap(result, + NON_STRICT_ARGUMENTS_ELEMENTS); + result->set_map(*non_strict_arguments_elements_map); ASSERT(result->HasNonStrictArgumentsElements()); + result->set_elements(*elements); global_context()->set_aliased_arguments_boilerplate(*result); } @@ -1131,20 +1125,19 @@ void Genesis::InitializeGlobal(Handle inner_global, // Create the descriptor array for the arguments object. Handle descriptors = factory->NewDescriptorArray(3); - DescriptorArray::WhitenessWitness witness(*descriptors); { // length FieldDescriptor d(*factory->length_symbol(), 0, DONT_ENUM); - descriptors->Set(0, &d, witness); + descriptors->Set(0, &d); } { // callee CallbacksDescriptor d(*factory->callee_symbol(), *callee, attributes); - descriptors->Set(1, &d, witness); + descriptors->Set(1, &d); } { // caller CallbacksDescriptor d(*factory->caller_symbol(), *caller, attributes); - descriptors->Set(2, &d, witness); + descriptors->Set(2, &d); } - descriptors->Sort(witness); + descriptors->Sort(); // Create the map. Allocate one in-object field for length. Handle map = factory->NewMap(JS_OBJECT_TYPE, @@ -1169,7 +1162,7 @@ void Genesis::InitializeGlobal(Handle inner_global, DONT_ENUM); #ifdef DEBUG - LookupResult lookup(isolate); + LookupResult lookup; result->LocalLookup(heap->length_symbol(), &lookup); ASSERT(lookup.IsProperty() && (lookup.type() == FIELD)); ASSERT(lookup.GetFieldIndex() == Heap::kArgumentsLengthIndex); @@ -1228,14 +1221,6 @@ void Genesis::InitializeGlobal(Handle inner_global, // Initialize the data slot. global_context()->set_data(heap->undefined_value()); - - { - // Initialize the random seed slot. - Handle zeroed_byte_array( - factory->NewByteArray(kRandomStateSize)); - global_context()->set_random_seed(*zeroed_byte_array); - memset(zeroed_byte_array->GetDataStartAddress(), 0, kRandomStateSize); - } } @@ -1243,26 +1228,12 @@ void Genesis::InitializeExperimentalGlobal() { Handle global = Handle(global_context()->global()); // TODO(mstarzinger): Move this into Genesis::InitializeGlobal once we no - // longer need to live behind a flag, so functions get added to the snapshot. - if (FLAG_harmony_collections) { - { // -- S e t - Handle prototype = - factory()->NewJSObject(isolate()->object_function(), TENURED); - InstallFunction(global, "Set", JS_SET_TYPE, JSSet::kSize, - prototype, Builtins::kIllegal, true); - } - { // -- M a p - Handle prototype = - factory()->NewJSObject(isolate()->object_function(), TENURED); - InstallFunction(global, "Map", JS_MAP_TYPE, JSMap::kSize, - prototype, Builtins::kIllegal, true); - } - { // -- W e a k M a p - Handle prototype = - factory()->NewJSObject(isolate()->object_function(), TENURED); - InstallFunction(global, "WeakMap", JS_WEAK_MAP_TYPE, JSWeakMap::kSize, - prototype, Builtins::kIllegal, true); - } + // longer need to live behind a flag, so WeakMap gets added to the snapshot. + if (FLAG_harmony_weakmaps) { // -- W e a k M a p + Handle prototype = + factory()->NewJSObject(isolate()->object_function(), TENURED); + InstallFunction(global, "WeakMap", JS_WEAK_MAP_TYPE, JSWeakMap::kSize, + prototype, Builtins::kIllegal, true); } } @@ -1391,7 +1362,6 @@ void Genesis::InstallExperimentalNativeFunctions() { INSTALL_NATIVE(JSFunction, "DerivedHasTrap", derived_has_trap); INSTALL_NATIVE(JSFunction, "DerivedGetTrap", derived_get_trap); INSTALL_NATIVE(JSFunction, "DerivedSetTrap", derived_set_trap); - INSTALL_NATIVE(JSFunction, "ProxyEnumerate", proxy_enumerate); } } @@ -1726,9 +1696,7 @@ bool Genesis::InstallNatives() { Handle reresult_descriptors = factory()->NewDescriptorArray(3); - DescriptorArray::WhitenessWitness witness(*reresult_descriptors); - - reresult_descriptors->CopyFrom(0, *array_descriptors, 0, witness); + reresult_descriptors->CopyFrom(0, *array_descriptors, 0); int enum_index = 0; { @@ -1736,7 +1704,7 @@ bool Genesis::InstallNatives() { JSRegExpResult::kIndexIndex, NONE, enum_index++); - reresult_descriptors->Set(1, &index_field, witness); + reresult_descriptors->Set(1, &index_field); } { @@ -1744,9 +1712,9 @@ bool Genesis::InstallNatives() { JSRegExpResult::kInputIndex, NONE, enum_index++); - reresult_descriptors->Set(2, &input_field, witness); + reresult_descriptors->Set(2, &input_field); } - reresult_descriptors->Sort(witness); + reresult_descriptors->Sort(); initial_map->set_inobject_properties(2); initial_map->set_pre_allocated_property_fields(2); @@ -1773,9 +1741,9 @@ bool Genesis::InstallExperimentalNatives() { "native proxy.js") == 0) { if (!CompileExperimentalBuiltin(isolate(), i)) return false; } - if (FLAG_harmony_collections && + if (FLAG_harmony_weakmaps && strcmp(ExperimentalNatives::GetScriptName(i).start(), - "native collection.js") == 0) { + "native weakmap.js") == 0) { if (!CompileExperimentalBuiltin(isolate(), i)) return false; } } @@ -2021,12 +1989,6 @@ bool Genesis::InstallExtension(v8::RegisteredExtension* current) { false); ASSERT(isolate->has_pending_exception() != result); if (!result) { - // We print out the name of the extension that fail to install. - // When an error is thrown during bootstrapping we automatically print - // the line number at which this happened to the console in the isolate - // error throwing functionality. - OS::PrintError("Error installing extension '%s'.\n", - current->extension()->name()); isolate->clear_pending_exception(); } current->set_state(v8::INSTALLED); @@ -2046,9 +2008,7 @@ bool Genesis::InstallJSBuiltins(Handle builtins) { builtins->set_javascript_builtin(id, *function); Handle shared = Handle(function->shared()); - if (!SharedFunctionInfo::EnsureCompiled(shared, CLEAR_EXCEPTION)) { - return false; - } + if (!EnsureCompiled(shared, CLEAR_EXCEPTION)) return false; // Set the code object on the function object. function->ReplaceCode(function->shared()->code()); builtins->set_javascript_builtin_code(id, shared->code()); @@ -2128,7 +2088,7 @@ void Genesis::TransferNamedProperties(Handle from, break; } case CALLBACKS: { - LookupResult result(isolate()); + LookupResult result; to->LocalLookup(descs->GetKey(i), &result); // If the property is already there we skip it if (result.IsProperty()) continue; @@ -2166,7 +2126,7 @@ void Genesis::TransferNamedProperties(Handle from, if (properties->IsKey(raw_key)) { ASSERT(raw_key->IsString()); // If the property is already there we skip it. - LookupResult result(isolate()); + LookupResult result; to->LocalLookup(String::cast(raw_key), &result); if (result.IsProperty()) continue; // Set the property. diff --git a/deps/v8/src/builtins.cc b/deps/v8/src/builtins.cc index e758b9a4158..d513200f0b9 100644 --- a/deps/v8/src/builtins.cc +++ b/deps/v8/src/builtins.cc @@ -1507,14 +1507,6 @@ static void Generate_KeyedStoreIC_NonStrictArguments(MacroAssembler* masm) { KeyedStoreIC::GenerateNonStrictArguments(masm); } -static void Generate_TransitionElementsSmiToDouble(MacroAssembler* masm) { - KeyedStoreIC::GenerateTransitionElementsSmiToDouble(masm); -} - -static void Generate_TransitionElementsDoubleToObject(MacroAssembler* masm) { - KeyedStoreIC::GenerateTransitionElementsDoubleToObject(masm); -} - #ifdef ENABLE_DEBUGGER_SUPPORT static void Generate_LoadIC_DebugBreak(MacroAssembler* masm) { Debug::GenerateLoadICDebugBreak(masm); diff --git a/deps/v8/src/builtins.h b/deps/v8/src/builtins.h index 24059e7728a..31090d3a084 100644 --- a/deps/v8/src/builtins.h +++ b/deps/v8/src/builtins.h @@ -167,10 +167,6 @@ enum BuiltinExtraArguments { kStrictMode) \ V(KeyedStoreIC_NonStrictArguments, KEYED_STORE_IC, MEGAMORPHIC, \ Code::kNoExtraICState) \ - V(TransitionElementsSmiToDouble, BUILTIN, UNINITIALIZED, \ - Code::kNoExtraICState) \ - V(TransitionElementsDoubleToObject, BUILTIN, UNINITIALIZED, \ - Code::kNoExtraICState) \ \ /* Uses KeyedLoadIC_Initialize; must be after in list. */ \ V(FunctionCall, BUILTIN, UNINITIALIZED, \ @@ -238,6 +234,7 @@ enum BuiltinExtraArguments { V(DELETE, 2) \ V(IN, 1) \ V(INSTANCE_OF, 1) \ + V(GET_KEYS, 0) \ V(FILTER_KEY, 1) \ V(CALL_NON_FUNCTION, 0) \ V(CALL_NON_FUNCTION_AS_CONSTRUCTOR, 0) \ diff --git a/deps/v8/src/checks.h b/deps/v8/src/checks.h index 832f778b25c..2f359f6cd84 100644 --- a/deps/v8/src/checks.h +++ b/deps/v8/src/checks.h @@ -63,9 +63,7 @@ static inline void CheckHelper(const char* file, // The CHECK macro checks that the given condition is true; if not, it // prints a message to stderr and aborts. -#define CHECK(condition) do { \ - if (!(condition)) CheckHelper(__FILE__, __LINE__, #condition, false); \ - } while (0) +#define CHECK(condition) CheckHelper(__FILE__, __LINE__, #condition, condition) // Helper function used by the CHECK_EQ function when given int @@ -259,8 +257,11 @@ template class StaticAssertionHelper { }; SEMI_STATIC_JOIN(__StaticAssertTypedef__, __LINE__) -extern bool FLAG_enable_slow_asserts; +namespace v8 { namespace internal { +bool EnableSlowAsserts(); + +} } // namespace v8::internal // The ASSERT macro is equivalent to CHECK except that it only // generates code in debug builds. @@ -272,7 +273,7 @@ extern bool FLAG_enable_slow_asserts; #define ASSERT_GE(v1, v2) CHECK_GE(v1, v2) #define ASSERT_LT(v1, v2) CHECK_LT(v1, v2) #define ASSERT_LE(v1, v2) CHECK_LE(v1, v2) -#define SLOW_ASSERT(condition) if (FLAG_enable_slow_asserts) CHECK(condition) +#define SLOW_ASSERT(condition) if (EnableSlowAsserts()) CHECK(condition) #else #define ASSERT_RESULT(expr) (expr) #define ASSERT(condition) ((void) 0) diff --git a/deps/v8/src/code-stubs.cc b/deps/v8/src/code-stubs.cc index b4374360c60..4bc2603c534 100644 --- a/deps/v8/src/code-stubs.cc +++ b/deps/v8/src/code-stubs.cc @@ -415,29 +415,4 @@ bool ToBooleanStub::Types::CanBeUndetectable() const { } -void ElementsTransitionAndStoreStub::Generate(MacroAssembler* masm) { - Label fail; - if (!FLAG_trace_elements_transitions) { - if (to_ == FAST_ELEMENTS) { - if (from_ == FAST_SMI_ONLY_ELEMENTS) { - ElementsTransitionGenerator::GenerateSmiOnlyToObject(masm); - } else if (from_ == FAST_DOUBLE_ELEMENTS) { - ElementsTransitionGenerator::GenerateDoubleToObject(masm, &fail); - } else { - UNREACHABLE(); - } - KeyedStoreStubCompiler::GenerateStoreFastElement(masm, - is_jsarray_, - FAST_ELEMENTS); - } else if (from_ == FAST_SMI_ONLY_ELEMENTS && to_ == FAST_DOUBLE_ELEMENTS) { - ElementsTransitionGenerator::GenerateSmiOnlyToDouble(masm, &fail); - KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(masm, is_jsarray_); - } else { - UNREACHABLE(); - } - } - masm->bind(&fail); - KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode_); -} - } } // namespace v8::internal diff --git a/deps/v8/src/code-stubs.h b/deps/v8/src/code-stubs.h index fc7000bb03d..acfbd469f0f 100644 --- a/deps/v8/src/code-stubs.h +++ b/deps/v8/src/code-stubs.h @@ -30,7 +30,6 @@ #include "allocation.h" #include "globals.h" -#include "codegen.h" namespace v8 { namespace internal { @@ -70,8 +69,7 @@ namespace internal { V(KeyedLoadElement) \ V(KeyedStoreElement) \ V(DebuggerStatement) \ - V(StringDictionaryLookup) \ - V(ElementsTransitionAndStore) + V(StringDictionaryLookup) // List of code stubs only used on ARM platforms. #ifdef V8_TARGET_ARCH_ARM @@ -364,7 +362,6 @@ class FastCloneShallowArrayStub : public CodeStub { enum Mode { CLONE_ELEMENTS, - CLONE_DOUBLE_ELEMENTS, COPY_ON_WRITE_ELEMENTS }; @@ -383,8 +380,8 @@ class FastCloneShallowArrayStub : public CodeStub { Major MajorKey() { return FastCloneShallowArray; } int MinorKey() { - ASSERT(mode_ == 0 || mode_ == 1 || mode_ == 2); - return length_ * 3 + mode_; + ASSERT(mode_ == 0 || mode_ == 1); + return (length_ << 1) | mode_; } }; @@ -1028,42 +1025,6 @@ class ToBooleanStub: public CodeStub { Types types_; }; - -class ElementsTransitionAndStoreStub : public CodeStub { - public: - ElementsTransitionAndStoreStub(ElementsKind from, - ElementsKind to, - bool is_jsarray, - StrictModeFlag strict_mode) - : from_(from), - to_(to), - is_jsarray_(is_jsarray), - strict_mode_(strict_mode) {} - - private: - class FromBits: public BitField {}; - class ToBits: public BitField {}; - class IsJSArrayBits: public BitField {}; - class StrictModeBits: public BitField {}; - - Major MajorKey() { return ElementsTransitionAndStore; } - int MinorKey() { - return FromBits::encode(from_) | - ToBits::encode(to_) | - IsJSArrayBits::encode(is_jsarray_) | - StrictModeBits::encode(strict_mode_); - } - - void Generate(MacroAssembler* masm); - - ElementsKind from_; - ElementsKind to_; - bool is_jsarray_; - StrictModeFlag strict_mode_; - - DISALLOW_COPY_AND_ASSIGN(ElementsTransitionAndStoreStub); -}; - } } // namespace v8::internal #endif // V8_CODE_STUBS_H_ diff --git a/deps/v8/src/codegen.h b/deps/v8/src/codegen.h index 5360d3ef3ca..e551abfb11a 100644 --- a/deps/v8/src/codegen.h +++ b/deps/v8/src/codegen.h @@ -81,19 +81,4 @@ enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF }; #error Unsupported target architecture. #endif -namespace v8 { -namespace internal { - -class ElementsTransitionGenerator : public AllStatic { - public: - static void GenerateSmiOnlyToObject(MacroAssembler* masm); - static void GenerateSmiOnlyToDouble(MacroAssembler* masm, Label* fail); - static void GenerateDoubleToObject(MacroAssembler* masm, Label* fail); - - private: - DISALLOW_COPY_AND_ASSIGN(ElementsTransitionGenerator); -}; - -} } // namespace v8::internal - #endif // V8_CODEGEN_H_ diff --git a/deps/v8/src/compiler.cc b/deps/v8/src/compiler.cc index 88db467c35e..4979a7f8663 100644 --- a/deps/v8/src/compiler.cc +++ b/deps/v8/src/compiler.cc @@ -59,6 +59,7 @@ CompilationInfo::CompilationInfo(Handle