diff options
author | Ryan Dahl <ry@tinyclouds.org> | 2012-01-17 02:37:57 +0400 |
---|---|---|
committer | Ryan Dahl <ry@tinyclouds.org> | 2012-01-17 02:37:57 +0400 |
commit | 60040a4f366d436d759729530f4d19e7e1958e51 (patch) | |
tree | 953a40adf24a0826836cc69843ea80d197a12dab /deps | |
parent | 1afd0b52fe9bb4642a44b48dabf9d7b26d00e4ab (diff) |
Upgrade V8 to 3.8.6
Diffstat (limited to 'deps')
177 files changed, 3329 insertions, 1703 deletions
diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog index 059b69252e6..1c1bddda82b 100644 --- a/deps/v8/ChangeLog +++ b/deps/v8/ChangeLog @@ -1,3 +1,22 @@ +2012-01-16: Version 3.8.6 + + Add primitive WebGL array support to d8. + + Improve heap size estimation (issue 1893). + + Hash collision DOS workaround extended from string keys + to numeric keys. + + Provide an API for iterating through all external strings referenced + from the JS heap. + + Adjust position recorded for call expressions. http://crbug.com/109195 + + Fix GC crash related to instanceof. http://crbug.com/109448 + + Performance improvements and bug fixes. + + 2012-01-05: Version 3.8.5 Fix broken test that assumes that no GC can clear the regexp cache (GC diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h index 18199435808..294b14d386f 100644 --- a/deps/v8/include/v8.h +++ b/deps/v8/include/v8.h @@ -2848,6 +2848,17 @@ class V8EXPORT StartupDataDecompressor { // NOLINT */ typedef bool (*EntropySource)(unsigned char* buffer, size_t length); + +/** + * Interface for iterating though all external resources in the heap. + */ +class V8EXPORT ExternalResourceVisitor { // NOLINT + public: + virtual ~ExternalResourceVisitor() {} + virtual void VisitExternalString(Handle<String> string) {} +}; + + /** * Container class for static utility functions. */ @@ -3204,6 +3215,13 @@ class V8EXPORT V8 { static void GetHeapStatistics(HeapStatistics* heap_statistics); /** + * Iterates through all external resources referenced from current isolate + * heap. This method is not expected to be used except for debugging purposes + * and may be quite slow. + */ + static void VisitExternalResources(ExternalResourceVisitor* visitor); + + /** * Optional notification that the embedder is idle. * V8 uses the notification to reduce memory footprint. * This call can be used repeatedly if the embedder remains idle. @@ -3816,7 +3834,7 @@ class Internals { static const int kFullStringRepresentationMask = 0x07; static const int kExternalTwoByteRepresentationTag = 0x02; - static const int kJSObjectType = 0xa6; + static const int kJSObjectType = 0xa7; static const int kFirstNonstringType = 0x80; static const int kForeignType = 0x85; diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index 3bd5a3180f6..bac3069308e 100644 --- a/deps/v8/src/api.cc +++ b/deps/v8/src/api.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -2165,6 +2165,11 @@ bool Value::IsInt32() const { if (obj->IsSmi()) return true; if (obj->IsNumber()) { double value = obj->Number(); + static const i::DoubleRepresentation minus_zero(-0.0); + i::DoubleRepresentation rep(value); + if (rep.bits == minus_zero.bits) { + return false; + } return i::FastI2D(i::FastD2I(value)) == value; } return false; @@ -2177,6 +2182,11 @@ bool Value::IsUint32() const { if (obj->IsSmi()) return i::Smi::cast(*obj)->value() >= 0; if (obj->IsNumber()) { double value = obj->Number(); + static const i::DoubleRepresentation minus_zero(-0.0); + i::DoubleRepresentation rep(value); + if (rep.bits == minus_zero.bits) { + return false; + } return i::FastUI2D(i::FastD2UI(value)) == value; } return false; @@ -2739,7 +2749,7 @@ bool v8::Object::Set(uint32_t index, v8::Handle<Value> value) { i::Handle<i::JSObject> self = Utils::OpenHandle(this); i::Handle<i::Object> value_obj = Utils::OpenHandle(*value); EXCEPTION_PREAMBLE(isolate); - i::Handle<i::Object> obj = i::SetElement( + i::Handle<i::Object> obj = i::JSObject::SetElement( self, index, value_obj, @@ -2845,7 +2855,7 @@ Local<Value> v8::Object::GetPrototype() { return Local<v8::Value>()); ENTER_V8(isolate); i::Handle<i::Object> self = Utils::OpenHandle(this); - i::Handle<i::Object> result = i::GetPrototype(self); + i::Handle<i::Object> result(self->GetPrototype()); return Utils::ToLocal(result); } @@ -2999,7 +3009,7 @@ bool v8::Object::Delete(v8::Handle<String> key) { i::HandleScope scope(isolate); i::Handle<i::JSObject> self = Utils::OpenHandle(this); i::Handle<i::String> key_obj = Utils::OpenHandle(*key); - return i::DeleteProperty(self, key_obj)->IsTrue(); + return i::JSObject::DeleteProperty(self, key_obj)->IsTrue(); } @@ -3020,7 +3030,7 @@ bool v8::Object::Delete(uint32_t index) { ENTER_V8(isolate); HandleScope scope; i::Handle<i::JSObject> self = Utils::OpenHandle(this); - return i::DeleteElement(self, index)->IsTrue(); + return i::JSObject::DeleteElement(self, index)->IsTrue(); } @@ -3225,7 +3235,7 @@ int v8::Object::GetIdentityHash() { ENTER_V8(isolate); i::HandleScope scope(isolate); i::Handle<i::JSObject> self = Utils::OpenHandle(this); - return i::GetIdentityHash(self); + return i::JSObject::GetIdentityHash(self); } @@ -3238,7 +3248,8 @@ bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key, i::Handle<i::JSObject> self = Utils::OpenHandle(this); i::Handle<i::String> key_obj = Utils::OpenHandle(*key); i::Handle<i::Object> value_obj = Utils::OpenHandle(*value); - i::Handle<i::Object> result = i::SetHiddenProperty(self, key_obj, value_obj); + i::Handle<i::Object> result = + i::JSObject::SetHiddenProperty(self, key_obj, value_obj); return *result == *self; } @@ -4038,6 +4049,13 @@ void v8::V8::GetHeapStatistics(HeapStatistics* heap_statistics) { } +void v8::V8::VisitExternalResources(ExternalResourceVisitor* visitor) { + i::Isolate* isolate = i::Isolate::Current(); + IsDeadCheck(isolate, "v8::V8::VisitExternalResources"); + isolate->heap()->VisitExternalResources(visitor); +} + + bool v8::V8::IdleNotification(int hint) { // Returning true tells the caller that it need not // continue to call IdleNotification. @@ -5542,7 +5560,7 @@ void Debug::DisableAgent() { void Debug::ProcessDebugMessages() { - i::Execution::ProcessDebugMesssages(true); + i::Execution::ProcessDebugMessages(true); } Local<Context> Debug::GetDebugContext() { diff --git a/deps/v8/src/arm/assembler-arm-inl.h b/deps/v8/src/arm/assembler-arm-inl.h index 79f9c7bd2b3..2ec6c7cfa79 100644 --- a/deps/v8/src/arm/assembler-arm-inl.h +++ b/deps/v8/src/arm/assembler-arm-inl.h @@ -32,7 +32,7 @@ // The original source code covered by the above license above has been modified // significantly by Google Inc. -// Copyright 2006-2008 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. #ifndef V8_ARM_ASSEMBLER_ARM_INL_H_ #define V8_ARM_ASSEMBLER_ARM_INL_H_ @@ -46,6 +46,13 @@ namespace v8 { namespace internal { +int DwVfpRegister::ToAllocationIndex(DwVfpRegister reg) { + ASSERT(!reg.is(kDoubleRegZero)); + ASSERT(!reg.is(kScratchDoubleReg)); + return reg.code(); +} + + void RelocInfo::apply(intptr_t delta) { if (RelocInfo::IsInternalReference(rmode_)) { // absolute code pointer inside code object moves with the code object. diff --git a/deps/v8/src/arm/assembler-arm.cc b/deps/v8/src/arm/assembler-arm.cc index 329493a340d..25922361a26 100644 --- a/deps/v8/src/arm/assembler-arm.cc +++ b/deps/v8/src/arm/assembler-arm.cc @@ -317,7 +317,7 @@ Assembler::Assembler(Isolate* arg_isolate, void* buffer, int buffer_size) own_buffer_ = false; } - // Setup buffer pointers. + // Set up buffer pointers. ASSERT(buffer_ != NULL); pc_ = buffer_; reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); @@ -349,7 +349,7 @@ void Assembler::GetCode(CodeDesc* desc) { CheckConstPool(true, false); ASSERT(num_pending_reloc_info_ == 0); - // Setup code descriptor. + // Set up code descriptor. desc->buffer = buffer_; desc->buffer_size = buffer_size_; desc->instr_size = pc_offset(); @@ -2446,7 +2446,7 @@ void Assembler::GrowBuffer() { } CHECK_GT(desc.buffer_size, 0); // no overflow - // Setup new buffer. + // Set up new buffer. desc.buffer = NewArray<byte>(desc.buffer_size); desc.instr_size = pc_offset(); diff --git a/deps/v8/src/arm/assembler-arm.h b/deps/v8/src/arm/assembler-arm.h index 247479d730b..e88739e4979 100644 --- a/deps/v8/src/arm/assembler-arm.h +++ b/deps/v8/src/arm/assembler-arm.h @@ -32,7 +32,7 @@ // The original source code covered by the above license above has been // modified significantly by Google Inc. -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // A light-weight ARM Assembler // Generates user mode instructions for the ARM architecture up to version 5 @@ -176,14 +176,11 @@ struct DwVfpRegister { static const int kNumAllocatableRegisters = kNumRegisters - kNumReservedRegisters; - static int ToAllocationIndex(DwVfpRegister reg) { - ASSERT(reg.code() != 0); - return reg.code() - 1; - } + inline static int ToAllocationIndex(DwVfpRegister reg); static DwVfpRegister FromAllocationIndex(int index) { ASSERT(index >= 0 && index < kNumAllocatableRegisters); - return from_code(index + 1); + return from_code(index); } static const char* AllocationIndexToString(int index) { @@ -307,6 +304,7 @@ const DwVfpRegister d15 = { 15 }; static const DwVfpRegister& kFirstCalleeSavedDoubleReg = d8; static const DwVfpRegister& kLastCalleeSavedDoubleReg = d15; static const DwVfpRegister& kDoubleRegZero = d14; +static const DwVfpRegister& kScratchDoubleReg = d15; // Coprocessor register diff --git a/deps/v8/src/arm/builtins-arm.cc b/deps/v8/src/arm/builtins-arm.cc index 69ef1872c76..2a650a44a5a 100644 --- a/deps/v8/src/arm/builtins-arm.cc +++ b/deps/v8/src/arm/builtins-arm.cc @@ -333,7 +333,7 @@ static void ArrayNativeCode(MacroAssembler* masm, r5, call_generic_code); __ IncrementCounter(counters->array_function_native(), 1, r3, r4); - // Setup return value, remove receiver from stack and return. + // Set up return value, remove receiver from stack and return. __ mov(r0, r2); __ add(sp, sp, Operand(kPointerSize)); __ Jump(lr); @@ -376,7 +376,7 @@ static void ArrayNativeCode(MacroAssembler* masm, true, call_generic_code); __ IncrementCounter(counters->array_function_native(), 1, r2, r4); - // Setup return value, remove receiver and argument from stack and return. + // Set up return value, remove receiver and argument from stack and return. __ mov(r0, r3); __ add(sp, sp, Operand(2 * kPointerSize)); __ Jump(lr); @@ -951,10 +951,10 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, // sp[4]: number of arguments (smi-tagged) __ ldr(r3, MemOperand(sp, 4 * kPointerSize)); - // Setup pointer to last argument. + // Set up pointer to last argument. __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset)); - // Setup number of arguments for function call below + // Set up number of arguments for function call below __ mov(r0, Operand(r3, LSR, kSmiTagSize)); // Copy arguments and receiver to the expression stack. @@ -1082,10 +1082,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, // Set up the context from the function argument. __ 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)); + __ InitializeRootRegister(); // 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 e95e2cf4216..15ef9bcf9de 100644 --- a/deps/v8/src/arm/code-stubs-arm.cc +++ b/deps/v8/src/arm/code-stubs-arm.cc @@ -156,13 +156,13 @@ void FastNewContextStub::Generate(MacroAssembler* masm) { // Load the function from the stack. __ ldr(r3, MemOperand(sp, 0)); - // Setup the object header. + // Set up the object header. __ LoadRoot(r2, Heap::kFunctionContextMapRootIndex); __ str(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); __ mov(r2, Operand(Smi::FromInt(length))); __ str(r2, FieldMemOperand(r0, FixedArray::kLengthOffset)); - // Setup the fixed slots. + // Set up the fixed slots. __ mov(r1, Operand(Smi::FromInt(0))); __ str(r3, MemOperand(r0, Context::SlotOffset(Context::CLOSURE_INDEX))); __ str(cp, MemOperand(r0, Context::SlotOffset(Context::PREVIOUS_INDEX))); @@ -207,7 +207,7 @@ void FastNewBlockContextStub::Generate(MacroAssembler* masm) { // Load the serialized scope info from the stack. __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); - // Setup the object header. + // Set up the object header. __ LoadRoot(r2, Heap::kBlockContextMapRootIndex); __ str(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); __ mov(r2, Operand(Smi::FromInt(length))); @@ -229,7 +229,7 @@ void FastNewBlockContextStub::Generate(MacroAssembler* masm) { __ ldr(r3, ContextOperand(r3, Context::CLOSURE_INDEX)); __ bind(&after_sentinel); - // Setup the fixed slots. + // Set up the fixed slots. __ str(r3, ContextOperand(r0, Context::CLOSURE_INDEX)); __ str(cp, ContextOperand(r0, Context::PREVIOUS_INDEX)); __ str(r1, ContextOperand(r0, Context::EXTENSION_INDEX)); @@ -717,7 +717,7 @@ void FloatingPointHelper::ConvertIntToDouble(MacroAssembler* masm, // Get the absolute value of the object (as an unsigned integer). __ rsb(int_scratch, int_scratch, Operand::Zero(), SetCC, mi); - // Get mantisssa[51:20]. + // Get mantissa[51:20]. // Get the position of the first set bit. __ CountLeadingZeros(dst1, int_scratch, scratch2); @@ -951,7 +951,7 @@ void FloatingPointHelper::DoubleIs32BitInteger(MacroAssembler* masm, // non zero bits left. So we need the (30 - exponent) last bits of the // 31 higher bits of the mantissa to be null. // Because bits [21:0] are null, we can check instead that the - // (32 - exponent) last bits of the 32 higher bits of the mantisssa are null. + // (32 - exponent) last bits of the 32 higher bits of the mantissa are null. // Get the 32 higher bits of the mantissa in dst. __ Ubfx(dst, @@ -3842,7 +3842,7 @@ void CEntryStub::Generate(MacroAssembler* masm) { FrameScope scope(masm, StackFrame::MANUAL); __ EnterExitFrame(save_doubles_); - // Setup argc and the builtin function in callee-saved registers. + // Set up argc and the builtin function in callee-saved registers. __ mov(r4, Operand(r0)); __ mov(r5, Operand(r1)); @@ -3919,7 +3919,7 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { // r2: receiver // r3: argc - // Setup argv in r4. + // Set up argv in r4. int offset_to_argv = (kNumCalleeSaved + 1) * kPointerSize; if (CpuFeatures::IsSupported(VFP3)) { offset_to_argv += kNumDoubleCalleeSaved * kDoubleSize; @@ -3942,7 +3942,7 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { __ ldr(r5, MemOperand(r5)); __ Push(r8, r7, r6, r5); - // Setup frame pointer for the frame to be pushed. + // Set up frame pointer for the frame to be pushed. __ add(fp, sp, Operand(-EntryFrameConstants::kCallerFPOffset)); // If this is the outermost JS call, set js_entry_sp value. @@ -4081,7 +4081,7 @@ void InstanceofStub::Generate(MacroAssembler* masm) { const Register inline_site = r9; const Register scratch = r2; - const int32_t kDeltaToLoadBoolResult = 3 * kPointerSize; + const int32_t kDeltaToLoadBoolResult = 4 * kPointerSize; Label slow, loop, is_instance, is_not_instance, not_js_object; @@ -4132,7 +4132,8 @@ void InstanceofStub::Generate(MacroAssembler* masm) { __ sub(inline_site, lr, scratch); // Get the map location in scratch and patch it. __ GetRelocatedValueLocation(inline_site, scratch); - __ str(map, MemOperand(scratch)); + __ ldr(scratch, MemOperand(scratch)); + __ str(map, FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); } // Register mapping: r3 is object map and r4 is function prototype. @@ -4401,7 +4402,7 @@ void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) { __ str(r3, FieldMemOperand(r0, i)); } - // Setup the callee in-object property. + // Set up the callee in-object property. STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); __ ldr(r3, MemOperand(sp, 2 * kPointerSize)); const int kCalleeOffset = JSObject::kHeaderSize + @@ -4414,7 +4415,7 @@ void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) { Heap::kArgumentsLengthIndex * kPointerSize; __ str(r2, FieldMemOperand(r0, kLengthOffset)); - // Setup the elements pointer in the allocated arguments object. + // Set up the elements pointer in the allocated arguments object. // If we allocated a parameter map, r4 will point there, otherwise // it will point to the backing store. __ add(r4, r0, Operand(Heap::kArgumentsObjectSize)); @@ -4509,7 +4510,7 @@ void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) { __ Ret(); // Do the runtime call to allocate the arguments object. - // r2 = argument count (taggged) + // r2 = argument count (tagged) __ bind(&runtime); __ str(r2, MemOperand(sp, 0 * kPointerSize)); // Patch argument count. __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); @@ -4582,7 +4583,7 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { // Get the parameters pointer from the stack. __ ldr(r2, MemOperand(sp, 1 * kPointerSize)); - // Setup the elements pointer in the allocated arguments object and + // Set up the elements pointer in the allocated arguments object and // initialize the header in the elements fixed array. __ add(r4, r0, Operand(Heap::kArgumentsObjectSizeStrict)); __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset)); @@ -4594,7 +4595,7 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { // Copy the fixed array slots. Label loop; - // Setup r4 to point to the first array slot. + // Set up r4 to point to the first array slot. __ add(r4, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); __ bind(&loop); // Pre-decrement r2 with kPointerSize on each iteration. @@ -5209,7 +5210,7 @@ void CallFunctionStub::Generate(MacroAssembler* masm) { // of the original receiver from the call site). __ bind(&non_function); __ str(r1, MemOperand(sp, argc_ * kPointerSize)); - __ mov(r0, Operand(argc_)); // Setup the number of arguments. + __ mov(r0, Operand(argc_)); // Set up the number of arguments. __ mov(r2, Operand(0, RelocInfo::NONE)); __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); __ SetCallKind(r5, CALL_AS_METHOD); @@ -5730,7 +5731,7 @@ void StringHelper::GenerateHashInit(MacroAssembler* masm, Register hash, Register character) { // hash = character + (character << 10); - __ LoadRoot(hash, Heap::kStringHashSeedRootIndex); + __ LoadRoot(hash, Heap::kHashSeedRootIndex); // Untag smi seed and add the character. __ add(hash, character, Operand(hash, LSR, kSmiTagSize)); // hash += hash << 10; @@ -5759,13 +5760,12 @@ void StringHelper::GenerateHashGetHash(MacroAssembler* masm, // hash ^= hash >> 11; __ eor(hash, hash, Operand(hash, LSR, 11)); // hash += hash << 15; - __ add(hash, hash, Operand(hash, LSL, 15), SetCC); + __ add(hash, hash, Operand(hash, LSL, 15)); - uint32_t kHashShiftCutOffMask = (1 << (32 - String::kHashShift)) - 1; - __ and_(hash, hash, Operand(kHashShiftCutOffMask)); + __ and_(hash, hash, Operand(String::kHashBitMask), SetCC); // if (hash == 0) hash = 27; - __ mov(hash, Operand(27), LeaveCC, eq); + __ mov(hash, Operand(StringHasher::kZeroHash), LeaveCC, eq); } diff --git a/deps/v8/src/arm/cpu-arm.cc b/deps/v8/src/arm/cpu-arm.cc index 51cfeb6c87f..7b08ed8c2f0 100644 --- a/deps/v8/src/arm/cpu-arm.cc +++ b/deps/v8/src/arm/cpu-arm.cc @@ -41,7 +41,7 @@ namespace v8 { namespace internal { -void CPU::Setup() { +void CPU::SetUp() { CpuFeatures::Probe(); } diff --git a/deps/v8/src/arm/deoptimizer-arm.cc b/deps/v8/src/arm/deoptimizer-arm.cc index 4b54b6dbc28..3689a9f6b6b 100644 --- a/deps/v8/src/arm/deoptimizer-arm.cc +++ b/deps/v8/src/arm/deoptimizer-arm.cc @@ -319,7 +319,7 @@ void Deoptimizer::DoComputeOsrOutputFrame() { output_[0] = input_; output_[0]->SetPc(reinterpret_cast<uint32_t>(from_)); } else { - // Setup the frame pointer and the context pointer. + // Set up the frame pointer and the context pointer. output_[0]->SetRegister(fp.code(), input_->GetRegister(fp.code())); output_[0]->SetRegister(cp.code(), input_->GetRegister(cp.code())); @@ -723,10 +723,7 @@ void Deoptimizer::EntryGenerator::Generate() { __ pop(ip); // remove sp __ pop(ip); // remove lr - // Set up the roots register. - ExternalReference roots_array_start = - ExternalReference::roots_array_start(isolate); - __ mov(r10, Operand(roots_array_start)); + __ InitializeRootRegister(); __ 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 7e9a889116a..38999a8e366 100644 --- a/deps/v8/src/arm/full-codegen-arm.cc +++ b/deps/v8/src/arm/full-codegen-arm.cc @@ -1009,7 +1009,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ ldr(r1, FieldMemOperand(r1, DescriptorArray::kEnumerationIndexOffset)); __ ldr(r2, FieldMemOperand(r1, DescriptorArray::kEnumCacheBridgeCacheOffset)); - // Setup the four remaining stack slots. + // Set up the four remaining stack slots. __ push(r0); // Map. __ ldr(r1, FieldMemOperand(r2, FixedArray::kLengthOffset)); __ mov(r0, Operand(Smi::FromInt(0))); diff --git a/deps/v8/src/arm/lithium-arm.cc b/deps/v8/src/arm/lithium-arm.cc index b001ecada06..e063ef11326 100644 --- a/deps/v8/src/arm/lithium-arm.cc +++ b/deps/v8/src/arm/lithium-arm.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -1038,14 +1038,23 @@ LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { - HValue* v = instr->value(); - if (v->EmitAtUses()) { - HBasicBlock* successor = HConstant::cast(v)->ToBoolean() + HValue* value = instr->value(); + if (value->EmitAtUses()) { + HBasicBlock* successor = HConstant::cast(value)->ToBoolean() ? instr->FirstSuccessor() : instr->SecondSuccessor(); return new LGoto(successor->block_id()); } - return AssignEnvironment(new LBranch(UseRegister(v))); + + LBranch* result = new LBranch(UseRegister(value)); + // Tagged values that are not known smis or booleans require a + // deoptimization environment. + Representation rep = value->representation(); + HType type = value->type(); + if (rep.IsTagged() && !type.IsSmi() && !type.IsBoolean()) { + return AssignEnvironment(result); + } + return result; } @@ -1344,7 +1353,12 @@ LInstruction* LChunkBuilder::DoMul(HMul* instr) { } else { left = UseRegisterAtStart(instr->LeastConstantOperand()); } - return AssignEnvironment(DefineAsRegister(new LMulI(left, right, temp))); + LMulI* mul = new LMulI(left, right, temp); + if (instr->CheckFlag(HValue::kCanOverflow) || + instr->CheckFlag(HValue::kBailoutOnMinusZero)) { + AssignEnvironment(mul); + } + return DefineAsRegister(mul); } else if (instr->representation().IsDouble()) { return DoArithmeticD(Token::MUL, instr); @@ -1413,6 +1427,15 @@ LInstruction* LChunkBuilder::DoPower(HPower* instr) { } +LInstruction* LChunkBuilder::DoRandom(HRandom* instr) { + ASSERT(instr->representation().IsDouble()); + ASSERT(instr->global_object()->representation().IsTagged()); + LOperand* global_object = UseFixed(instr->global_object(), r0); + LRandom* result = new LRandom(global_object); + return MarkAsCall(DefineFixedDouble(result, d7), instr); +} + + LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) { ASSERT(instr->left()->representation().IsTagged()); ASSERT(instr->right()->representation().IsTagged()); @@ -1529,7 +1552,7 @@ LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch( LInstruction* LChunkBuilder::DoClassOfTestAndBranch( HClassOfTestAndBranch* instr) { ASSERT(instr->value()->representation().IsTagged()); - return new LClassOfTestAndBranch(UseTempRegister(instr->value()), + return new LClassOfTestAndBranch(UseRegister(instr->value()), TempRegister()); } @@ -1556,7 +1579,7 @@ LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) { LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) { LOperand* object = UseRegister(instr->value()); LValueOf* result = new LValueOf(object, TempRegister()); - return AssignEnvironment(DefineAsRegister(result)); + return DefineAsRegister(result); } @@ -1874,7 +1897,8 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement( LOperand* obj = UseRegisterAtStart(instr->object()); LOperand* key = UseRegisterAtStart(instr->key()); LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key); - return AssignEnvironment(DefineAsRegister(result)); + if (instr->RequiresHoleCheck()) AssignEnvironment(result); + return DefineAsRegister(result); } diff --git a/deps/v8/src/arm/lithium-arm.h b/deps/v8/src/arm/lithium-arm.h index 703666c4a15..d3aff76e181 100644 --- a/deps/v8/src/arm/lithium-arm.h +++ b/deps/v8/src/arm/lithium-arm.h @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -141,6 +141,7 @@ class LCodeGen; V(Parameter) \ V(Power) \ V(PushArgument) \ + V(Random) \ V(RegExpLiteral) \ V(Return) \ V(ShiftI) \ @@ -1026,6 +1027,17 @@ class LPower: public LTemplateInstruction<1, 2, 0> { }; +class LRandom: public LTemplateInstruction<1, 1, 0> { + public: + explicit LRandom(LOperand* global_object) { + inputs_[0] = global_object; + } + + DECLARE_CONCRETE_INSTRUCTION(Random, "random") + DECLARE_HYDROGEN_ACCESSOR(Random) +}; + + class LArithmeticD: public LTemplateInstruction<1, 2, 0> { public: LArithmeticD(Token::Value op, 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 e1e35d251ec..b5ed517087a 100644 --- a/deps/v8/src/arm/lithium-codegen-arm.cc +++ b/deps/v8/src/arm/lithium-codegen-arm.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -1994,7 +1994,7 @@ void LCodeGen::DoHasCachedArrayIndexAndBranch( // Branches to a label or falls through with the answer in flags. Trashes -// the temp registers, but not the input. Only input and temp2 may alias. +// the temp registers, but not the input. void LCodeGen::EmitClassOfTest(Label* is_true, Label* is_false, Handle<String>class_name, @@ -2002,7 +2002,9 @@ void LCodeGen::EmitClassOfTest(Label* is_true, Register temp, Register temp2) { ASSERT(!input.is(temp)); - ASSERT(!temp.is(temp2)); // But input and temp2 may be the same register. + ASSERT(!input.is(temp2)); + ASSERT(!temp.is(temp2)); + __ JumpIfSmi(input, is_false); if (class_name->IsEqualTo(CStrVector("Function"))) { @@ -2141,7 +2143,10 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { // We use Factory::the_hole_value() on purpose instead of loading from the // root array to force relocation to be able to later patch with // the cached map. - __ mov(ip, Operand(factory()->the_hole_value())); + Handle<JSGlobalPropertyCell> cell = + factory()->NewJSGlobalPropertyCell(factory()->the_hole_value()); + __ mov(ip, Operand(Handle<Object>(cell))); + __ ldr(ip, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset)); __ cmp(map, Operand(ip)); __ b(ne, &cache_miss); // We use Factory::the_hole_value() on purpose instead of loading from the @@ -2901,7 +2906,7 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function, __ ldr(ip, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); __ Call(ip); - // Setup deoptimization. + // Set up deoptimization. RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); // Restore context. @@ -3190,6 +3195,30 @@ void LCodeGen::DoPower(LPower* instr) { } +void LCodeGen::DoRandom(LRandom* instr) { + // Having marked this instruction as a call we can use any + // registers. + ASSERT(ToDoubleRegister(instr->result()).is(d7)); + ASSERT(ToRegister(instr->InputAt(0)).is(r0)); + + __ PrepareCallCFunction(1, scratch0()); + __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalContextOffset)); + __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); + + // 0x41300000 is the top half of 1.0 x 2^20 as a double. + // Create this constant using mov/orr to avoid PC relative load. + __ mov(r1, Operand(0x41000000)); + __ orr(r1, r1, Operand(0x300000)); + // Move 0x41300000xxxxxxxx (x = random bits) to VFP. + __ vmov(d7, r0, r1); + // Move 0x4130000000000000 to VFP. + __ mov(r0, Operand(0, RelocInfo::NONE)); + __ vmov(d8, r0, r1); + // Subtract and store the result in the heap number. + __ vsub(d7, d7, d8); +} + + void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { ASSERT(ToDoubleRegister(instr->result()).is(d2)); TranscendentalCacheStub stub(TranscendentalCache::LOG, @@ -3874,6 +3903,7 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) { void LCodeGen::EmitNumberUntagD(Register input_reg, DoubleRegister result_reg, bool deoptimize_on_undefined, + bool deoptimize_on_minus_zero, LEnvironment* env) { Register scratch = scratch0(); SwVfpRegister flt_scratch = double_scratch0().low(); @@ -3909,6 +3939,14 @@ void LCodeGen::EmitNumberUntagD(Register input_reg, // Heap number to double register conversion. __ sub(ip, input_reg, Operand(kHeapObjectTag)); __ vldr(result_reg, ip, HeapNumber::kValueOffset); + if (deoptimize_on_minus_zero) { + __ vmov(ip, result_reg.low()); + __ cmp(ip, Operand(0)); + __ b(ne, &done); + __ vmov(ip, result_reg.high()); + __ cmp(ip, Operand(HeapNumber::kSignMask)); + DeoptimizeIf(eq, env); + } __ jmp(&done); // Smi to double register conversion @@ -4042,6 +4080,7 @@ void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { EmitNumberUntagD(input_reg, result_reg, instr->hydrogen()->deoptimize_on_undefined(), + instr->hydrogen()->deoptimize_on_minus_zero(), instr->environment()); } @@ -4155,14 +4194,26 @@ void LCodeGen::DoCheckFunction(LCheckFunction* instr) { } +void LCodeGen::DoCheckMapCommon(Register reg, + Register scratch, + Handle<Map> map, + CompareMapMode mode, + LEnvironment* env) { + Label success; + __ CompareMap(reg, scratch, map, &success, mode); + DeoptimizeIf(ne, env); + __ bind(&success); +} + + void LCodeGen::DoCheckMap(LCheckMap* instr) { Register scratch = scratch0(); LOperand* input = instr->InputAt(0); ASSERT(input->IsRegister()); Register reg = ToRegister(input); - __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); - __ cmp(scratch, Operand(instr->hydrogen()->map())); - DeoptimizeIf(ne, instr->environment()); + Handle<Map> map = instr->hydrogen()->map(); + DoCheckMapCommon(reg, scratch, map, instr->hydrogen()->mode(), + instr->environment()); } @@ -4231,9 +4282,9 @@ void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { // Check prototype maps up to the holder. while (!current_prototype.is_identical_to(holder)) { - __ ldr(temp2, FieldMemOperand(temp1, HeapObject::kMapOffset)); - __ cmp(temp2, Operand(Handle<Map>(current_prototype->map()))); - DeoptimizeIf(ne, instr->environment()); + DoCheckMapCommon(temp1, temp2, + Handle<Map>(current_prototype->map()), + ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment()); current_prototype = Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype())); // Load next prototype object. @@ -4241,8 +4292,9 @@ void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { } // Check the holder map. - __ ldr(temp2, FieldMemOperand(temp1, HeapObject::kMapOffset)); - __ cmp(temp2, Operand(Handle<Map>(current_prototype->map()))); + DoCheckMapCommon(temp1, temp2, + Handle<Map>(current_prototype->map()), + ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment()); DeoptimizeIf(ne, instr->environment()); } diff --git a/deps/v8/src/arm/lithium-codegen-arm.h b/deps/v8/src/arm/lithium-codegen-arm.h index e6626481b3a..00823e1638c 100644 --- a/deps/v8/src/arm/lithium-codegen-arm.h +++ b/deps/v8/src/arm/lithium-codegen-arm.h @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -119,6 +119,9 @@ class LCodeGen BASE_EMBEDDED { void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, Label* map_check); + void DoCheckMapCommon(Register reg, Register scratch, Handle<Map> map, + CompareMapMode mode, LEnvironment* env); + // Parallel move support. void DoParallelMove(LParallelMove* move); void DoGap(LGap* instr); @@ -153,7 +156,7 @@ class LCodeGen BASE_EMBEDDED { HGraph* graph() const { return chunk_->graph(); } Register scratch0() { return r9; } - DwVfpRegister double_scratch0() { return d15; } + DwVfpRegister double_scratch0() { return kScratchDoubleReg; } int GetNextEmittedBlock(int block); LInstruction* GetNextInstruction(); @@ -270,6 +273,7 @@ class LCodeGen BASE_EMBEDDED { void EmitNumberUntagD(Register input, DoubleRegister result, bool deoptimize_on_undefined, + bool deoptimize_on_minus_zero, LEnvironment* env); // Emits optimized code for typeof x == "y". Modifies input register. @@ -408,7 +412,7 @@ class LDeferredCode: public ZoneObject { virtual void Generate() = 0; virtual LInstruction* instr() = 0; - void SetExit(Label *exit) { external_exit_ = exit; } + void SetExit(Label* exit) { external_exit_ = exit; } Label* entry() { return &entry_; } Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; } int instruction_index() const { return instruction_index_; } diff --git a/deps/v8/src/arm/lithium-gap-resolver-arm.cc b/deps/v8/src/arm/lithium-gap-resolver-arm.cc index ee6cb8ec91c..cefca476ade 100644 --- a/deps/v8/src/arm/lithium-gap-resolver-arm.cc +++ b/deps/v8/src/arm/lithium-gap-resolver-arm.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -34,7 +34,6 @@ namespace v8 { namespace internal { static const Register kSavedValueRegister = { 9 }; -static const DoubleRegister kSavedDoubleValueRegister = { 0 }; LGapResolver::LGapResolver(LCodeGen* owner) : cgen_(owner), moves_(32), root_index_(0), in_cycle_(false), @@ -172,9 +171,9 @@ void LGapResolver::BreakCycle(int index) { } else if (source->IsStackSlot()) { __ ldr(kSavedValueRegister, cgen_->ToMemOperand(source)); } else if (source->IsDoubleRegister()) { - __ vmov(kSavedDoubleValueRegister, cgen_->ToDoubleRegister(source)); + __ vmov(kScratchDoubleReg, cgen_->ToDoubleRegister(source)); } else if (source->IsDoubleStackSlot()) { - __ vldr(kSavedDoubleValueRegister, cgen_->ToMemOperand(source)); + __ vldr(kScratchDoubleReg, cgen_->ToMemOperand(source)); } else { UNREACHABLE(); } @@ -193,11 +192,9 @@ void LGapResolver::RestoreValue() { } else if (saved_destination_->IsStackSlot()) { __ str(kSavedValueRegister, cgen_->ToMemOperand(saved_destination_)); } else if (saved_destination_->IsDoubleRegister()) { - __ vmov(cgen_->ToDoubleRegister(saved_destination_), - kSavedDoubleValueRegister); + __ vmov(cgen_->ToDoubleRegister(saved_destination_), kScratchDoubleReg); } else if (saved_destination_->IsDoubleStackSlot()) { - __ vstr(kSavedDoubleValueRegister, - cgen_->ToMemOperand(saved_destination_)); + __ vstr(kScratchDoubleReg, cgen_->ToMemOperand(saved_destination_)); } else { UNREACHABLE(); } @@ -235,8 +232,8 @@ void LGapResolver::EmitMove(int index) { // ip is overwritten while saving the value to the destination. // Therefore we can't use ip. It is OK if the read from the source // destroys ip, since that happens before the value is read. - __ vldr(kSavedDoubleValueRegister.low(), source_operand); - __ vstr(kSavedDoubleValueRegister.low(), destination_operand); + __ vldr(kScratchDoubleReg.low(), source_operand); + __ vstr(kScratchDoubleReg.low(), destination_operand); } else { __ ldr(ip, source_operand); __ str(ip, destination_operand); @@ -297,8 +294,8 @@ void LGapResolver::EmitMove(int index) { __ ldr(kSavedValueRegister, source_high_operand); __ str(kSavedValueRegister, destination_high_operand); } else { - __ vldr(kSavedDoubleValueRegister, source_operand); - __ vstr(kSavedDoubleValueRegister, destination_operand); + __ vldr(kScratchDoubleReg, source_operand); + __ vstr(kScratchDoubleReg, destination_operand); } } } else { diff --git a/deps/v8/src/arm/macro-assembler-arm.cc b/deps/v8/src/arm/macro-assembler-arm.cc index 59a5e5ba79e..fa97611cf83 100644 --- a/deps/v8/src/arm/macro-assembler-arm.cc +++ b/deps/v8/src/arm/macro-assembler-arm.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -396,14 +396,14 @@ void MacroAssembler::Usat(Register dst, int satpos, const Operand& src, void MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index, Condition cond) { - ldr(destination, MemOperand(roots, index << kPointerSizeLog2), cond); + ldr(destination, MemOperand(kRootRegister, index << kPointerSizeLog2), cond); } void MacroAssembler::StoreRoot(Register source, Heap::RootListIndex index, Condition cond) { - str(source, MemOperand(roots, index << kPointerSizeLog2), cond); + str(source, MemOperand(kRootRegister, index << kPointerSizeLog2), cond); } @@ -496,13 +496,10 @@ void MacroAssembler::RecordWrite(Register object, // registers are cp. ASSERT(!address.is(cp) && !value.is(cp)); - if (FLAG_debug_code) { - Label ok; + if (emit_debug_code()) { ldr(ip, MemOperand(address)); cmp(ip, value); - b(eq, &ok); - stop("Wrong address or value passed to RecordWrite"); - bind(&ok); + Check(eq, "Wrong address or value passed to RecordWrite"); } Label done; @@ -551,7 +548,7 @@ void MacroAssembler::RememberedSetHelper(Register object, // For debug tests. SaveFPRegsMode fp_mode, RememberedSetFinalAction and_then) { Label done; - if (FLAG_debug_code) { + if (emit_debug_code()) { Label ok; JumpIfNotInNewSpace(object, scratch, &ok); stop("Remembered set pointer is in new space"); @@ -820,12 +817,12 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) { void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) { - // Setup the frame structure on the stack. + // Set up the frame structure on the stack. ASSERT_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement); ASSERT_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset); ASSERT_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset); Push(lr, fp); - mov(fp, Operand(sp)); // Setup new frame pointer. + mov(fp, Operand(sp)); // Set up new frame pointer. // Reserve room for saved entry sp and code object. sub(sp, sp, Operand(2 * kPointerSize)); if (emit_debug_code()) { @@ -1414,6 +1411,35 @@ void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, } +void MacroAssembler::GetNumberHash(Register t0, Register scratch) { + // First of all we assign the hash seed to scratch. + LoadRoot(scratch, Heap::kHashSeedRootIndex); + SmiUntag(scratch); + + // Xor original key with a seed. + eor(t0, t0, Operand(scratch)); + + // Compute the hash code from the untagged key. This must be kept in sync + // with ComputeIntegerHash in utils.h. + // + // hash = ~hash + (hash << 15); + mvn(scratch, Operand(t0)); + add(t0, scratch, Operand(t0, LSL, 15)); + // hash = hash ^ (hash >> 12); + eor(t0, t0, Operand(t0, LSR, 12)); + // hash = hash + (hash << 2); + add(t0, t0, Operand(t0, LSL, 2)); + // hash = hash ^ (hash >> 4); + eor(t0, t0, Operand(t0, LSR, 4)); + // hash = hash * 2057; + mov(scratch, Operand(t0, LSL, 11)); + add(t0, t0, Operand(t0, LSL, 3)); + add(t0, t0, scratch); + // hash = hash ^ (hash >> 16); + eor(t0, t0, Operand(t0, LSR, 16)); +} + + void MacroAssembler::LoadFromNumberDictionary(Label* miss, Register elements, Register key, @@ -1443,26 +1469,10 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, // t2 - used for the index into the dictionary. Label done; - // Compute the hash code from the untagged key. This must be kept in sync - // with ComputeIntegerHash in utils.h. - // - // hash = ~hash + (hash << 15); - mvn(t1, Operand(t0)); - add(t0, t1, Operand(t0, LSL, 15)); - // hash = hash ^ (hash >> 12); - eor(t0, t0, Operand(t0, LSR, 12)); - // hash = hash + (hash << 2); - add(t0, t0, Operand(t0, LSL, 2)); - // hash = hash ^ (hash >> 4); - eor(t0, t0, Operand(t0, LSR, 4)); - // hash = hash * 2057; - mov(t1, Operand(2057)); - mul(t0, t0, t1); - // hash = hash ^ (hash >> 16); - eor(t0, t0, Operand(t0, LSR, 16)); + GetNumberHash(t0, t1); // Compute the capacity mask. - ldr(t1, FieldMemOperand(elements, NumberDictionary::kCapacityOffset)); + ldr(t1, FieldMemOperand(elements, SeededNumberDictionary::kCapacityOffset)); mov(t1, Operand(t1, ASR, kSmiTagSize)); // convert smi to int sub(t1, t1, Operand(1)); @@ -1473,17 +1483,17 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, mov(t2, t0); // Compute the masked index: (hash + i + i * i) & mask. if (i > 0) { - add(t2, t2, Operand(NumberDictionary::GetProbeOffset(i))); + add(t2, t2, Operand(SeededNumberDictionary::GetProbeOffset(i))); } and_(t2, t2, Operand(t1)); // Scale the index by multiplying by the element size. - ASSERT(NumberDictionary::kEntrySize == 3); + ASSERT(SeededNumberDictionary::kEntrySize == 3); add(t2, t2, Operand(t2, LSL, 1)); // t2 = t2 * 3 // Check if the key is identical to the name. add(t2, elements, Operand(t2, LSL, kPointerSizeLog2)); - ldr(ip, FieldMemOperand(t2, NumberDictionary::kElementsStartOffset)); + ldr(ip, FieldMemOperand(t2, SeededNumberDictionary::kElementsStartOffset)); cmp(key, Operand(ip)); if (i != kProbes - 1) { b(eq, &done); @@ -1496,14 +1506,14 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, // Check that the value is a normal property. // t2: elements + (index * kPointerSize) const int kDetailsOffset = - NumberDictionary::kElementsStartOffset + 2 * kPointerSize; + SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize; ldr(t1, FieldMemOperand(t2, kDetailsOffset)); tst(t1, Operand(Smi::FromInt(PropertyDetails::TypeField::kMask))); b(ne, miss); // Get the value at the masked, scaled index and return. const int kValueOffset = - NumberDictionary::kElementsStartOffset + kPointerSize; + SeededNumberDictionary::kElementsStartOffset + kPointerSize; ldr(result, FieldMemOperand(t2, kValueOffset)); } @@ -1992,18 +2002,49 @@ void MacroAssembler::StoreNumberToDoubleElements(Register value_reg, } +void MacroAssembler::CompareMap(Register obj, + Register scratch, + Handle<Map> map, + Label* early_success, + CompareMapMode mode) { + ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); + cmp(scratch, Operand(map)); + if (mode == ALLOW_ELEMENT_TRANSITION_MAPS) { + Map* transitioned_fast_element_map( + map->LookupElementsTransitionMap(FAST_ELEMENTS, NULL)); + ASSERT(transitioned_fast_element_map == NULL || + map->elements_kind() != FAST_ELEMENTS); + if (transitioned_fast_element_map != NULL) { + b(eq, early_success); + cmp(scratch, Operand(Handle<Map>(transitioned_fast_element_map))); + } + + Map* transitioned_double_map( + map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, NULL)); + ASSERT(transitioned_double_map == NULL || + map->elements_kind() == FAST_SMI_ONLY_ELEMENTS); + if (transitioned_double_map != NULL) { + b(eq, early_success); + cmp(scratch, Operand(Handle<Map>(transitioned_double_map))); + } + } +} + + void MacroAssembler::CheckMap(Register obj, Register scratch, Handle<Map> map, Label* fail, - SmiCheckType smi_check_type) { + SmiCheckType smi_check_type, + CompareMapMode mode) { if (smi_check_type == DO_SMI_CHECK) { JumpIfSmi(obj, fail); } - ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset)); - mov(ip, Operand(map)); - cmp(scratch, ip); + + Label success; + CompareMap(obj, scratch, map, &success, mode); b(ne, fail); + bind(&success); } @@ -3460,7 +3501,7 @@ void MacroAssembler::EnsureNotWhite( tst(mask_scratch, load_scratch); b(ne, &done); - if (FLAG_debug_code) { + if (emit_debug_code()) { // Check for impossible bit pattern. Label ok; // LSL may overflow, making the check conservative. diff --git a/deps/v8/src/arm/macro-assembler-arm.h b/deps/v8/src/arm/macro-assembler-arm.h index 392c2f7503f..4b55a3b0641 100644 --- a/deps/v8/src/arm/macro-assembler-arm.h +++ b/deps/v8/src/arm/macro-assembler-arm.h @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -52,7 +52,7 @@ inline Operand SmiUntagOperand(Register object) { // Give alias names to registers const Register cp = { 8 }; // JavaScript context pointer -const Register roots = { 10 }; // Roots array pointer. +const Register kRootRegister = { 10 }; // Roots array pointer. // Flags used for the AllocateInNewSpace functions. enum AllocationFlags { @@ -499,10 +499,16 @@ class MacroAssembler: public Assembler { Register map, Register scratch); + void InitializeRootRegister() { + ExternalReference roots_array_start = + ExternalReference::roots_array_start(isolate()); + mov(kRootRegister, Operand(roots_array_start)); + } + // --------------------------------------------------------------------------- // JavaScript invokes - // Setup call kind marking in ecx. The method takes ecx as an + // Set up call kind marking in ecx. The method takes ecx as an // explicit first parameter to make the code more readable at the // call sites. void SetCallKind(Register dst, CallKind kind); @@ -584,6 +590,7 @@ class MacroAssembler: public Assembler { Register scratch, Label* miss); + void GetNumberHash(Register t0, Register scratch); void LoadFromNumberDictionary(Label* miss, Register elements, @@ -790,15 +797,26 @@ class MacroAssembler: public Assembler { Register scratch4, Label* fail); - // Check if the map of an object is equal to a specified map (either - // given directly or as an index into the root list) and branch to - // label if not. Skip the smi check if not required (object is known - // to be a heap object) + // Compare an object's map with the specified map and its transitioned + // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. Condition flags are + // set with result of map compare. If multiple map compares are required, the + // compare sequences branches to early_success. + void CompareMap(Register obj, + Register scratch, + Handle<Map> map, + Label* early_success, + CompareMapMode mode = REQUIRE_EXACT_MAP); + + // Check if the map of an object is equal to a specified map and branch to + // label if not. Skip the smi check if not required (object is known to be a + // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match + // against maps that are ElementsKind transition maps of the specificed map. void CheckMap(Register obj, Register scratch, Handle<Map> map, Label* fail, - SmiCheckType smi_check_type); + SmiCheckType smi_check_type, + CompareMapMode mode = REQUIRE_EXACT_MAP); void CheckMap(Register obj, diff --git a/deps/v8/src/arm/simulator-arm.cc b/deps/v8/src/arm/simulator-arm.cc index 0525529fde2..1ae172c008d 100644 --- a/deps/v8/src/arm/simulator-arm.cc +++ b/deps/v8/src/arm/simulator-arm.cc @@ -741,7 +741,7 @@ Simulator::Simulator(Isolate* isolate) : isolate_(isolate) { isolate_->set_simulator_i_cache(i_cache_); } Initialize(isolate); - // Setup simulator support first. Some of this information is needed to + // Set up simulator support first. Some of this information is needed to // setup the architecture state. size_t stack_size = 1 * 1024*1024; // allocate 1MB for stack stack_ = reinterpret_cast<char*>(malloc(stack_size)); @@ -750,7 +750,7 @@ Simulator::Simulator(Isolate* isolate) : isolate_(isolate) { break_pc_ = NULL; break_instr_ = 0; - // Setup architecture state. + // Set up architecture state. // All registers are initialized to zero to start with. for (int i = 0; i < num_registers; i++) { registers_[i] = 0; @@ -3324,7 +3324,7 @@ void Simulator::Execute() { int32_t Simulator::Call(byte* entry, int argument_count, ...) { va_list parameters; va_start(parameters, argument_count); - // Setup arguments + // Set up arguments // First four arguments passed in registers. ASSERT(argument_count >= 4); @@ -3367,7 +3367,7 @@ int32_t Simulator::Call(byte* entry, int argument_count, ...) { int32_t r10_val = get_register(r10); int32_t r11_val = get_register(r11); - // Setup the callee-saved registers with a known value. To be able to check + // Set up the callee-saved registers with a known value. To be able to check // that they are preserved properly across JS execution. int32_t callee_saved_value = icount_; set_register(r4, callee_saved_value); diff --git a/deps/v8/src/arm/stub-cache-arm.cc b/deps/v8/src/arm/stub-cache-arm.cc index b6b2ee2f049..c3a82ff9344 100644 --- a/deps/v8/src/arm/stub-cache-arm.cc +++ b/deps/v8/src/arm/stub-cache-arm.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -376,13 +376,9 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm, // r0 : value Label exit; - // Check that the receiver isn't a smi. - __ JumpIfSmi(receiver_reg, miss_label); - - // Check that the map of the receiver hasn't changed. - __ ldr(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); - __ cmp(scratch, Operand(Handle<Map>(object->map()))); - __ b(ne, miss_label); + // Check that the map of the object hasn't changed. + __ CheckMap(receiver_reg, scratch, Handle<Map>(object->map()), miss_label, + DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); // Perform global security token check if needed. if (object->IsJSGlobalProxy()) { @@ -1019,10 +1015,9 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object, __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); } else { Handle<Map> 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); + __ CheckMap(reg, scratch1, current_map, miss, DONT_DO_SMI_CHECK, + ALLOW_ELEMENT_TRANSITION_MAPS); + // 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. @@ -1053,9 +1048,8 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object, LOG(masm()->isolate(), IntEvent("check-maps-depth", depth + 1)); // Check the holder map. - __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); - __ cmp(scratch1, Operand(Handle<Map>(current->map()))); - __ b(ne, miss); + __ CheckMap(reg, scratch1, Handle<Map>(current->map()), miss, + DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); // Perform security check for access to the global object. ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); @@ -1150,7 +1144,7 @@ void StubCompiler::GenerateLoadCallback(Handle<JSObject> object, __ EnterExitFrame(false, kApiStackSpace); // Create AccessorInfo instance on the stack above the exit frame with - // scratch2 (internal::Object **args_) as the data. + // scratch2 (internal::Object** args_) as the data. __ str(scratch2, MemOperand(sp, 1 * kPointerSize)); __ add(r1, sp, Operand(1 * kPointerSize)); // r1 = AccessorInfo& @@ -2411,7 +2405,7 @@ Handle<Code> CallStubCompiler::CompileCallGlobal( __ str(r3, MemOperand(sp, argc * kPointerSize)); } - // Setup the context (function already in r1). + // Set up the context (function already in r1). __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); // Jump to the cached code (tail call). @@ -2472,13 +2466,9 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback( // ----------------------------------- Label miss; - // Check that the object isn't a smi. - __ JumpIfSmi(r1, &miss); - // Check that the map of the object hasn't changed. - __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); - __ cmp(r3, Operand(Handle<Map>(object->map()))); - __ b(ne, &miss); + __ CheckMap(r1, r3, Handle<Map>(object->map()), &miss, + DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); // Perform global security token check if needed. if (object->IsJSGlobalProxy()) { @@ -2520,13 +2510,9 @@ Handle<Code> StoreStubCompiler::CompileStoreInterceptor( // ----------------------------------- Label miss; - // Check that the object isn't a smi. - __ JumpIfSmi(r1, &miss); - // Check that the map of the object hasn't changed. - __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); - __ cmp(r3, Operand(Handle<Map>(receiver->map()))); - __ b(ne, &miss); + __ CheckMap(r1, r3, Handle<Map>(receiver->map()), &miss, + DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); // Perform global security token check if needed. if (receiver->IsJSGlobalProxy()) { diff --git a/deps/v8/src/assembler.h b/deps/v8/src/assembler.h index cec20fca073..8c705a84b47 100644 --- a/deps/v8/src/assembler.h +++ b/deps/v8/src/assembler.h @@ -371,7 +371,7 @@ class RelocInfo BASE_EMBEDDED { // routines expect to access these pointers indirectly. The following // location provides a place for these pointers to exist natually // when accessed via the Iterator. - Object *reconstructed_obj_ptr_; + Object* reconstructed_obj_ptr_; // External-reference pointers are also split across instruction-pairs // in mips, but are accessed via indirect pointers. This location // provides a place for that pointer to exist naturally. Its address diff --git a/deps/v8/src/atomicops_internals_x86_macosx.h b/deps/v8/src/atomicops_internals_x86_macosx.h index 2bac006bdca..bfb02b3851f 100644 --- a/deps/v8/src/atomicops_internals_x86_macosx.h +++ b/deps/v8/src/atomicops_internals_x86_macosx.h @@ -35,7 +35,7 @@ namespace v8 { namespace internal { -inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32 *ptr, +inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, Atomic32 old_value, Atomic32 new_value) { Atomic32 prev_value; @@ -49,7 +49,7 @@ inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32 *ptr, return prev_value; } -inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32 *ptr, +inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value) { Atomic32 old_value; do { @@ -59,12 +59,12 @@ inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32 *ptr, return old_value; } -inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32 *ptr, +inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment) { return OSAtomicAdd32(increment, const_cast<Atomic32*>(ptr)); } -inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32 *ptr, +inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment) { return OSAtomicAdd32Barrier(increment, const_cast<Atomic32*>(ptr)); } @@ -73,7 +73,7 @@ inline void MemoryBarrier() { OSMemoryBarrier(); } -inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32 *ptr, +inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, Atomic32 old_value, Atomic32 new_value) { Atomic32 prev_value; @@ -87,7 +87,7 @@ inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32 *ptr, return prev_value; } -inline Atomic32 Release_CompareAndSwap(volatile Atomic32 *ptr, +inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, Atomic32 old_value, Atomic32 new_value) { return Acquire_CompareAndSwap(ptr, old_value, new_value); @@ -97,12 +97,12 @@ inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) { *ptr = value; } -inline void Acquire_Store(volatile Atomic32 *ptr, Atomic32 value) { +inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) { *ptr = value; MemoryBarrier(); } -inline void Release_Store(volatile Atomic32 *ptr, Atomic32 value) { +inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { MemoryBarrier(); *ptr = value; } @@ -111,13 +111,13 @@ inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { return *ptr; } -inline Atomic32 Acquire_Load(volatile const Atomic32 *ptr) { +inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { Atomic32 value = *ptr; MemoryBarrier(); return value; } -inline Atomic32 Release_Load(volatile const Atomic32 *ptr) { +inline Atomic32 Release_Load(volatile const Atomic32* ptr) { MemoryBarrier(); return *ptr; } @@ -126,7 +126,7 @@ inline Atomic32 Release_Load(volatile const Atomic32 *ptr) { // 64-bit implementation on 64-bit platform -inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64 *ptr, +inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, Atomic64 old_value, Atomic64 new_value) { Atomic64 prev_value; @@ -140,7 +140,7 @@ inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64 *ptr, return prev_value; } -inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64 *ptr, +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value) { Atomic64 old_value; do { @@ -150,17 +150,17 @@ inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64 *ptr, return old_value; } -inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64 *ptr, +inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment) { return OSAtomicAdd64(increment, const_cast<Atomic64*>(ptr)); } -inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64 *ptr, +inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment) { return OSAtomicAdd64Barrier(increment, const_cast<Atomic64*>(ptr)); } -inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64 *ptr, +inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, Atomic64 old_value, Atomic64 new_value) { Atomic64 prev_value; @@ -174,7 +174,7 @@ inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64 *ptr, return prev_value; } -inline Atomic64 Release_CompareAndSwap(volatile Atomic64 *ptr, +inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, Atomic64 old_value, Atomic64 new_value) { // The lib kern interface does not distinguish between @@ -186,12 +186,12 @@ inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { *ptr = value; } -inline void Acquire_Store(volatile Atomic64 *ptr, Atomic64 value) { +inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) { *ptr = value; MemoryBarrier(); } -inline void Release_Store(volatile Atomic64 *ptr, Atomic64 value) { +inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) { MemoryBarrier(); *ptr = value; } @@ -200,13 +200,13 @@ inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { return *ptr; } -inline Atomic64 Acquire_Load(volatile const Atomic64 *ptr) { +inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) { Atomic64 value = *ptr; MemoryBarrier(); return value; } -inline Atomic64 Release_Load(volatile const Atomic64 *ptr) { +inline Atomic64 Release_Load(volatile const Atomic64* ptr) { MemoryBarrier(); return *ptr; } @@ -264,7 +264,7 @@ inline AtomicWord Release_CompareAndSwap(volatile AtomicWord* ptr, old_value, new_value); } -inline void NoBarrier_Store(volatile AtomicWord *ptr, AtomicWord value) { +inline void NoBarrier_Store(volatile AtomicWord* ptr, AtomicWord value) { NoBarrier_Store( reinterpret_cast<volatile AtomicWordCastType*>(ptr), value); } @@ -279,7 +279,7 @@ inline void Release_Store(volatile AtomicWord* ptr, AtomicWord value) { reinterpret_cast<volatile AtomicWordCastType*>(ptr), value); } -inline AtomicWord NoBarrier_Load(volatile const AtomicWord *ptr) { +inline AtomicWord NoBarrier_Load(volatile const AtomicWord* ptr) { return NoBarrier_Load( reinterpret_cast<volatile const AtomicWordCastType*>(ptr)); } diff --git a/deps/v8/src/bootstrapper.cc b/deps/v8/src/bootstrapper.cc index d1bf975fb5f..752b220e5b5 100644 --- a/deps/v8/src/bootstrapper.cc +++ b/deps/v8/src/bootstrapper.cc @@ -264,13 +264,13 @@ class Genesis BASE_EMBEDDED { Handle<Map> CreateStrictModeFunctionMap( PrototypePropertyMode prototype_mode, Handle<JSFunction> empty_function, - Handle<FixedArray> arguments_callbacks, - Handle<FixedArray> caller_callbacks); + Handle<AccessorPair> arguments_callbacks, + Handle<AccessorPair> caller_callbacks); Handle<DescriptorArray> ComputeStrictFunctionInstanceDescriptor( PrototypePropertyMode propertyMode, - Handle<FixedArray> arguments, - Handle<FixedArray> caller); + Handle<AccessorPair> arguments, + Handle<AccessorPair> caller); static bool CompileBuiltin(Isolate* isolate, int index); static bool CompileExperimentalBuiltin(Isolate* isolate, int index); @@ -378,7 +378,9 @@ static Handle<JSFunction> InstallFunction(Handle<JSObject> target, } else { attributes = DONT_ENUM; } - SetLocalPropertyNoThrow(target, symbol, function, attributes); + CHECK_NOT_EMPTY_HANDLE(isolate, + JSObject::SetLocalPropertyIgnoreAttributes( + target, symbol, function, attributes)); if (is_ecma_native) { function->shared()->set_instance_class_name(*symbol); } @@ -538,8 +540,8 @@ Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) { Handle<DescriptorArray> Genesis::ComputeStrictFunctionInstanceDescriptor( PrototypePropertyMode prototypeMode, - Handle<FixedArray> arguments, - Handle<FixedArray> caller) { + Handle<AccessorPair> arguments, + Handle<AccessorPair> caller) { Handle<DescriptorArray> descriptors = factory()->NewDescriptorArray(prototypeMode == DONT_ADD_PROTOTYPE ? 4 @@ -600,7 +602,7 @@ Handle<JSFunction> Genesis::GetThrowTypeErrorFunction() { throw_type_error_function->shared()->set_code(*code); throw_type_error_function->shared()->DontAdaptArguments(); - PreventExtensions(throw_type_error_function); + JSObject::PreventExtensions(throw_type_error_function); } return throw_type_error_function; } @@ -609,8 +611,8 @@ Handle<JSFunction> Genesis::GetThrowTypeErrorFunction() { Handle<Map> Genesis::CreateStrictModeFunctionMap( PrototypePropertyMode prototype_mode, Handle<JSFunction> empty_function, - Handle<FixedArray> arguments_callbacks, - Handle<FixedArray> caller_callbacks) { + Handle<AccessorPair> arguments_callbacks, + Handle<AccessorPair> caller_callbacks) { Handle<Map> map = factory()->NewMap(JS_FUNCTION_TYPE, JSFunction::kSize); Handle<DescriptorArray> descriptors = ComputeStrictFunctionInstanceDescriptor(prototype_mode, @@ -627,8 +629,8 @@ void Genesis::CreateStrictModeFunctionMaps(Handle<JSFunction> empty) { // Create the callbacks arrays for ThrowTypeError functions. // The get/set callacks are filled in after the maps are created below. Factory* factory = empty->GetIsolate()->factory(); - Handle<FixedArray> arguments = factory->NewFixedArray(2, TENURED); - Handle<FixedArray> caller = factory->NewFixedArray(2, TENURED); + Handle<AccessorPair> arguments(factory->NewAccessorPair()); + Handle<AccessorPair> caller(factory->NewAccessorPair()); // Allocate map for the strict mode function instances. Handle<Map> strict_mode_function_instance_map = @@ -663,11 +665,11 @@ void Genesis::CreateStrictModeFunctionMaps(Handle<JSFunction> empty) { Handle<JSFunction> throw_function = GetThrowTypeErrorFunction(); - // Complete the callback fixed arrays. - arguments->set(0, *throw_function); - arguments->set(1, *throw_function); - caller->set(0, *throw_function); - caller->set(1, *throw_function); + // Complete the callbacks. + arguments->set_getter(*throw_function); + arguments->set_setter(*throw_function); + caller->set_getter(*throw_function); + caller->set_setter(*throw_function); } @@ -753,11 +755,10 @@ Handle<JSGlobalProxy> Genesis::CreateNewGlobals( Handle<JSObject> prototype = Handle<JSObject>( JSObject::cast(js_global_function->instance_prototype())); - SetLocalPropertyNoThrow( - prototype, - factory()->constructor_symbol(), - isolate()->object_function(), - NONE); + CHECK_NOT_EMPTY_HANDLE(isolate(), + JSObject::SetLocalPropertyIgnoreAttributes( + prototype, factory()->constructor_symbol(), + isolate()->object_function(), NONE)); } else { Handle<FunctionTemplateInfo> js_global_constructor( FunctionTemplateInfo::cast(js_global_template->constructor())); @@ -834,7 +835,7 @@ void Genesis::HookUpInnerGlobal(Handle<GlobalObject> inner_global) { factory()->LookupAsciiSymbol("global"), inner_global, attributes); - // Setup the reference from the global object to the builtins object. + // Set up the reference from the global object to the builtins object. JSGlobalObject::cast(*inner_global)->set_builtins(*builtins_global); TransferNamedProperties(inner_global_from_snapshot, inner_global); TransferIndexedProperties(inner_global_from_snapshot, inner_global); @@ -863,8 +864,10 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, Heap* heap = isolate->heap(); Handle<String> object_name = Handle<String>(heap->Object_symbol()); - SetLocalPropertyNoThrow(inner_global, object_name, - isolate->object_function(), DONT_ENUM); + CHECK_NOT_EMPTY_HANDLE(isolate, + JSObject::SetLocalPropertyIgnoreAttributes( + inner_global, object_name, + isolate->object_function(), DONT_ENUM)); Handle<JSObject> global = Handle<JSObject>(global_context()->global()); @@ -1046,14 +1049,15 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, { // -- J S O N Handle<String> name = factory->NewStringFromAscii(CStrVector("JSON")); - Handle<JSFunction> cons = factory->NewFunction( - name, - factory->the_hole_value()); + Handle<JSFunction> cons = factory->NewFunction(name, + factory->the_hole_value()); cons->SetInstancePrototype(global_context()->initial_object_prototype()); cons->SetInstanceClassName(*name); Handle<JSObject> json_object = factory->NewJSObject(cons, TENURED); ASSERT(json_object->IsJSObject()); - SetLocalPropertyNoThrow(global, name, json_object, DONT_ENUM); + CHECK_NOT_EMPTY_HANDLE(isolate, + JSObject::SetLocalPropertyIgnoreAttributes( + global, name, json_object, DONT_ENUM)); global_context()->set_json_object(*json_object); } @@ -1083,12 +1087,14 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, global_context()->set_arguments_boilerplate(*result); // Note: length must be added as the first property and // callee must be added as the second property. - SetLocalPropertyNoThrow(result, factory->length_symbol(), - factory->undefined_value(), - DONT_ENUM); - SetLocalPropertyNoThrow(result, factory->callee_symbol(), - factory->undefined_value(), - DONT_ENUM); + CHECK_NOT_EMPTY_HANDLE(isolate, + JSObject::SetLocalPropertyIgnoreAttributes( + result, factory->length_symbol(), + factory->undefined_value(), DONT_ENUM)); + CHECK_NOT_EMPTY_HANDLE(isolate, + JSObject::SetLocalPropertyIgnoreAttributes( + result, factory->callee_symbol(), + factory->undefined_value(), DONT_ENUM)); #ifdef DEBUG LookupResult lookup(isolate); @@ -1136,17 +1142,17 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY); // Create the ThrowTypeError functions. - Handle<FixedArray> callee = factory->NewFixedArray(2, TENURED); - Handle<FixedArray> caller = factory->NewFixedArray(2, TENURED); + Handle<AccessorPair> callee = factory->NewAccessorPair(); + Handle<AccessorPair> caller = factory->NewAccessorPair(); Handle<JSFunction> throw_function = GetThrowTypeErrorFunction(); // Install the ThrowTypeError functions. - callee->set(0, *throw_function); - callee->set(1, *throw_function); - caller->set(0, *throw_function); - caller->set(1, *throw_function); + callee->set_getter(*throw_function); + callee->set_setter(*throw_function); + caller->set_getter(*throw_function); + caller->set_setter(*throw_function); // Create the descriptor array for the arguments object. Handle<DescriptorArray> descriptors = factory->NewDescriptorArray(3); @@ -1183,9 +1189,10 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, global_context()->set_strict_mode_arguments_boilerplate(*result); // Add length property only for strict mode boilerplate. - SetLocalPropertyNoThrow(result, factory->length_symbol(), - factory->undefined_value(), - DONT_ENUM); + CHECK_NOT_EMPTY_HANDLE(isolate, + JSObject::SetLocalPropertyIgnoreAttributes( + result, factory->length_symbol(), + factory->undefined_value(), DONT_ENUM)); #ifdef DEBUG LookupResult lookup(isolate); @@ -1353,7 +1360,7 @@ bool Genesis::CompileScriptCached(Vector<const char> name, if (cache != NULL) cache->Add(name, function_info); } - // Setup the function context. Conceptually, we should clone the + // Set up the function context. Conceptually, we should clone the // function before overwriting the context but since we're in a // single-threaded environment it is not strictly necessary. ASSERT(top_context->IsGlobalContext()); @@ -1440,7 +1447,7 @@ bool Genesis::InstallNatives() { builtins->set_global_context(*global_context()); builtins->set_global_receiver(*builtins); - // Setup the 'global' properties of the builtins object. The + // Set up the 'global' properties of the builtins object. The // 'global' property that refers to the global object is the only // way to get from code running in the builtins context to the // global object. @@ -1448,9 +1455,11 @@ bool Genesis::InstallNatives() { static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE); Handle<String> global_symbol = factory()->LookupAsciiSymbol("global"); Handle<Object> global_obj(global_context()->global()); - SetLocalPropertyNoThrow(builtins, global_symbol, global_obj, attributes); + CHECK_NOT_EMPTY_HANDLE(isolate(), + JSObject::SetLocalPropertyIgnoreAttributes( + builtins, global_symbol, global_obj, attributes)); - // Setup the reference from the global object to the builtins object. + // Set up the reference from the global object to the builtins object. JSGlobalObject::cast(global_context()->global())->set_builtins(*builtins); // Create a bridge function that has context in the global context. @@ -1674,7 +1683,7 @@ bool Genesis::InstallNatives() { InstallNativeFunctions(); // Store the map for the string prototype after the natives has been compiled - // and the String function has been setup. + // and the String function has been set up. Handle<JSFunction> string_function(global_context()->string_function()); ASSERT(JSObject::cast( string_function->initial_map()->prototype())->HasFastProperties()); @@ -1911,25 +1920,28 @@ bool Bootstrapper::InstallExtensions(Handle<Context> global_context, void Genesis::InstallSpecialObjects(Handle<Context> global_context) { - Factory* factory = global_context->GetIsolate()->factory(); + Isolate* isolate = global_context->GetIsolate(); + Factory* factory = isolate->factory(); HandleScope scope; - Handle<JSGlobalObject> js_global( - JSGlobalObject::cast(global_context->global())); + Handle<JSGlobalObject> global(JSGlobalObject::cast(global_context->global())); // Expose the natives in global if a name for it is specified. if (FLAG_expose_natives_as != NULL && strlen(FLAG_expose_natives_as) != 0) { - Handle<String> natives_string = - factory->LookupAsciiSymbol(FLAG_expose_natives_as); - SetLocalPropertyNoThrow(js_global, natives_string, - Handle<JSObject>(js_global->builtins()), DONT_ENUM); + Handle<String> natives = factory->LookupAsciiSymbol(FLAG_expose_natives_as); + CHECK_NOT_EMPTY_HANDLE(isolate, + JSObject::SetLocalPropertyIgnoreAttributes( + global, natives, + Handle<JSObject>(global->builtins()), + DONT_ENUM)); } - Handle<Object> Error = GetProperty(js_global, "Error"); + Handle<Object> Error = GetProperty(global, "Error"); if (Error->IsJSObject()) { Handle<String> name = factory->LookupAsciiSymbol("stackTraceLimit"); - SetLocalPropertyNoThrow(Handle<JSObject>::cast(Error), - name, - Handle<Smi>(Smi::FromInt(FLAG_stack_trace_limit)), - NONE); + Handle<Smi> stack_trace_limit(Smi::FromInt(FLAG_stack_trace_limit)); + CHECK_NOT_EMPTY_HANDLE(isolate, + JSObject::SetLocalPropertyIgnoreAttributes( + Handle<JSObject>::cast(Error), name, + stack_trace_limit, NONE)); } #ifdef ENABLE_DEBUGGER_SUPPORT @@ -1948,7 +1960,9 @@ void Genesis::InstallSpecialObjects(Handle<Context> global_context) { Handle<String> debug_string = factory->LookupAsciiSymbol(FLAG_expose_debug_as); Handle<Object> global_proxy(debug->debug_context()->global_proxy()); - SetLocalPropertyNoThrow(js_global, debug_string, global_proxy, DONT_ENUM); + CHECK_NOT_EMPTY_HANDLE(isolate, + JSObject::SetLocalPropertyIgnoreAttributes( + global, debug_string, global_proxy, DONT_ENUM)); } #endif } @@ -2164,7 +2178,9 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from, Handle<String> key = Handle<String>(descs->GetKey(i)); int index = descs->GetFieldIndex(i); Handle<Object> value = Handle<Object>(from->FastPropertyAt(index)); - SetLocalPropertyNoThrow(to, key, value, details.attributes()); + CHECK_NOT_EMPTY_HANDLE(to->GetIsolate(), + JSObject::SetLocalPropertyIgnoreAttributes( + to, key, value, details.attributes())); break; } case CONSTANT_FUNCTION: { @@ -2172,7 +2188,9 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from, Handle<String> key = Handle<String>(descs->GetKey(i)); Handle<JSFunction> fun = Handle<JSFunction>(descs->GetConstantFunction(i)); - SetLocalPropertyNoThrow(to, key, fun, details.attributes()); + CHECK_NOT_EMPTY_HANDLE(to->GetIsolate(), + JSObject::SetLocalPropertyIgnoreAttributes( + to, key, fun, details.attributes())); break; } case CALLBACKS: { @@ -2187,7 +2205,7 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from, Handle<Object> callbacks(descs->GetCallbacksObject(i)); PropertyDetails d = PropertyDetails(details.attributes(), CALLBACKS, details.index()); - SetNormalizedProperty(to, key, callbacks, d); + JSObject::SetNormalizedProperty(to, key, callbacks, d); break; } case MAP_TRANSITION: @@ -2224,7 +2242,9 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from, value = Handle<Object>(JSGlobalPropertyCell::cast(*value)->value()); } PropertyDetails details = properties->DetailsAt(i); - SetLocalPropertyNoThrow(to, key, value, details.attributes()); + CHECK_NOT_EMPTY_HANDLE(to->GetIsolate(), + JSObject::SetLocalPropertyIgnoreAttributes( + to, key, value, details.attributes())); } } } diff --git a/deps/v8/src/bootstrapper.h b/deps/v8/src/bootstrapper.h index abf61b9fe58..101c2e1b1fd 100644 --- a/deps/v8/src/bootstrapper.h +++ b/deps/v8/src/bootstrapper.h @@ -88,7 +88,7 @@ class SourceCodeCache BASE_EMBEDDED { // context. class Bootstrapper { public: - // Requires: Heap::Setup has been called. + // Requires: Heap::SetUp has been called. void Initialize(bool create_heap_objects); void TearDown(); diff --git a/deps/v8/src/builtins.cc b/deps/v8/src/builtins.cc index 916799499f4..69e5161ce51 100644 --- a/deps/v8/src/builtins.cc +++ b/deps/v8/src/builtins.cc @@ -1719,7 +1719,7 @@ void Builtins::InitBuiltinFunctionTable() { #undef DEF_FUNCTION_PTR_A } -void Builtins::Setup(bool create_heap_objects) { +void Builtins::SetUp(bool create_heap_objects) { ASSERT(!initialized_); Isolate* isolate = Isolate::Current(); Heap* heap = isolate->heap(); diff --git a/deps/v8/src/builtins.h b/deps/v8/src/builtins.h index 6a84f2ddd19..f20d97df5bc 100644 --- a/deps/v8/src/builtins.h +++ b/deps/v8/src/builtins.h @@ -265,7 +265,7 @@ class Builtins { // Generate all builtin code objects. Should be called once during // isolate initialization. - void Setup(bool create_heap_objects); + void SetUp(bool create_heap_objects); void TearDown(); // Garbage collection support. diff --git a/deps/v8/src/code-stubs.cc b/deps/v8/src/code-stubs.cc index 85410c3cc8c..5fa9a2b5c02 100644 --- a/deps/v8/src/code-stubs.cc +++ b/deps/v8/src/code-stubs.cc @@ -40,7 +40,7 @@ namespace internal { bool CodeStub::FindCodeInCache(Code** code_out) { Heap* heap = Isolate::Current()->heap(); int index = heap->code_stubs()->FindEntry(GetKey()); - if (index != NumberDictionary::kNotFound) { + if (index != UnseededNumberDictionary::kNotFound) { *code_out = Code::cast(heap->code_stubs()->ValueAt(index)); return true; } @@ -132,9 +132,9 @@ Handle<Code> CodeStub::GetCode() { AddToSpecialCache(new_object); } else { // Update the dictionary and the root in Heap. - Handle<NumberDictionary> dict = + Handle<UnseededNumberDictionary> dict = factory->DictionaryAtNumberPut( - Handle<NumberDictionary>(heap->code_stubs()), + Handle<UnseededNumberDictionary>(heap->code_stubs()), GetKey(), new_object); heap->public_set_code_stubs(*dict); diff --git a/deps/v8/src/compiler.cc b/deps/v8/src/compiler.cc index d2a4a0bfdc4..362273e27ad 100644 --- a/deps/v8/src/compiler.cc +++ b/deps/v8/src/compiler.cc @@ -628,7 +628,7 @@ bool Compiler::CompileLazy(CompilationInfo* info) { // scope info. Please note, that the order of the shared function // info initialization is important since set_scope_info might // trigger a GC, causing the ASSERT below to be invalid if the code - // was flushed. By settting the code object last we avoid this. + // was flushed. By setting the code object last we avoid this. Handle<ScopeInfo> scope_info = ScopeInfo::Create(info->scope()); shared->set_scope_info(*scope_info); shared->set_code(*code); diff --git a/deps/v8/src/cpu-profiler.cc b/deps/v8/src/cpu-profiler.cc index d74c034ac53..2bd62ad3904 100644 --- a/deps/v8/src/cpu-profiler.cc +++ b/deps/v8/src/cpu-profiler.cc @@ -493,7 +493,7 @@ void CpuProfiler::StartProcessorIfNotStarted() { NoBarrier_Store(&is_profiling_, true); processor_->Start(); // Enumerate stuff we already have in the heap. - if (isolate->heap()->HasBeenSetup()) { + if (isolate->heap()->HasBeenSetUp()) { if (!FLAG_prof_browser_mode) { bool saved_log_code_flag = FLAG_log_code; FLAG_log_code = true; @@ -562,7 +562,7 @@ void CpuProfiler::StopProcessor() { } -void CpuProfiler::Setup() { +void CpuProfiler::SetUp() { Isolate* isolate = Isolate::Current(); if (isolate->cpu_profiler() == NULL) { isolate->set_cpu_profiler(new CpuProfiler()); diff --git a/deps/v8/src/cpu-profiler.h b/deps/v8/src/cpu-profiler.h index a71c0e0ab4e..3f4fec5f458 100644 --- a/deps/v8/src/cpu-profiler.h +++ b/deps/v8/src/cpu-profiler.h @@ -204,7 +204,7 @@ namespace internal { // TODO(isolates): isolatify this class. class CpuProfiler { public: - static void Setup(); + static void SetUp(); static void TearDown(); static void StartProfiling(const char* title); @@ -230,11 +230,11 @@ class CpuProfiler { Code* code, String* name); static void CodeCreateEvent(Logger::LogEventsAndTags tag, Code* code, - SharedFunctionInfo *shared, + SharedFunctionInfo* shared, String* name); static void CodeCreateEvent(Logger::LogEventsAndTags tag, Code* code, - SharedFunctionInfo *shared, + SharedFunctionInfo* shared, String* source, int line); static void CodeCreateEvent(Logger::LogEventsAndTags tag, Code* code, int args_count); diff --git a/deps/v8/src/cpu.h b/deps/v8/src/cpu.h index 2525484a016..247af71aa35 100644 --- a/deps/v8/src/cpu.h +++ b/deps/v8/src/cpu.h @@ -53,7 +53,7 @@ namespace internal { class CPU : public AllStatic { public: // Initializes the cpu architecture support. Called once at VM startup. - static void Setup(); + static void SetUp(); static bool SupportsCrankshaft(); diff --git a/deps/v8/src/d8-debug.cc b/deps/v8/src/d8-debug.cc index 8fbc876dabb..1cbc0b39a01 100644 --- a/deps/v8/src/d8-debug.cc +++ b/deps/v8/src/d8-debug.cc @@ -169,7 +169,7 @@ void RemoteDebugger::Run() { bool ok; // Make sure that socket support is initialized. - ok = i::Socket::Setup(); + ok = i::Socket::SetUp(); if (!ok) { printf("Unable to initialize socket support %d\n", i::Socket::LastError()); return; diff --git a/deps/v8/src/d8.cc b/deps/v8/src/d8.cc index ad850f5ee78..97828a4ac4c 100644 --- a/deps/v8/src/d8.cc +++ b/deps/v8/src/d8.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -281,63 +281,161 @@ Handle<Value> Shell::Load(const Arguments& args) { return Undefined(); } +static size_t convertToUint(Local<Value> value_in, TryCatch* try_catch) { + if (value_in->IsUint32()) { + return value_in->Uint32Value(); + } + + Local<Value> number = value_in->ToNumber(); + if (try_catch->HasCaught()) return 0; + + ASSERT(number->IsNumber()); + Local<Int32> int32 = number->ToInt32(); + if (try_catch->HasCaught() || int32.IsEmpty()) return 0; + + int32_t raw_value = int32->Int32Value(); + if (try_catch->HasCaught()) return 0; + + if (raw_value < 0) { + ThrowException(String::New("Array length must not be negative.")); + return 0; + } + + static const int kMaxLength = 0x3fffffff; +#ifndef V8_SHARED + ASSERT(kMaxLength == i::ExternalArray::kMaxLength); +#endif // V8_SHARED + if (raw_value > static_cast<int32_t>(kMaxLength)) { + ThrowException( + String::New("Array length exceeds maximum length.")); + } + return static_cast<size_t>(raw_value); +} + + +const char kArrayBufferReferencePropName[] = "_is_array_buffer_"; +const char kArrayBufferMarkerPropName[] = "_array_buffer_ref_"; + Handle<Value> Shell::CreateExternalArray(const Arguments& args, ExternalArrayType type, size_t element_size) { + TryCatch try_catch; + bool is_array_buffer_construct = element_size == 0; + if (is_array_buffer_construct) { + type = v8::kExternalByteArray; + element_size = 1; + } ASSERT(element_size == 1 || element_size == 2 || element_size == 4 || element_size == 8); - if (args.Length() != 1) { + if (args.Length() == 0) { return ThrowException( - String::New("Array constructor needs one parameter.")); + String::New("Array constructor must have at least one " + "parameter.")); } - static const int kMaxLength = 0x3fffffff; -#ifndef V8_SHARED - ASSERT(kMaxLength == i::ExternalArray::kMaxLength); -#endif // V8_SHARED - size_t length = 0; - TryCatch try_catch; - if (args[0]->IsUint32()) { - length = args[0]->Uint32Value(); - } else { - Local<Number> number = args[0]->ToNumber(); - if (number.IsEmpty()) { - ASSERT(try_catch.HasCaught()); - return try_catch.Exception(); + bool first_arg_is_array_buffer = + args[0]->IsObject() && + args[0]->ToObject()->Get( + String::New(kArrayBufferMarkerPropName))->IsTrue(); + // Currently, only the following constructors are supported: + // TypedArray(unsigned long length) + // TypedArray(ArrayBuffer buffer, + // optional unsigned long byteOffset, + // optional unsigned long length) + if (args.Length() > 3) { + return ThrowException( + String::New("Array constructor from ArrayBuffer must " + "have 1-3 parameters.")); + } + + Local<Value> length_value = (args.Length() < 3) + ? (first_arg_is_array_buffer + ? args[0]->ToObject()->Get(String::New("length")) + : args[0]) + : args[2]; + size_t length = convertToUint(length_value, &try_catch); + if (try_catch.HasCaught()) return try_catch.Exception(); + + void* data = NULL; + size_t offset = 0; + + Handle<Object> array = Object::New(); + if (first_arg_is_array_buffer) { + Handle<Object> derived_from = args[0]->ToObject(); + data = derived_from->GetIndexedPropertiesExternalArrayData(); + + size_t array_buffer_length = convertToUint( + derived_from->Get(String::New("length")), + &try_catch); + if (try_catch.HasCaught()) return try_catch.Exception(); + + if (data == NULL && array_buffer_length != 0) { + return ThrowException( + String::New("ArrayBuffer doesn't have data")); } - ASSERT(number->IsNumber()); - Local<Int32> int32 = number->ToInt32(); - if (int32.IsEmpty()) { - if (try_catch.HasCaught()) { - return try_catch.Exception(); + + if (args.Length() > 1) { + offset = convertToUint(args[1], &try_catch); + if (try_catch.HasCaught()) return try_catch.Exception(); + + // The given byteOffset must be a multiple of the element size of the + // specific type, otherwise an exception is raised. + if (offset % element_size != 0) { + return ThrowException( + String::New("offset must be multiple of element_size")); } } - int32_t raw_length = int32->Int32Value(); - if (try_catch.HasCaught()) { - return try_catch.Exception(); + + if (offset > array_buffer_length) { + return ThrowException( + String::New("byteOffset must be less than ArrayBuffer length.")); } - if (raw_length < 0) { - return ThrowException(String::New("Array length must not be negative.")); + + if (args.Length() == 2) { + // If length is not explicitly specified, the length of the ArrayBuffer + // minus the byteOffset must be a multiple of the element size of the + // specific type, or an exception is raised. + length = array_buffer_length - offset; + } + + if (args.Length() != 3) { + if (length % element_size != 0) { + return ThrowException( + String::New("ArrayBuffer length minus the byteOffset must be a " + "multiple of the element size")); + } + length /= element_size; } - if (raw_length > static_cast<int32_t>(kMaxLength)) { + + // If a given byteOffset and length references an area beyond the end of + // the ArrayBuffer an exception is raised. + if (offset + (length * element_size) > array_buffer_length) { return ThrowException( - String::New("Array length exceeds maximum length.")); + String::New("length references an area beyond the end of the " + "ArrayBuffer")); } - length = static_cast<size_t>(raw_length); - } - if (length > static_cast<size_t>(kMaxLength)) { - return ThrowException(String::New("Array length exceeds maximum length.")); + + // Hold a reference to the ArrayBuffer so its buffer doesn't get collected. + array->Set(String::New(kArrayBufferReferencePropName), args[0], ReadOnly); } - void* data = calloc(length, element_size); - if (data == NULL) { - return ThrowException(String::New("Memory allocation failed.")); + + if (is_array_buffer_construct) { + array->Set(String::New(kArrayBufferMarkerPropName), True(), ReadOnly); } - Handle<Object> array = Object::New(); + Persistent<Object> persistent_array = Persistent<Object>::New(array); persistent_array.MakeWeak(data, ExternalArrayWeakCallback); persistent_array.MarkIndependent(); - array->SetIndexedPropertiesToExternalArrayData(data, type, - static_cast<int>(length)); + if (data == NULL && length != 0) { + data = calloc(length, element_size); + if (data == NULL) { + return ThrowException(String::New("Memory allocation failed.")); + } + } + + array->SetIndexedPropertiesToExternalArrayData( + reinterpret_cast<uint8_t*>(data) + offset, type, + static_cast<int>(length)); array->Set(String::New("length"), Int32::New(static_cast<int32_t>(length)), ReadOnly); array->Set(String::New("BYTES_PER_ELEMENT"), @@ -347,11 +445,22 @@ Handle<Value> Shell::CreateExternalArray(const Arguments& args, void Shell::ExternalArrayWeakCallback(Persistent<Value> object, void* data) { - free(data); + HandleScope scope; + Handle<String> prop_name = String::New(kArrayBufferReferencePropName); + Handle<Object> converted_object = object->ToObject(); + Local<Value> prop_value = converted_object->Get(prop_name); + if (data != NULL && !prop_value->IsObject()) { + free(data); + } object.Dispose(); } +Handle<Value> Shell::ArrayBuffer(const Arguments& args) { + return CreateExternalArray(args, v8::kExternalByteArray, 0); +} + + Handle<Value> Shell::Int8Array(const Arguments& args) { return CreateExternalArray(args, v8::kExternalByteArray, sizeof(int8_t)); } @@ -693,6 +802,8 @@ Handle<ObjectTemplate> Shell::CreateGlobalTemplate() { FunctionTemplate::New(DisableProfiler)); // Bind the handlers for external arrays. + global_template->Set(String::New("ArrayBuffer"), + FunctionTemplate::New(ArrayBuffer)); global_template->Set(String::New("Int8Array"), FunctionTemplate::New(Int8Array)); global_template->Set(String::New("Uint8Array"), diff --git a/deps/v8/src/d8.h b/deps/v8/src/d8.h index 15d8d5d50fc..6c7733ccfaf 100644 --- a/deps/v8/src/d8.h +++ b/deps/v8/src/d8.h @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -289,6 +289,7 @@ class Shell : public i::AllStatic { static Handle<Value> Read(const Arguments& args); static Handle<Value> ReadLine(const Arguments& args); static Handle<Value> Load(const Arguments& args); + static Handle<Value> ArrayBuffer(const Arguments& args); static Handle<Value> Int8Array(const Arguments& args); static Handle<Value> Uint8Array(const Arguments& args); static Handle<Value> Int16Array(const Arguments& args); diff --git a/deps/v8/src/debug-debugger.js b/deps/v8/src/debug-debugger.js index 8cbe0b362cf..120a2970079 100644 --- a/deps/v8/src/debug-debugger.js +++ b/deps/v8/src/debug-debugger.js @@ -1547,7 +1547,7 @@ DebugCommandProcessor.prototype.continueRequest_ = function(request, response) { } } - // Setup the VM for stepping. + // Set up the VM for stepping. this.exec_state_.prepareStep(action, count); } diff --git a/deps/v8/src/debug.cc b/deps/v8/src/debug.cc index 24e17823d82..ffba7821cac 100644 --- a/deps/v8/src/debug.cc +++ b/deps/v8/src/debug.cc @@ -682,7 +682,7 @@ void ScriptCache::HandleWeakScript(v8::Persistent<v8::Value> obj, void* data) { } -void Debug::Setup(bool create_heap_objects) { +void Debug::SetUp(bool create_heap_objects) { ThreadInit(); if (create_heap_objects) { // Get code to handle debug break on return. @@ -827,8 +827,8 @@ bool Debug::Load() { Handle<GlobalObject> global = Handle<GlobalObject>(context->global()); RETURN_IF_EMPTY_HANDLE_VALUE( isolate_, - SetProperty(global, key, Handle<Object>(global->builtins()), - NONE, kNonStrictMode), + JSReceiver::SetProperty(global, key, Handle<Object>(global->builtins()), + NONE, kNonStrictMode), false); // Compile the JavaScript for the debugger in the debugger context. @@ -1213,7 +1213,7 @@ void Debug::ClearAllBreakPoints() { void Debug::FloodWithOneShot(Handle<SharedFunctionInfo> shared) { PrepareForBreakPoints(); - // Make sure the function has setup the debug info. + // Make sure the function has set up the debug info. if (!EnsureDebugInfo(shared)) { // Return if we failed to retrieve the debug info. return; @@ -2855,7 +2855,7 @@ void Debugger::NotifyMessageHandler(v8::DebugEvent event, command.Dispose(); // Return from debug event processing if either the VM is put into the - // runnning state (through a continue command) or auto continue is active + // running state (through a continue command) or auto continue is active // and there are no more commands queued. if (running && !HasCommands()) { return; @@ -3065,7 +3065,7 @@ bool Debugger::StartAgent(const char* name, int port, v8::Debug::DebugBreak(); } - if (Socket::Setup()) { + if (Socket::SetUp()) { if (agent_ == NULL) { agent_ = new DebuggerAgent(name, port); agent_->Start(); diff --git a/deps/v8/src/debug.h b/deps/v8/src/debug.h index a39d8013e47..582aadae8d4 100644 --- a/deps/v8/src/debug.h +++ b/deps/v8/src/debug.h @@ -178,7 +178,9 @@ class ScriptCache : private HashMap { private: // Calculate the hash value from the key (script id). - static uint32_t Hash(int key) { return ComputeIntegerHash(key); } + static uint32_t Hash(int key) { + return ComputeIntegerHash(key, v8::internal::kZeroHashSeed); + } // Scripts match if their keys (script id) match. static bool ScriptMatch(void* key1, void* key2) { return key1 == key2; } @@ -222,7 +224,7 @@ class DebugInfoListNode { // DebugInfo. class Debug { public: - void Setup(bool create_heap_objects); + void SetUp(bool create_heap_objects); bool Load(); void Unload(); bool IsLoaded() { return !debug_context_.is_null(); } diff --git a/deps/v8/src/elements.cc b/deps/v8/src/elements.cc index fd2b6d248a3..e54ec626912 100644 --- a/deps/v8/src/elements.cc +++ b/deps/v8/src/elements.cc @@ -549,11 +549,11 @@ class PixelElementsAccessor class DictionaryElementsAccessor : public ElementsAccessorBase<DictionaryElementsAccessor, - NumberDictionary> { + SeededNumberDictionary> { public: // Adjusts the length of the dictionary backing store and returns the new // length according to ES5 section 15.4.5.2 behavior. - static MaybeObject* SetLengthWithoutNormalize(NumberDictionary* dict, + static MaybeObject* SetLengthWithoutNormalize(SeededNumberDictionary* dict, JSArray* array, Object* length_object, uint32_t length) { @@ -619,9 +619,10 @@ class DictionaryElementsAccessor if (is_arguments) { backing_store = FixedArray::cast(backing_store->get(1)); } - NumberDictionary* dictionary = NumberDictionary::cast(backing_store); + SeededNumberDictionary* dictionary = + SeededNumberDictionary::cast(backing_store); int entry = dictionary->FindEntry(key); - if (entry != NumberDictionary::kNotFound) { + if (entry != SeededNumberDictionary::kNotFound) { Object* result = dictionary->DeleteProperty(entry, mode); if (result == heap->true_value()) { MaybeObject* maybe_elements = dictionary->Shrink(key); @@ -654,7 +655,7 @@ class DictionaryElementsAccessor protected: friend class ElementsAccessorBase<DictionaryElementsAccessor, - NumberDictionary>; + SeededNumberDictionary>; virtual MaybeObject* Delete(JSObject* obj, uint32_t key, @@ -662,12 +663,12 @@ class DictionaryElementsAccessor return DeleteCommon(obj, key, mode); } - static MaybeObject* Get(NumberDictionary* backing_store, + static MaybeObject* Get(SeededNumberDictionary* backing_store, uint32_t key, JSObject* obj, Object* receiver) { int entry = backing_store->FindEntry(key); - if (entry != NumberDictionary::kNotFound) { + if (entry != SeededNumberDictionary::kNotFound) { Object* element = backing_store->ValueAt(entry); PropertyDetails details = backing_store->DetailsAt(entry); if (details.type() == CALLBACKS) { @@ -682,7 +683,7 @@ class DictionaryElementsAccessor return obj->GetHeap()->the_hole_value(); } - static uint32_t GetKeyForIndex(NumberDictionary* dict, + static uint32_t GetKeyForIndex(SeededNumberDictionary* dict, uint32_t index) { Object* key = dict->KeyAt(index); return Smi::cast(key)->value(); @@ -895,7 +896,7 @@ MaybeObject* ElementsAccessorBase<ElementsAccessorSubclass, BackingStoreClass>:: if (length->IsNumber()) { uint32_t value; if (length->ToArrayIndex(&value)) { - NumberDictionary* dictionary; + SeededNumberDictionary* dictionary; MaybeObject* maybe_object = array->NormalizeElements(); if (!maybe_object->To(&dictionary)) return maybe_object; Object* new_length; diff --git a/deps/v8/src/execution.cc b/deps/v8/src/execution.cc index b16e7396ad4..125241ceec9 100644 --- a/deps/v8/src/execution.cc +++ b/deps/v8/src/execution.cc @@ -845,13 +845,13 @@ Object* Execution::DebugBreakHelper() { // Clear the debug break request flag. isolate->stack_guard()->Continue(DEBUGBREAK); - ProcessDebugMesssages(debug_command_only); + ProcessDebugMessages(debug_command_only); // Return to continue execution. return isolate->heap()->undefined_value(); } -void Execution::ProcessDebugMesssages(bool debug_command_only) { +void Execution::ProcessDebugMessages(bool debug_command_only) { Isolate* isolate = Isolate::Current(); // Clear the debug command request flag. isolate->stack_guard()->Continue(DEBUGCOMMAND); diff --git a/deps/v8/src/execution.h b/deps/v8/src/execution.h index f2d17d0792b..014736ee882 100644 --- a/deps/v8/src/execution.h +++ b/deps/v8/src/execution.h @@ -136,7 +136,7 @@ class Execution : public AllStatic { Handle<Object> is_global); #ifdef ENABLE_DEBUGGER_SUPPORT static Object* DebugBreakHelper(); - static void ProcessDebugMesssages(bool debug_command_only); + static void ProcessDebugMessages(bool debug_command_only); #endif // If the stack guard is triggered, but it is not an actual diff --git a/deps/v8/src/factory.cc b/deps/v8/src/factory.cc index c2976a577a1..0b796350d44 100644 --- a/deps/v8/src/factory.cc +++ b/deps/v8/src/factory.cc @@ -77,11 +77,21 @@ Handle<StringDictionary> Factory::NewStringDictionary(int at_least_space_for) { } -Handle<NumberDictionary> Factory::NewNumberDictionary(int at_least_space_for) { +Handle<SeededNumberDictionary> Factory::NewSeededNumberDictionary( + int at_least_space_for) { ASSERT(0 <= at_least_space_for); CALL_HEAP_FUNCTION(isolate(), - NumberDictionary::Allocate(at_least_space_for), - NumberDictionary); + SeededNumberDictionary::Allocate(at_least_space_for), + SeededNumberDictionary); +} + + +Handle<UnseededNumberDictionary> Factory::NewUnseededNumberDictionary( + int at_least_space_for) { + ASSERT(0 <= at_least_space_for); + CALL_HEAP_FUNCTION(isolate(), + UnseededNumberDictionary::Allocate(at_least_space_for), + UnseededNumberDictionary); } @@ -131,6 +141,13 @@ Handle<DeoptimizationOutputData> Factory::NewDeoptimizationOutputData( } +Handle<AccessorPair> Factory::NewAccessorPair() { + CALL_HEAP_FUNCTION(isolate(), + isolate()->heap()->AllocateAccessorPair(), + AccessorPair); +} + + // Symbols are created in the old generation (data space). Handle<String> Factory::LookupSymbol(Vector<const char> string) { CALL_HEAP_FUNCTION(isolate(), @@ -698,7 +715,7 @@ Handle<JSFunction> Factory::NewFunction(Handle<String> name, // Allocate the function Handle<JSFunction> function = NewFunction(name, the_hole_value()); - // Setup the code pointer in both the shared function info and in + // Set up the code pointer in both the shared function info and in // the function itself. function->shared()->set_code(*code); function->set_code(*code); @@ -729,7 +746,7 @@ Handle<JSFunction> Factory::NewFunctionWithPrototype(Handle<String> name, // Allocate the function. Handle<JSFunction> function = NewFunction(name, prototype); - // Setup the code pointer in both the shared function info and in + // Set up the code pointer in both the shared function info and in // the function itself. function->shared()->set_code(*code); function->set_code(*code); @@ -751,7 +768,10 @@ Handle<JSFunction> Factory::NewFunctionWithPrototype(Handle<String> name, // property that refers to the function. SetPrototypeProperty(function, prototype); // Currently safe because it is only invoked from Genesis. - SetLocalPropertyNoThrow(prototype, constructor_symbol(), function, DONT_ENUM); + CHECK_NOT_EMPTY_HANDLE(isolate(), + JSObject::SetLocalPropertyIgnoreAttributes( + prototype, constructor_symbol(), + function, DONT_ENUM)); return function; } @@ -1061,13 +1081,23 @@ Handle<String> Factory::Uint32ToString(uint32_t value) { } -Handle<NumberDictionary> Factory::DictionaryAtNumberPut( - Handle<NumberDictionary> dictionary, +Handle<SeededNumberDictionary> Factory::DictionaryAtNumberPut( + Handle<SeededNumberDictionary> dictionary, + uint32_t key, + Handle<Object> value) { + CALL_HEAP_FUNCTION(isolate(), + dictionary->AtNumberPut(key, *value), + SeededNumberDictionary); +} + + +Handle<UnseededNumberDictionary> Factory::DictionaryAtNumberPut( + Handle<UnseededNumberDictionary> dictionary, uint32_t key, Handle<Object> value) { CALL_HEAP_FUNCTION(isolate(), dictionary->AtNumberPut(key, *value), - NumberDictionary); + UnseededNumberDictionary); } diff --git a/deps/v8/src/factory.h b/deps/v8/src/factory.h index e9a43fd4fc7..8725b67ec9b 100644 --- a/deps/v8/src/factory.h +++ b/deps/v8/src/factory.h @@ -54,7 +54,11 @@ class Factory { int size, PretenureFlag pretenure = NOT_TENURED); - Handle<NumberDictionary> NewNumberDictionary(int at_least_space_for); + Handle<SeededNumberDictionary> NewSeededNumberDictionary( + int at_least_space_for); + + Handle<UnseededNumberDictionary> NewUnseededNumberDictionary( + int at_least_space_for); Handle<StringDictionary> NewStringDictionary(int at_least_space_for); @@ -69,6 +73,8 @@ class Factory { Handle<DeoptimizationOutputData> NewDeoptimizationOutputData( int deopt_entry_count, PretenureFlag pretenure); + // Allocates a pre-tenured empty AccessorPair. + Handle<AccessorPair> NewAccessorPair(); Handle<String> LookupSymbol(Vector<const char> str); Handle<String> LookupSymbol(Handle<String> str); @@ -430,8 +436,13 @@ class Factory { Handle<Object> stack_trace, Handle<Object> stack_frames); - Handle<NumberDictionary> DictionaryAtNumberPut( - Handle<NumberDictionary>, + Handle<SeededNumberDictionary> DictionaryAtNumberPut( + Handle<SeededNumberDictionary>, + uint32_t key, + Handle<Object> value); + + Handle<UnseededNumberDictionary> DictionaryAtNumberPut( + Handle<UnseededNumberDictionary>, uint32_t key, Handle<Object> value); diff --git a/deps/v8/src/flag-definitions.h b/deps/v8/src/flag-definitions.h index 07060dcb038..9284e1369fe 100644 --- a/deps/v8/src/flag-definitions.h +++ b/deps/v8/src/flag-definitions.h @@ -349,13 +349,13 @@ DEFINE_bool(trace_exception, false, "print stack trace when throwing exceptions") DEFINE_bool(preallocate_message_memory, false, "preallocate some memory to build stack traces.") -DEFINE_bool(randomize_string_hashes, +DEFINE_bool(randomize_hashes, true, - "randomize string hashes to avoid predictable hash collisions " + "randomize hashes to avoid predictable hash collisions " "(with snapshots this option cannot override the baked-in seed)") -DEFINE_int(string_hash_seed, +DEFINE_int(hash_seed, 0, - "Fixed seed to use to string hashing (0 means random)" + "Fixed seed to use to hash property keys (0 means random)" "(with snapshots this option cannot override the baked-in seed)") // v8.cc diff --git a/deps/v8/src/frames.cc b/deps/v8/src/frames.cc index e3ed2de4e36..3a46e0869f4 100644 --- a/deps/v8/src/frames.cc +++ b/deps/v8/src/frames.cc @@ -485,7 +485,7 @@ Code* ExitFrame::unchecked_code() const { void ExitFrame::ComputeCallerState(State* state) const { - // Setup the caller state. + // Set up the caller state. state->sp = caller_sp(); state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset); state->pc_address @@ -1303,7 +1303,8 @@ InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* isolate_->counters()->pc_to_code()->Increment(); ASSERT(IsPowerOf2(kInnerPointerToCodeCacheSize)); uint32_t hash = ComputeIntegerHash( - static_cast<uint32_t>(reinterpret_cast<uintptr_t>(inner_pointer))); + static_cast<uint32_t>(reinterpret_cast<uintptr_t>(inner_pointer)), + v8::internal::kZeroHashSeed); uint32_t index = hash & (kInnerPointerToCodeCacheSize - 1); InnerPointerToCodeCacheEntry* entry = cache(index); if (entry->inner_pointer == inner_pointer) { diff --git a/deps/v8/src/full-codegen.cc b/deps/v8/src/full-codegen.cc index 04086d483d9..5c7a23d54de 100644 --- a/deps/v8/src/full-codegen.cc +++ b/deps/v8/src/full-codegen.cc @@ -1178,7 +1178,7 @@ void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { } ExitFinallyBlock(); // Return to the calling code. - // Setup try handler. + // Set up try handler. __ bind(&try_entry); __ PushTryHandler(IN_JAVASCRIPT, TRY_FINALLY_HANDLER, stmt->index()); { TryFinally try_body(this, &finally_entry); @@ -1284,7 +1284,7 @@ FullCodeGenerator::NestedStatement* FullCodeGenerator::TryCatch::Exit( bool FullCodeGenerator::TryLiteralCompare(CompareOperation* expr) { - Expression *sub_expr; + Expression* sub_expr; Handle<String> check; if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { EmitLiteralCompareTypeof(expr, sub_expr, check); diff --git a/deps/v8/src/gdb-jit.cc b/deps/v8/src/gdb-jit.cc index b386bed177a..4192222f90e 100644 --- a/deps/v8/src/gdb-jit.cc +++ b/deps/v8/src/gdb-jit.cc @@ -1556,23 +1556,23 @@ class DebugLineSection : public DebugSection { class UnwindInfoSection : public DebugSection { public: - explicit UnwindInfoSection(CodeDescription *desc); - virtual bool WriteBody(Writer *w); + explicit UnwindInfoSection(CodeDescription* desc); + virtual bool WriteBody(Writer* w); - int WriteCIE(Writer *w); - void WriteFDE(Writer *w, int); + int WriteCIE(Writer* w); + void WriteFDE(Writer* w, int); - void WriteFDEStateOnEntry(Writer *w); - void WriteFDEStateAfterRBPPush(Writer *w); - void WriteFDEStateAfterRBPSet(Writer *w); - void WriteFDEStateAfterRBPPop(Writer *w); + void WriteFDEStateOnEntry(Writer* w); + void WriteFDEStateAfterRBPPush(Writer* w); + void WriteFDEStateAfterRBPSet(Writer* w); + void WriteFDEStateAfterRBPPop(Writer* w); - void WriteLength(Writer *w, + void WriteLength(Writer* w, Writer::Slot<uint32_t>* length_slot, int initial_position); private: - CodeDescription *desc_; + CodeDescription* desc_; // DWARF3 Specification, Table 7.23 enum CFIInstructions { @@ -1623,7 +1623,7 @@ class UnwindInfoSection : public DebugSection { }; -void UnwindInfoSection::WriteLength(Writer *w, +void UnwindInfoSection::WriteLength(Writer* w, Writer::Slot<uint32_t>* length_slot, int initial_position) { uint32_t align = (w->position() - initial_position) % kPointerSize; @@ -1639,7 +1639,7 @@ void UnwindInfoSection::WriteLength(Writer *w, } -UnwindInfoSection::UnwindInfoSection(CodeDescription *desc) +UnwindInfoSection::UnwindInfoSection(CodeDescription* desc) #ifdef __ELF : ELFSection(".eh_frame", TYPE_X86_64_UNWIND, 1), #else @@ -1648,7 +1648,7 @@ UnwindInfoSection::UnwindInfoSection(CodeDescription *desc) #endif desc_(desc) { } -int UnwindInfoSection::WriteCIE(Writer *w) { +int UnwindInfoSection::WriteCIE(Writer* w) { Writer::Slot<uint32_t> cie_length_slot = w->CreateSlotHere<uint32_t>(); uint32_t cie_position = w->position(); @@ -1668,7 +1668,7 @@ int UnwindInfoSection::WriteCIE(Writer *w) { } -void UnwindInfoSection::WriteFDE(Writer *w, int cie_position) { +void UnwindInfoSection::WriteFDE(Writer* w, int cie_position) { // The only FDE for this function. The CFA is the current RBP. Writer::Slot<uint32_t> fde_length_slot = w->CreateSlotHere<uint32_t>(); int fde_position = w->position(); @@ -1686,7 +1686,7 @@ void UnwindInfoSection::WriteFDE(Writer *w, int cie_position) { } -void UnwindInfoSection::WriteFDEStateOnEntry(Writer *w) { +void UnwindInfoSection::WriteFDEStateOnEntry(Writer* w) { // The first state, just after the control has been transferred to the the // function. @@ -1713,7 +1713,7 @@ void UnwindInfoSection::WriteFDEStateOnEntry(Writer *w) { } -void UnwindInfoSection::WriteFDEStateAfterRBPPush(Writer *w) { +void UnwindInfoSection::WriteFDEStateAfterRBPPush(Writer* w) { // The second state, just after RBP has been pushed. // RBP / CFA for this function is now the current RSP, so just set the @@ -1734,7 +1734,7 @@ void UnwindInfoSection::WriteFDEStateAfterRBPPush(Writer *w) { } -void UnwindInfoSection::WriteFDEStateAfterRBPSet(Writer *w) { +void UnwindInfoSection::WriteFDEStateAfterRBPSet(Writer* w) { // The third state, after the RBP has been set. // The CFA can now directly be set to RBP. @@ -1749,7 +1749,7 @@ void UnwindInfoSection::WriteFDEStateAfterRBPSet(Writer *w) { } -void UnwindInfoSection::WriteFDEStateAfterRBPPop(Writer *w) { +void UnwindInfoSection::WriteFDEStateAfterRBPPop(Writer* w) { // The fourth (final) state. The RBP has been popped (just before issuing a // return). @@ -1769,7 +1769,7 @@ void UnwindInfoSection::WriteFDEStateAfterRBPPop(Writer *w) { } -bool UnwindInfoSection::WriteBody(Writer *w) { +bool UnwindInfoSection::WriteBody(Writer* w) { uint32_t cie_position = WriteCIE(w); WriteFDE(w, cie_position); return true; @@ -1810,8 +1810,8 @@ extern "C" { struct JITDescriptor { uint32_t version_; uint32_t action_flag_; - JITCodeEntry *relevant_entry_; - JITCodeEntry *first_entry_; + JITCodeEntry* relevant_entry_; + JITCodeEntry* first_entry_; }; // GDB will place breakpoint into this function. @@ -1998,7 +1998,7 @@ void GDBJITInterface::AddCode(Handle<String> name, } } -static void AddUnwindInfo(CodeDescription *desc) { +static void AddUnwindInfo(CodeDescription* desc) { #ifdef V8_TARGET_ARCH_X64 if (desc->tag() == GDBJITInterface::FUNCTION) { // To avoid propagating unwinding information through diff --git a/deps/v8/src/handles.cc b/deps/v8/src/handles.cc index 2ff797d0773..34eaddbbd71 100644 --- a/deps/v8/src/handles.cc +++ b/deps/v8/src/handles.cc @@ -208,42 +208,6 @@ void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared, } -void NormalizeProperties(Handle<JSObject> object, - PropertyNormalizationMode mode, - int expected_additional_properties) { - CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), - object->NormalizeProperties( - mode, - expected_additional_properties)); -} - - -Handle<NumberDictionary> NormalizeElements(Handle<JSObject> object) { - CALL_HEAP_FUNCTION(object->GetIsolate(), - object->NormalizeElements(), - NumberDictionary); -} - - -void TransformToFastProperties(Handle<JSObject> object, - int unused_property_fields) { - CALL_HEAP_FUNCTION_VOID( - object->GetIsolate(), - object->TransformToFastProperties(unused_property_fields)); -} - - -Handle<NumberDictionary> NumberDictionarySet( - Handle<NumberDictionary> dictionary, - uint32_t index, - Handle<Object> value, - PropertyDetails details) { - CALL_HEAP_FUNCTION(dictionary->GetIsolate(), - dictionary->Set(index, *value, details), - NumberDictionary); -} - - void FlattenString(Handle<String> string) { CALL_HEAP_FUNCTION_VOID(string->GetIsolate(), string->TryFlatten()); } @@ -265,17 +229,6 @@ Handle<Object> SetPrototype(Handle<JSFunction> function, } -Handle<Object> SetProperty(Handle<JSReceiver> object, - Handle<String> key, - Handle<Object> value, - PropertyAttributes attributes, - StrictModeFlag strict_mode) { - CALL_HEAP_FUNCTION(object->GetIsolate(), - object->SetProperty(*key, *value, attributes, strict_mode), - Object); -} - - Handle<Object> SetProperty(Handle<Object> object, Handle<Object> key, Handle<Object> value, @@ -303,16 +256,6 @@ Handle<Object> ForceSetProperty(Handle<JSObject> object, } -Handle<Object> SetNormalizedProperty(Handle<JSObject> object, - Handle<String> key, - Handle<Object> value, - PropertyDetails details) { - CALL_HEAP_FUNCTION(object->GetIsolate(), - object->SetNormalizedProperty(*key, *value, details), - Object); -} - - Handle<Object> ForceDeleteProperty(Handle<JSObject> object, Handle<Object> key) { Isolate* isolate = object->GetIsolate(); @@ -322,30 +265,6 @@ Handle<Object> ForceDeleteProperty(Handle<JSObject> object, } -Handle<Object> SetLocalPropertyIgnoreAttributes( - Handle<JSObject> object, - Handle<String> key, - Handle<Object> value, - PropertyAttributes attributes) { - CALL_HEAP_FUNCTION( - object->GetIsolate(), - object->SetLocalPropertyIgnoreAttributes(*key, *value, attributes), - Object); -} - - -void SetLocalPropertyNoThrow(Handle<JSObject> object, - Handle<String> key, - Handle<Object> value, - PropertyAttributes attributes) { - Isolate* isolate = object->GetIsolate(); - ASSERT(!isolate->has_pending_exception()); - CHECK(!SetLocalPropertyIgnoreAttributes( - object, key, value, attributes).is_null()); - CHECK(!isolate->has_pending_exception()); -} - - Handle<Object> SetPropertyWithInterceptor(Handle<JSObject> object, Handle<String> key, Handle<Object> value, @@ -389,12 +308,6 @@ Handle<Object> GetPropertyWithInterceptor(Handle<JSObject> receiver, } -Handle<Object> GetPrototype(Handle<Object> obj) { - Handle<Object> result(obj->GetPrototype()); - return result; -} - - Handle<Object> SetPrototype(Handle<JSObject> obj, Handle<Object> value) { const bool skip_hidden_prototypes = false; CALL_HEAP_FUNCTION(obj->GetIsolate(), @@ -402,44 +315,6 @@ Handle<Object> SetPrototype(Handle<JSObject> obj, Handle<Object> value) { } -Handle<Object> PreventExtensions(Handle<JSObject> object) { - CALL_HEAP_FUNCTION(object->GetIsolate(), object->PreventExtensions(), Object); -} - - -Handle<Object> SetHiddenProperty(Handle<JSObject> obj, - Handle<String> key, - Handle<Object> value) { - CALL_HEAP_FUNCTION(obj->GetIsolate(), - obj->SetHiddenProperty(*key, *value), - Object); -} - - -int GetIdentityHash(Handle<JSReceiver> obj) { - CALL_AND_RETRY(obj->GetIsolate(), - obj->GetIdentityHash(ALLOW_CREATION), - return Smi::cast(__object__)->value(), - return 0); -} - - -Handle<Object> DeleteElement(Handle<JSObject> obj, - uint32_t index) { - CALL_HEAP_FUNCTION(obj->GetIsolate(), - obj->DeleteElement(index, JSObject::NORMAL_DELETION), - Object); -} - - -Handle<Object> DeleteProperty(Handle<JSObject> obj, - Handle<String> prop) { - CALL_HEAP_FUNCTION(obj->GetIsolate(), - obj->DeleteProperty(*prop, JSObject::NORMAL_DELETION), - Object); -} - - Handle<Object> LookupSingleCharacterStringFromCode(uint32_t index) { Isolate* isolate = Isolate::Current(); CALL_HEAP_FUNCTION( @@ -457,43 +332,6 @@ Handle<String> SubString(Handle<String> str, } -Handle<Object> SetElement(Handle<JSObject> object, - uint32_t index, - Handle<Object> value, - StrictModeFlag strict_mode) { - if (object->HasExternalArrayElements()) { - if (!value->IsSmi() && !value->IsHeapNumber() && !value->IsUndefined()) { - bool has_exception; - Handle<Object> number = Execution::ToNumber(value, &has_exception); - if (has_exception) return Handle<Object>(); - value = number; - } - } - CALL_HEAP_FUNCTION(object->GetIsolate(), - object->SetElement(index, *value, strict_mode, true), - Object); -} - - -Handle<Object> SetOwnElement(Handle<JSObject> object, - uint32_t index, - Handle<Object> value, - StrictModeFlag strict_mode) { - ASSERT(!object->HasExternalArrayElements()); - CALL_HEAP_FUNCTION(object->GetIsolate(), - object->SetElement(index, *value, strict_mode, false), - Object); -} - - -Handle<Object> TransitionElementsKind(Handle<JSObject> object, - ElementsKind to_kind) { - CALL_HEAP_FUNCTION(object->GetIsolate(), - object->TransitionElementsKind(to_kind), - Object); -} - - Handle<JSObject> Copy(Handle<JSObject> obj) { Isolate* isolate = obj->GetIsolate(); CALL_HEAP_FUNCTION(isolate, diff --git a/deps/v8/src/handles.h b/deps/v8/src/handles.h index cfa65b3786b..42089134e4b 100644 --- a/deps/v8/src/handles.h +++ b/deps/v8/src/handles.h @@ -167,18 +167,6 @@ class HandleScope { // an object of expected type, or the handle is an error if running out // of space or encountering an internal error. -void NormalizeProperties(Handle<JSObject> object, - PropertyNormalizationMode mode, - int expected_additional_properties); -Handle<NumberDictionary> NormalizeElements(Handle<JSObject> object); -void TransformToFastProperties(Handle<JSObject> object, - int unused_property_fields); -MUST_USE_RESULT Handle<NumberDictionary> NumberDictionarySet( - Handle<NumberDictionary> dictionary, - uint32_t index, - Handle<Object> value, - PropertyDetails details); - // Flattens a string. void FlattenString(Handle<String> str); @@ -186,12 +174,6 @@ void FlattenString(Handle<String> str); // string. Handle<String> FlattenGetString(Handle<String> str); -Handle<Object> SetProperty(Handle<JSReceiver> object, - Handle<String> key, - Handle<Object> value, - PropertyAttributes attributes, - StrictModeFlag strict_mode); - Handle<Object> SetProperty(Handle<Object> object, Handle<Object> key, Handle<Object> value, @@ -203,40 +185,9 @@ Handle<Object> ForceSetProperty(Handle<JSObject> object, Handle<Object> value, PropertyAttributes attributes); -Handle<Object> SetNormalizedProperty(Handle<JSObject> object, - Handle<String> key, - Handle<Object> value, - PropertyDetails details); - Handle<Object> ForceDeleteProperty(Handle<JSObject> object, Handle<Object> key); -Handle<Object> SetLocalPropertyIgnoreAttributes( - Handle<JSObject> object, - Handle<String> key, - Handle<Object> value, - PropertyAttributes attributes); - -// Used to set local properties on the object we totally control -// and which therefore has no accessors and alikes. -void SetLocalPropertyNoThrow(Handle<JSObject> object, - Handle<String> key, - Handle<Object> value, - PropertyAttributes attributes = NONE); - -MUST_USE_RESULT Handle<Object> SetElement(Handle<JSObject> object, - uint32_t index, - Handle<Object> value, - StrictModeFlag strict_mode); - -Handle<Object> SetOwnElement(Handle<JSObject> object, - uint32_t index, - Handle<Object> value, - StrictModeFlag strict_mode); - -Handle<Object> TransitionElementsKind(Handle<JSObject> object, - ElementsKind to_kind); - Handle<Object> GetProperty(Handle<JSReceiver> obj, const char* name); @@ -248,21 +199,8 @@ Handle<Object> GetPropertyWithInterceptor(Handle<JSObject> receiver, Handle<String> name, PropertyAttributes* attributes); -Handle<Object> GetPrototype(Handle<Object> obj); - Handle<Object> SetPrototype(Handle<JSObject> obj, Handle<Object> value); -// Sets a hidden property on an object. Returns obj on success, undefined -// if trying to set the property on a detached proxy. -Handle<Object> SetHiddenProperty(Handle<JSObject> obj, - Handle<String> key, - Handle<Object> value); - -int GetIdentityHash(Handle<JSReceiver> obj); - -Handle<Object> DeleteElement(Handle<JSObject> obj, uint32_t index); -Handle<Object> DeleteProperty(Handle<JSObject> obj, Handle<String> prop); - Handle<Object> LookupSingleCharacterStringFromCode(uint32_t index); Handle<JSObject> Copy(Handle<JSObject> obj); @@ -316,7 +254,6 @@ Handle<String> SubString(Handle<String> str, int end, PretenureFlag pretenure = NOT_TENURED); - // Sets the expected number of properties for the function's instances. void SetExpectedNofProperties(Handle<JSFunction> func, int nof); @@ -335,8 +272,6 @@ Handle<JSGlobalProxy> ReinitializeJSGlobalProxy( Handle<Object> SetPrototype(Handle<JSFunction> function, Handle<Object> prototype); -Handle<Object> PreventExtensions(Handle<JSObject> object); - Handle<ObjectHashSet> ObjectHashSetAdd(Handle<ObjectHashSet> table, Handle<Object> key); diff --git a/deps/v8/src/heap-inl.h b/deps/v8/src/heap-inl.h index ef6e58ed0b8..4d98fbad107 100644 --- a/deps/v8/src/heap-inl.h +++ b/deps/v8/src/heap-inl.h @@ -463,7 +463,7 @@ MaybeObject* Heap::PrepareForCompare(String* str) { int Heap::AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) { - ASSERT(HasBeenSetup()); + ASSERT(HasBeenSetUp()); int amount = amount_of_external_allocated_memory_ + change_in_bytes; if (change_in_bytes >= 0) { // Avoid overflow. diff --git a/deps/v8/src/heap-profiler.cc b/deps/v8/src/heap-profiler.cc index 46c63c27c87..8be6f27685e 100644 --- a/deps/v8/src/heap-profiler.cc +++ b/deps/v8/src/heap-profiler.cc @@ -51,7 +51,7 @@ void HeapProfiler::ResetSnapshots() { } -void HeapProfiler::Setup() { +void HeapProfiler::SetUp() { Isolate* isolate = Isolate::Current(); if (isolate->heap_profiler() == NULL) { isolate->set_heap_profiler(new HeapProfiler()); diff --git a/deps/v8/src/heap-profiler.h b/deps/v8/src/heap-profiler.h index b1bc91c307a..ef5c4f4b4a0 100644 --- a/deps/v8/src/heap-profiler.h +++ b/deps/v8/src/heap-profiler.h @@ -48,7 +48,7 @@ class HeapSnapshotsCollection; // to generate .hp files for use by the GHC/Valgrind tool hp2ps. class HeapProfiler { public: - static void Setup(); + static void SetUp(); static void TearDown(); static HeapSnapshot* TakeSnapshot(const char* name, diff --git a/deps/v8/src/heap.cc b/deps/v8/src/heap.cc index 31cd889cbef..3c871e27065 100644 --- a/deps/v8/src/heap.cc +++ b/deps/v8/src/heap.cc @@ -176,7 +176,7 @@ Heap::Heap() intptr_t Heap::Capacity() { - if (!HasBeenSetup()) return 0; + if (!HasBeenSetUp()) return 0; return new_space_.Capacity() + old_pointer_space_->Capacity() + @@ -188,7 +188,7 @@ intptr_t Heap::Capacity() { intptr_t Heap::CommittedMemory() { - if (!HasBeenSetup()) return 0; + if (!HasBeenSetUp()) return 0; return new_space_.CommittedMemory() + old_pointer_space_->CommittedMemory() + @@ -200,14 +200,14 @@ intptr_t Heap::CommittedMemory() { } intptr_t Heap::CommittedMemoryExecutable() { - if (!HasBeenSetup()) return 0; + if (!HasBeenSetUp()) return 0; return isolate()->memory_allocator()->SizeExecutable(); } intptr_t Heap::Available() { - if (!HasBeenSetup()) return 0; + if (!HasBeenSetUp()) return 0; return new_space_.Available() + old_pointer_space_->Available() + @@ -218,7 +218,7 @@ intptr_t Heap::Available() { } -bool Heap::HasBeenSetup() { +bool Heap::HasBeenSetUp() { return old_pointer_space_ != NULL && old_data_space_ != NULL && code_space_ != NULL && @@ -1354,6 +1354,28 @@ void Heap::ProcessWeakReferences(WeakObjectRetainer* retainer) { } +void Heap::VisitExternalResources(v8::ExternalResourceVisitor* visitor) { + AssertNoAllocation no_allocation; + + class VisitorAdapter : public ObjectVisitor { + public: + explicit VisitorAdapter(v8::ExternalResourceVisitor* visitor) + : visitor_(visitor) {} + virtual void VisitPointers(Object** start, Object** end) { + for (Object** p = start; p < end; p++) { + if ((*p)->IsExternalString()) { + visitor_->VisitExternalString(Utils::ToLocal( + Handle<String>(String::cast(*p)))); + } + } + } + private: + v8::ExternalResourceVisitor* visitor_; + } visitor_adapter(visitor); + external_string_table_.Iterate(&visitor_adapter); +} + + class NewSpaceScavenger : public StaticNewSpaceVisitor<NewSpaceScavenger> { public: static inline void VisitPointer(Heap* heap, Object** p) { @@ -1869,6 +1891,19 @@ MaybeObject* Heap::AllocatePolymorphicCodeCache() { } +MaybeObject* Heap::AllocateAccessorPair() { + Object* result; + { MaybeObject* maybe_result = AllocateStruct(ACCESSOR_PAIR_TYPE); + if (!maybe_result->ToObject(&result)) return maybe_result; + } + AccessorPair* accessors = AccessorPair::cast(result); + // Later we will have to distinguish between undefined and the hole... + // accessors->set_getter(the_hole_value(), SKIP_WRITE_BARRIER); + // accessors->set_setter(the_hole_value(), SKIP_WRITE_BARRIER); + return accessors; +} + + const Heap::StringTypeTable Heap::string_type_table[] = { #define STRING_TYPE_ELEMENT(type, size, name, camel_name) \ {type, size, k##camel_name##MapRootIndex}, @@ -2428,18 +2463,18 @@ bool Heap::CreateInitialObjects() { // Allocate the code_stubs dictionary. The initial size is set to avoid // expanding the dictionary during bootstrapping. - { MaybeObject* maybe_obj = NumberDictionary::Allocate(128); + { MaybeObject* maybe_obj = UnseededNumberDictionary::Allocate(128); if (!maybe_obj->ToObject(&obj)) return false; } - set_code_stubs(NumberDictionary::cast(obj)); + set_code_stubs(UnseededNumberDictionary::cast(obj)); // Allocate the non_monomorphic_cache used in stub-cache.cc. The initial size // is set to avoid expanding the dictionary during bootstrapping. - { MaybeObject* maybe_obj = NumberDictionary::Allocate(64); + { MaybeObject* maybe_obj = UnseededNumberDictionary::Allocate(64); if (!maybe_obj->ToObject(&obj)) return false; } - set_non_monomorphic_cache(NumberDictionary::cast(obj)); + set_non_monomorphic_cache(UnseededNumberDictionary::cast(obj)); { MaybeObject* maybe_obj = AllocatePolymorphicCodeCache(); if (!maybe_obj->ToObject(&obj)) return false; @@ -3794,7 +3829,7 @@ MaybeObject* Heap::AllocateGlobalObject(JSFunction* constructor) { } Map* new_map = Map::cast(obj); - // Setup the global object as a normalized object. + // Set up the global object as a normalized object. global->set_map(new_map); global->map()->clear_instance_descriptors(); global->set_properties(dictionary); @@ -4727,7 +4762,7 @@ bool Heap::IdleGlobalGC() { #ifdef DEBUG void Heap::Print() { - if (!HasBeenSetup()) return; + if (!HasBeenSetUp()) return; isolate()->PrintStack(); AllSpaces spaces; for (Space* space = spaces.next(); space != NULL; space = spaces.next()) @@ -4792,7 +4827,7 @@ bool Heap::Contains(HeapObject* value) { bool Heap::Contains(Address addr) { if (OS::IsOutsideAllocatedSpace(addr)) return false; - return HasBeenSetup() && + return HasBeenSetUp() && (new_space_.ToSpaceContains(addr) || old_pointer_space_->Contains(addr) || old_data_space_->Contains(addr) || @@ -4810,7 +4845,7 @@ bool Heap::InSpace(HeapObject* value, AllocationSpace space) { bool Heap::InSpace(Address addr, AllocationSpace space) { if (OS::IsOutsideAllocatedSpace(addr)) return false; - if (!HasBeenSetup()) return false; + if (!HasBeenSetUp()) return false; switch (space) { case NEW_SPACE: @@ -4835,7 +4870,7 @@ bool Heap::InSpace(Address addr, AllocationSpace space) { #ifdef DEBUG void Heap::Verify() { - ASSERT(HasBeenSetup()); + ASSERT(HasBeenSetUp()); store_buffer()->Verify(); @@ -5262,7 +5297,7 @@ void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) { bool Heap::ConfigureHeap(int max_semispace_size, intptr_t max_old_gen_size, intptr_t max_executable_size) { - if (HasBeenSetup()) return false; + if (HasBeenSetUp()) return false; if (max_semispace_size > 0) { if (max_semispace_size < Page::kPageSize) { @@ -5551,7 +5586,7 @@ class HeapDebugUtils { #endif -bool Heap::Setup(bool create_heap_objects) { +bool Heap::SetUp(bool create_heap_objects) { #ifdef DEBUG allocation_timeout_ = FLAG_gc_interval; debug_utils_ = new HeapDebugUtils(this); @@ -5581,12 +5616,12 @@ bool Heap::Setup(bool create_heap_objects) { MarkMapPointersAsEncoded(false); - // Setup memory allocator. - if (!isolate_->memory_allocator()->Setup(MaxReserved(), MaxExecutableSize())) + // Set up memory allocator. + if (!isolate_->memory_allocator()->SetUp(MaxReserved(), MaxExecutableSize())) return false; - // Setup new space. - if (!new_space_.Setup(reserved_semispace_size_, max_semispace_size_)) { + // Set up new space. + if (!new_space_.SetUp(reserved_semispace_size_, max_semispace_size_)) { return false; } @@ -5597,7 +5632,7 @@ bool Heap::Setup(bool create_heap_objects) { OLD_POINTER_SPACE, NOT_EXECUTABLE); if (old_pointer_space_ == NULL) return false; - if (!old_pointer_space_->Setup()) return false; + if (!old_pointer_space_->SetUp()) return false; // Initialize old data space. old_data_space_ = @@ -5606,14 +5641,14 @@ bool Heap::Setup(bool create_heap_objects) { OLD_DATA_SPACE, NOT_EXECUTABLE); if (old_data_space_ == NULL) return false; - if (!old_data_space_->Setup()) return false; + if (!old_data_space_->SetUp()) return false; // Initialize the code space, set its maximum capacity to the old // generation size. It needs executable memory. // On 64-bit platform(s), we put all code objects in a 2 GB range of // virtual address space, so that they can call each other with near calls. if (code_range_size_ > 0) { - if (!isolate_->code_range()->Setup(code_range_size_)) { + if (!isolate_->code_range()->SetUp(code_range_size_)) { return false; } } @@ -5621,7 +5656,7 @@ bool Heap::Setup(bool create_heap_objects) { code_space_ = new OldSpace(this, max_old_generation_size_, CODE_SPACE, EXECUTABLE); if (code_space_ == NULL) return false; - if (!code_space_->Setup()) return false; + if (!code_space_->SetUp()) return false; // Initialize map space. map_space_ = new MapSpace(this, @@ -5629,28 +5664,28 @@ bool Heap::Setup(bool create_heap_objects) { FLAG_max_map_space_pages, MAP_SPACE); if (map_space_ == NULL) return false; - if (!map_space_->Setup()) return false; + if (!map_space_->SetUp()) return false; // Initialize global property cell space. cell_space_ = new CellSpace(this, max_old_generation_size_, CELL_SPACE); if (cell_space_ == NULL) return false; - if (!cell_space_->Setup()) return false; + if (!cell_space_->SetUp()) return false; // The large object code space may contain code or data. We set the memory // to be non-executable here for safety, but this means we need to enable it // explicitly when allocating large code objects. lo_space_ = new LargeObjectSpace(this, max_old_generation_size_, LO_SPACE); if (lo_space_ == NULL) return false; - if (!lo_space_->Setup()) return false; + if (!lo_space_->SetUp()) return false; - // Setup the seed that is used to randomize the string hash function. - ASSERT(string_hash_seed() == 0); - if (FLAG_randomize_string_hashes) { - if (FLAG_string_hash_seed == 0) { - set_string_hash_seed( + // Set up the seed that is used to randomize the string hash function. + ASSERT(hash_seed() == 0); + if (FLAG_randomize_hashes) { + if (FLAG_hash_seed == 0) { + set_hash_seed( Smi::FromInt(V8::RandomPrivate(isolate()) & 0x3fffffff)); } else { - set_string_hash_seed(Smi::FromInt(FLAG_string_hash_seed)); + set_hash_seed(Smi::FromInt(FLAG_hash_seed)); } } @@ -5668,7 +5703,7 @@ bool Heap::Setup(bool create_heap_objects) { LOG(isolate_, IntPtrTEvent("heap-capacity", Capacity())); LOG(isolate_, IntPtrTEvent("heap-available", Available())); - store_buffer()->Setup(); + store_buffer()->SetUp(); return true; } diff --git a/deps/v8/src/heap.h b/deps/v8/src/heap.h index 2d993bbc2b4..a1a53db4a35 100644 --- a/deps/v8/src/heap.h +++ b/deps/v8/src/heap.h @@ -96,7 +96,7 @@ inline Heap* _inline_get_heap_(); V(FixedArray, single_character_string_cache, SingleCharacterStringCache) \ V(FixedArray, string_split_cache, StringSplitCache) \ V(Object, termination_exception, TerminationException) \ - V(Smi, string_hash_seed, StringHashSeed) \ + V(Smi, hash_seed, HashSeed) \ V(Map, string_map, StringMap) \ V(Map, symbol_map, SymbolMap) \ V(Map, cons_string_map, ConsStringMap) \ @@ -146,8 +146,8 @@ inline Heap* _inline_get_heap_(); V(Map, neander_map, NeanderMap) \ V(JSObject, message_listeners, MessageListeners) \ V(Foreign, prototype_accessors, PrototypeAccessors) \ - V(NumberDictionary, code_stubs, CodeStubs) \ - V(NumberDictionary, non_monomorphic_cache, NonMonomorphicCache) \ + V(UnseededNumberDictionary, code_stubs, CodeStubs) \ + V(UnseededNumberDictionary, non_monomorphic_cache, NonMonomorphicCache) \ V(PolymorphicCodeCache, polymorphic_code_cache, PolymorphicCodeCache) \ V(Code, js_entry_code, JsEntryCode) \ V(Code, js_construct_entry_code, JsConstructEntryCode) \ @@ -434,7 +434,7 @@ class ExternalStringTable { class Heap { public: // Configure heap size before setup. Return false if the heap has been - // setup already. + // set up already. bool ConfigureHeap(int max_semispace_size, intptr_t max_old_gen_size, intptr_t max_executable_size); @@ -443,7 +443,7 @@ class Heap { // Initializes the global object heap. If create_heap_objects is true, // also creates the basic non-mutable objects. // Returns whether it succeeded. - bool Setup(bool create_heap_objects); + bool SetUp(bool create_heap_objects); // Destroys all memory allocated by the heap. void TearDown(); @@ -453,8 +453,8 @@ class Heap { // jslimit_/real_jslimit_ variable in the StackGuard. void SetStackLimits(); - // Returns whether Setup has been called. - bool HasBeenSetup(); + // Returns whether SetUp has been called. + bool HasBeenSetUp(); // Returns the maximum amount of memory reserved for the heap. For // the young generation, we reserve 4 times the amount needed for a @@ -615,6 +615,9 @@ class Heap { // Allocates an empty PolymorphicCodeCache. MUST_USE_RESULT MaybeObject* AllocatePolymorphicCodeCache(); + // Allocates a pre-tenured empty AccessorPair. + MUST_USE_RESULT MaybeObject* AllocateAccessorPair(); + // Clear the Instanceof cache (used when a prototype changes). inline void ClearInstanceofCache(); @@ -1136,7 +1139,7 @@ class Heap { inline AllocationSpace TargetSpaceId(InstanceType type); // Sets the stub_cache_ (only used when expanding the dictionary). - void public_set_code_stubs(NumberDictionary* value) { + void public_set_code_stubs(UnseededNumberDictionary* value) { roots_[kCodeStubsRootIndex] = value; } @@ -1148,7 +1151,7 @@ class Heap { } // Sets the non_monomorphic_cache_ (only used when expanding the dictionary). - void public_set_non_monomorphic_cache(NumberDictionary* value) { + void public_set_non_monomorphic_cache(UnseededNumberDictionary* value) { roots_[kNonMonomorphicCacheRootIndex] = value; } @@ -1409,6 +1412,8 @@ class Heap { void ProcessWeakReferences(WeakObjectRetainer* retainer); + void VisitExternalResources(v8::ExternalResourceVisitor* visitor); + // Helper function that governs the promotion policy from new space to // old. If the object's old address lies below the new space's age // mark or if we've already filled the bottom 1/16th of the to space, @@ -1506,9 +1511,9 @@ class Heap { return idle_notification_will_schedule_next_gc_; } - uint32_t StringHashSeed() { - uint32_t seed = static_cast<uint32_t>(string_hash_seed()->value()); - ASSERT(FLAG_randomize_string_hashes || seed == 0); + uint32_t HashSeed() { + uint32_t seed = static_cast<uint32_t>(hash_seed()->value()); + ASSERT(FLAG_randomize_hashes || seed == 0); return seed; } @@ -1911,7 +1916,7 @@ class Heap { PromotionQueue promotion_queue_; // Flag is set when the heap has been configured. The heap can be repeatedly - // configured through the API until it is setup. + // configured through the API until it is set up. bool configured_; ExternalStringTable external_string_table_; diff --git a/deps/v8/src/hydrogen-instructions.cc b/deps/v8/src/hydrogen-instructions.cc index 1ff7f16fdf4..887e80afc43 100644 --- a/deps/v8/src/hydrogen-instructions.cc +++ b/deps/v8/src/hydrogen-instructions.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -788,6 +788,29 @@ HValue* HTypeof::Canonicalize() { } +HValue* HBitwise::Canonicalize() { + if (!representation().IsInteger32()) return this; + // If x is an int32, then x & -1 == x, x | 0 == x and x ^ 0 == x. + int32_t nop_constant = (op() == Token::BIT_AND) ? -1 : 0; + if (left()->IsConstant() && + HConstant::cast(left())->HasInteger32Value() && + HConstant::cast(left())->Integer32Value() == nop_constant) { + return right(); + } + if (right()->IsConstant() && + HConstant::cast(right())->HasInteger32Value() && + HConstant::cast(right())->Integer32Value() == nop_constant) { + return left(); + } + return this; +} + + +HValue* HChange::Canonicalize() { + return (from().Equals(to())) ? value() : this; +} + + void HTypeof::PrintDataTo(StringStream* stream) { value()->PrintNameTo(stream); } diff --git a/deps/v8/src/hydrogen-instructions.h b/deps/v8/src/hydrogen-instructions.h index 1856c809296..5082e4d3ff0 100644 --- a/deps/v8/src/hydrogen-instructions.h +++ b/deps/v8/src/hydrogen-instructions.h @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -146,6 +146,7 @@ class LChunkBuilder; V(Parameter) \ V(Power) \ V(PushArgument) \ + V(Random) \ V(RegExpLiteral) \ V(Return) \ V(Sar) \ @@ -1130,12 +1131,16 @@ class HChange: public HUnaryOperation { virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited); virtual HType CalculateInferredType(); + virtual HValue* Canonicalize(); Representation from() { return value()->representation(); } Representation to() { return representation(); } bool deoptimize_on_undefined() const { return CheckFlag(kDeoptimizeOnUndefined); } + bool deoptimize_on_minus_zero() const { + return CheckFlag(kBailoutOnMinusZero); + } virtual Representation RequiredInputRepresentation(int index) { return from(); } @@ -1921,8 +1926,11 @@ class HLoadExternalArrayPointer: public HUnaryOperation { class HCheckMap: public HTemplateInstruction<2> { public: - HCheckMap(HValue* value, Handle<Map> map, HValue* typecheck = NULL) - : map_(map) { + HCheckMap(HValue* value, Handle<Map> map, + HValue* typecheck = NULL, + CompareMapMode mode = REQUIRE_EXACT_MAP) + : map_(map), + mode_(mode) { SetOperandAt(0, value); // If callers don't depend on a typecheck, they can pass in NULL. In that // case we use a copy of the |value| argument as a dummy value. @@ -1930,6 +1938,9 @@ class HCheckMap: public HTemplateInstruction<2> { set_representation(Representation::Tagged()); SetFlag(kUseGVN); SetFlag(kDependsOnMaps); + has_element_transitions_ = + map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, NULL) != NULL || + map->LookupElementsTransitionMap(FAST_ELEMENTS, NULL) != NULL; } virtual Representation RequiredInputRepresentation(int index) { @@ -1940,17 +1951,24 @@ class HCheckMap: public HTemplateInstruction<2> { HValue* value() { return OperandAt(0); } Handle<Map> map() const { return map_; } + CompareMapMode mode() const { return mode_; } DECLARE_CONCRETE_INSTRUCTION(CheckMap) protected: virtual bool DataEquals(HValue* other) { HCheckMap* b = HCheckMap::cast(other); - return map_.is_identical_to(b->map()); + // Two CheckMaps instructions are DataEqual if their maps are identical and + // they have the same mode. The mode comparison can be ignored if the map + // has no elements transitions. + return map_.is_identical_to(b->map()) && + (b->mode() == mode() || !has_element_transitions_); } private: + bool has_element_transitions_; Handle<Map> map_; + CompareMapMode mode_; }; @@ -2985,6 +3003,23 @@ class HPower: public HTemplateInstruction<2> { }; +class HRandom: public HTemplateInstruction<1> { + public: + explicit HRandom(HValue* global_object) { + SetOperandAt(0, global_object); + set_representation(Representation::Double()); + } + + HValue* global_object() { return OperandAt(0); } + + virtual Representation RequiredInputRepresentation(int index) { + return Representation::Tagged(); + } + + DECLARE_CONCRETE_INSTRUCTION(Random) +}; + + class HAdd: public HArithmeticBinaryOperation { public: HAdd(HValue* context, HValue* left, HValue* right) @@ -3138,6 +3173,8 @@ class HBitwise: public HBitwiseBinaryOperation { virtual bool IsCommutative() const { return true; } + virtual HValue* Canonicalize(); + static HInstruction* NewHBitwise(Zone* zone, Token::Value op, HValue* context, diff --git a/deps/v8/src/hydrogen.cc b/deps/v8/src/hydrogen.cc index 92308704328..47dcc805367 100644 --- a/deps/v8/src/hydrogen.cc +++ b/deps/v8/src/hydrogen.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -628,7 +628,11 @@ HGraph::HGraph(CompilationInfo* info) Handle<Code> HGraph::Compile(CompilationInfo* info) { int values = GetMaximumValueID(); if (values > LAllocator::max_initial_value_ids()) { - if (FLAG_trace_bailout) PrintF("Function is too big\n"); + if (FLAG_trace_bailout) { + SmartArrayPointer<char> name( + info->shared_info()->DebugName()->ToCString()); + PrintF("Function @\"%s\" is too big.\n", *name); + } return Handle<Code>::null(); } @@ -2301,7 +2305,7 @@ HGraph* HGraphBuilder::CreateGraph() { Bailout("function with illegal redeclaration"); return NULL; } - SetupScope(scope); + SetUpScope(scope); // Add an edge to the body entry. This is warty: the graph's start // environment will be used by the Lithium translation as the initial @@ -2465,7 +2469,7 @@ HInstruction* HGraphBuilder::PreProcessCall(HCall<V>* call) { } -void HGraphBuilder::SetupScope(Scope* scope) { +void HGraphBuilder::SetUpScope(Scope* scope) { HConstant* undefined_constant = new(zone()) HConstant( isolate()->factory()->undefined_value(), Representation::Tagged()); AddInstruction(undefined_constant); @@ -3572,7 +3576,8 @@ HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object, bool smi_and_map_check) { if (smi_and_map_check) { AddInstruction(new(zone()) HCheckNonSmi(object)); - AddInstruction(new(zone()) HCheckMap(object, type)); + AddInstruction(new(zone()) HCheckMap(object, type, NULL, + ALLOW_ELEMENT_TRANSITION_MAPS)); } int index = ComputeStoredFieldIndex(type, name, lookup); @@ -4117,7 +4122,8 @@ HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, bool smi_and_map_check) { if (smi_and_map_check) { AddInstruction(new(zone()) HCheckNonSmi(object)); - AddInstruction(new(zone()) HCheckMap(object, type)); + AddInstruction(new(zone()) HCheckMap(object, type, NULL, + ALLOW_ELEMENT_TRANSITION_MAPS)); } int index = lookup->GetLocalFieldIndexFromMap(*type); @@ -4157,7 +4163,8 @@ HInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj, true); } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) { AddInstruction(new(zone()) HCheckNonSmi(obj)); - AddInstruction(new(zone()) HCheckMap(obj, map)); + AddInstruction(new(zone()) HCheckMap(obj, map, NULL, + ALLOW_ELEMENT_TRANSITION_MAPS)); Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); return new(zone()) HConstant(function, Representation::Tagged()); } else { @@ -4652,7 +4659,8 @@ void HGraphBuilder::AddCheckConstantFunction(Call* expr, // its prototypes. if (smi_and_map_check) { AddInstruction(new(zone()) HCheckNonSmi(receiver)); - AddInstruction(new(zone()) HCheckMap(receiver, receiver_map)); + AddInstruction(new(zone()) HCheckMap(receiver, receiver_map, NULL, + ALLOW_ELEMENT_TRANSITION_MAPS)); } if (!expr->holder().is_null()) { AddInstruction(new(zone()) HCheckPrototypeMaps( @@ -5124,6 +5132,69 @@ bool HGraphBuilder::TryInlineBuiltinFunction(Call* expr, return true; } break; + case kMathRandom: + if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) { + AddCheckConstantFunction(expr, receiver, receiver_map, true); + Drop(1); + HValue* context = environment()->LookupContext(); + HGlobalObject* global_object = new(zone()) HGlobalObject(context); + AddInstruction(global_object); + HRandom* result = new(zone()) HRandom(global_object); + ast_context()->ReturnInstruction(result, expr->id()); + return true; + } + break; + case kMathMax: + case kMathMin: + if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { + AddCheckConstantFunction(expr, receiver, receiver_map, true); + HValue* right = Pop(); + HValue* left = Pop(); + // Do not inline if the return representation is not certain. + if (!left->representation().Equals(right->representation())) { + Push(left); + Push(right); + return false; + } + + Pop(); // Pop receiver. + Token::Value op = (id == kMathMin) ? Token::LT : Token::GT; + HCompareIDAndBranch* compare = NULL; + + if (left->representation().IsTagged()) { + HChange* left_cvt = + new(zone()) HChange(left, Representation::Double(), false, true); + left_cvt->SetFlag(HValue::kBailoutOnMinusZero); + AddInstruction(left_cvt); + HChange* right_cvt = + new(zone()) HChange(right, Representation::Double(), false, true); + right_cvt->SetFlag(HValue::kBailoutOnMinusZero); + AddInstruction(right_cvt); + compare = new(zone()) HCompareIDAndBranch(left_cvt, right_cvt, op); + compare->SetInputRepresentation(Representation::Double()); + } else { + compare = new(zone()) HCompareIDAndBranch(left, right, op); + compare->SetInputRepresentation(left->representation()); + } + + HBasicBlock* return_left = graph()->CreateBasicBlock(); + HBasicBlock* return_right = graph()->CreateBasicBlock(); + + compare->SetSuccessorAt(0, return_left); + compare->SetSuccessorAt(1, return_right); + current_block()->Finish(compare); + + set_current_block(return_left); + Push(left); + set_current_block(return_right); + Push(right); + + HBasicBlock* join = CreateJoin(return_left, return_right, expr->id()); + set_current_block(join); + ast_context()->ReturnValue(Pop()); + return true; + } + break; default: // Not yet supported for inlining. break; @@ -6195,9 +6266,11 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { Handle<Map> map = oracle()->GetCompareMap(expr); if (!map.is_null()) { AddInstruction(new(zone()) HCheckNonSmi(left)); - AddInstruction(new(zone()) HCheckMap(left, map)); + AddInstruction(new(zone()) HCheckMap(left, map, NULL, + ALLOW_ELEMENT_TRANSITION_MAPS)); AddInstruction(new(zone()) HCheckNonSmi(right)); - AddInstruction(new(zone()) HCheckMap(right, map)); + AddInstruction(new(zone()) HCheckMap(right, map, NULL, + ALLOW_ELEMENT_TRANSITION_MAPS)); HCompareObjectEqAndBranch* result = new(zone()) HCompareObjectEqAndBranch(left, right); result->set_position(expr->position()); @@ -6569,7 +6642,11 @@ void HGraphBuilder::GenerateLog(CallRuntime* call) { // Fast support for Math.random(). void HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { - return Bailout("inlined runtime function: RandomHeapNumber"); + HValue* context = environment()->LookupContext(); + HGlobalObject* global_object = new(zone()) HGlobalObject(context); + AddInstruction(global_object); + HRandom* result = new(zone()) HRandom(global_object); + return ast_context()->ReturnInstruction(result, call->id()); } diff --git a/deps/v8/src/hydrogen.h b/deps/v8/src/hydrogen.h index ded1356d189..9705859066d 100644 --- a/deps/v8/src/hydrogen.h +++ b/deps/v8/src/hydrogen.h @@ -870,7 +870,7 @@ class HGraphBuilder: public AstVisitor { Representation rep); static Representation ToRepresentation(TypeInfo info); - void SetupScope(Scope* scope); + void SetUpScope(Scope* scope); virtual void VisitStatements(ZoneList<Statement*>* statements); #define DECLARE_VISIT(type) virtual void Visit##type(type* node); diff --git a/deps/v8/src/ia32/assembler-ia32.cc b/deps/v8/src/ia32/assembler-ia32.cc index 7a5a1916441..bb050b63f91 100644 --- a/deps/v8/src/ia32/assembler-ia32.cc +++ b/deps/v8/src/ia32/assembler-ia32.cc @@ -350,7 +350,7 @@ Assembler::Assembler(Isolate* arg_isolate, void* buffer, int buffer_size) } #endif - // Setup buffer pointers. + // Set up buffer pointers. ASSERT(buffer_ != NULL); pc_ = buffer_; reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); @@ -377,7 +377,7 @@ void Assembler::GetCode(CodeDesc* desc) { // Finalize code (at this point overflow() may be true, but the gap ensures // that we are still not overlapping instructions and relocation info). ASSERT(pc_ <= reloc_info_writer.pos()); // No overlap. - // Setup code descriptor. + // Set up code descriptor. desc->buffer = buffer_; desc->buffer_size = buffer_size_; desc->instr_size = pc_offset(); @@ -2457,7 +2457,7 @@ void Assembler::GrowBuffer() { V8::FatalProcessOutOfMemory("Assembler::GrowBuffer"); } - // Setup new buffer. + // Set up new buffer. desc.buffer = NewArray<byte>(desc.buffer_size); desc.instr_size = pc_offset(); desc.reloc_size = (buffer_ + buffer_size_) - (reloc_info_writer.pos()); diff --git a/deps/v8/src/ia32/builtins-ia32.cc b/deps/v8/src/ia32/builtins-ia32.cc index 55f66f1df8e..4666311af68 100644 --- a/deps/v8/src/ia32/builtins-ia32.cc +++ b/deps/v8/src/ia32/builtins-ia32.cc @@ -333,7 +333,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, __ push(ebx); __ push(ebx); - // Setup pointer to last argument. + // Set up pointer to last argument. __ lea(ebx, Operand(ebp, StandardFrameConstants::kCallerSPOffset)); // Copy arguments and receiver to the expression stack. diff --git a/deps/v8/src/ia32/code-stubs-ia32.cc b/deps/v8/src/ia32/code-stubs-ia32.cc index 9bc024f40d0..b654390c2b7 100644 --- a/deps/v8/src/ia32/code-stubs-ia32.cc +++ b/deps/v8/src/ia32/code-stubs-ia32.cc @@ -128,14 +128,14 @@ void FastNewContextStub::Generate(MacroAssembler* masm) { // Get the function from the stack. __ mov(ecx, Operand(esp, 1 * kPointerSize)); - // Setup the object header. + // Set up the object header. Factory* factory = masm->isolate()->factory(); __ mov(FieldOperand(eax, HeapObject::kMapOffset), factory->function_context_map()); __ mov(FieldOperand(eax, Context::kLengthOffset), Immediate(Smi::FromInt(length))); - // Setup the fixed slots. + // Set up the fixed slots. __ Set(ebx, Immediate(0)); // Set to NULL. __ mov(Operand(eax, Context::SlotOffset(Context::CLOSURE_INDEX)), ecx); __ mov(Operand(eax, Context::SlotOffset(Context::PREVIOUS_INDEX)), esi); @@ -179,7 +179,7 @@ void FastNewBlockContextStub::Generate(MacroAssembler* masm) { // Get the serialized scope info from the stack. __ mov(ebx, Operand(esp, 2 * kPointerSize)); - // Setup the object header. + // Set up the object header. Factory* factory = masm->isolate()->factory(); __ mov(FieldOperand(eax, HeapObject::kMapOffset), factory->block_context_map()); @@ -202,7 +202,7 @@ void FastNewBlockContextStub::Generate(MacroAssembler* masm) { __ mov(ecx, ContextOperand(ecx, Context::CLOSURE_INDEX)); __ bind(&after_sentinel); - // Setup the fixed slots. + // Set up the fixed slots. __ mov(ContextOperand(eax, Context::CLOSURE_INDEX), ecx); __ mov(ContextOperand(eax, Context::PREVIOUS_INDEX), esi); __ mov(ContextOperand(eax, Context::EXTENSION_INDEX), ebx); @@ -3379,7 +3379,7 @@ void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) { __ mov(FieldOperand(eax, i), edx); } - // Setup the callee in-object property. + // Set up the callee in-object property. STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); __ mov(edx, Operand(esp, 4 * kPointerSize)); __ mov(FieldOperand(eax, JSObject::kHeaderSize + @@ -3392,7 +3392,7 @@ void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) { Heap::kArgumentsLengthIndex * kPointerSize), ecx); - // Setup the elements pointer in the allocated arguments object. + // Set up the elements pointer in the allocated arguments object. // If we allocated a parameter map, edi will point there, otherwise to the // backing store. __ lea(edi, Operand(eax, Heap::kArgumentsObjectSize)); @@ -3571,7 +3571,7 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { // Get the parameters pointer from the stack. __ mov(edx, Operand(esp, 2 * kPointerSize)); - // Setup the elements pointer in the allocated arguments object and + // Set up the elements pointer in the allocated arguments object and // initialize the header in the elements fixed array. __ lea(edi, Operand(eax, Heap::kArgumentsObjectSizeStrict)); __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); @@ -4950,7 +4950,7 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { Label invoke, handler_entry, exit; Label not_outermost_js, not_outermost_js_2; - // Setup frame. + // Set up frame. __ push(ebp); __ mov(ebp, esp); @@ -5081,8 +5081,8 @@ void InstanceofStub::Generate(MacroAssembler* masm) { static const int kDeltaToCmpImmediate = 2; static const int kDeltaToMov = 8; static const int kDeltaToMovImmediate = 9; - static const int8_t kCmpEdiImmediateByte1 = BitCast<int8_t, uint8_t>(0x81); - static const int8_t kCmpEdiImmediateByte2 = BitCast<int8_t, uint8_t>(0xff); + static const int8_t kCmpEdiOperandByte1 = BitCast<int8_t, uint8_t>(0x3b); + static const int8_t kCmpEdiOperandByte2 = BitCast<int8_t, uint8_t>(0x3d); static const int8_t kMovEaxImmediateByte = BitCast<int8_t, uint8_t>(0xb8); ExternalReference roots_array_start = @@ -5147,12 +5147,13 @@ void InstanceofStub::Generate(MacroAssembler* masm) { __ mov(scratch, Operand(esp, 0 * kPointerSize)); __ sub(scratch, Operand(esp, 1 * kPointerSize)); if (FLAG_debug_code) { - __ cmpb(Operand(scratch, 0), kCmpEdiImmediateByte1); + __ cmpb(Operand(scratch, 0), kCmpEdiOperandByte1); __ Assert(equal, "InstanceofStub unexpected call site cache (cmp 1)"); - __ cmpb(Operand(scratch, 1), kCmpEdiImmediateByte2); + __ cmpb(Operand(scratch, 1), kCmpEdiOperandByte2); __ Assert(equal, "InstanceofStub unexpected call site cache (cmp 2)"); } - __ mov(Operand(scratch, kDeltaToCmpImmediate), map); + __ mov(scratch, Operand(scratch, kDeltaToCmpImmediate)); + __ mov(Operand(scratch, 0), map); } // Loop through the prototype chain of the object looking for the function @@ -6037,7 +6038,7 @@ void StringHelper::GenerateHashInit(MacroAssembler* masm, if (Serializer::enabled()) { ExternalReference roots_array_start = ExternalReference::roots_array_start(masm->isolate()); - __ mov(scratch, Immediate(Heap::kStringHashSeedRootIndex)); + __ mov(scratch, Immediate(Heap::kHashSeedRootIndex)); __ mov(scratch, Operand::StaticArray(scratch, times_pointer_size, roots_array_start)); @@ -6046,7 +6047,7 @@ void StringHelper::GenerateHashInit(MacroAssembler* masm, __ shl(scratch, 10); __ add(hash, scratch); } else { - int32_t seed = masm->isolate()->heap()->StringHashSeed(); + int32_t seed = masm->isolate()->heap()->HashSeed(); __ lea(scratch, Operand(character, seed)); __ shl(scratch, 10); __ lea(hash, Operand(scratch, character, times_1, seed)); @@ -6091,14 +6092,12 @@ void StringHelper::GenerateHashGetHash(MacroAssembler* masm, __ shl(scratch, 15); __ add(hash, scratch); - uint32_t kHashShiftCutOffMask = (1 << (32 - String::kHashShift)) - 1; - __ and_(hash, kHashShiftCutOffMask); + __ and_(hash, String::kHashBitMask); // if (hash == 0) hash = 27; Label hash_not_zero; - __ test(hash, hash); __ j(not_zero, &hash_not_zero, Label::kNear); - __ mov(hash, Immediate(27)); + __ mov(hash, Immediate(StringHasher::kZeroHash)); __ bind(&hash_not_zero); } diff --git a/deps/v8/src/ia32/cpu-ia32.cc b/deps/v8/src/ia32/cpu-ia32.cc index 57e66df9e33..9eabb2a9693 100644 --- a/deps/v8/src/ia32/cpu-ia32.cc +++ b/deps/v8/src/ia32/cpu-ia32.cc @@ -41,7 +41,7 @@ namespace v8 { namespace internal { -void CPU::Setup() { +void CPU::SetUp() { CpuFeatures::Probe(); } diff --git a/deps/v8/src/ia32/deoptimizer-ia32.cc b/deps/v8/src/ia32/deoptimizer-ia32.cc index 98c240079e4..292315d10ca 100644 --- a/deps/v8/src/ia32/deoptimizer-ia32.cc +++ b/deps/v8/src/ia32/deoptimizer-ia32.cc @@ -406,7 +406,7 @@ void Deoptimizer::DoComputeOsrOutputFrame() { output_[0] = input_; output_[0]->SetPc(reinterpret_cast<uint32_t>(from_)); } else { - // Setup the frame pointer and the context pointer. + // Set up the frame pointer and the context pointer. // All OSR stack frames are dynamically aligned to an 8-byte boundary. int frame_pointer = input_->GetRegister(ebp.code()); if ((frame_pointer & 0x4) == 0) { diff --git a/deps/v8/src/ia32/full-codegen-ia32.cc b/deps/v8/src/ia32/full-codegen-ia32.cc index 6e2391110b2..4f3274436a6 100644 --- a/deps/v8/src/ia32/full-codegen-ia32.cc +++ b/deps/v8/src/ia32/full-codegen-ia32.cc @@ -967,7 +967,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset)); __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset)); - // Setup the four remaining stack slots. + // Set up the four remaining stack slots. __ push(eax); // Map. __ push(edx); // Enumeration cache. __ mov(eax, FieldOperand(edx, FixedArray::kLengthOffset)); diff --git a/deps/v8/src/ia32/lithium-codegen-ia32.cc b/deps/v8/src/ia32/lithium-codegen-ia32.cc index 137d62c5546..8d412fdb537 100644 --- a/deps/v8/src/ia32/lithium-codegen-ia32.cc +++ b/deps/v8/src/ia32/lithium-codegen-ia32.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -1831,7 +1831,7 @@ void LCodeGen::DoHasCachedArrayIndexAndBranch( // Branches to a label or falls through with the answer in the z flag. Trashes -// the temp registers, but not the input. Only input and temp2 may alias. +// the temp registers, but not the input. void LCodeGen::EmitClassOfTest(Label* is_true, Label* is_false, Handle<String>class_name, @@ -1839,7 +1839,8 @@ void LCodeGen::EmitClassOfTest(Label* is_true, Register temp, Register temp2) { ASSERT(!input.is(temp)); - ASSERT(!temp.is(temp2)); // But input and temp2 may be the same register. + ASSERT(!input.is(temp2)); + ASSERT(!temp.is(temp2)); __ JumpIfSmi(input, is_false); if (class_name->IsEqualTo(CStrVector("Function"))) { @@ -1899,12 +1900,7 @@ void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { Register input = ToRegister(instr->InputAt(0)); Register temp = ToRegister(instr->TempAt(0)); Register temp2 = ToRegister(instr->TempAt(1)); - if (input.is(temp)) { - // Swap. - Register swapper = temp; - temp = temp2; - temp2 = swapper; - } + Handle<String> class_name = instr->hydrogen()->class_name(); int true_block = chunk_->LookupDestination(instr->true_block_id()); @@ -1979,7 +1975,9 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { Register map = ToRegister(instr->TempAt(0)); __ mov(map, FieldOperand(object, HeapObject::kMapOffset)); __ bind(deferred->map_check()); // Label for calculating code patching. - __ cmp(map, factory()->the_hole_value()); // Patched to cached map. + Handle<JSGlobalPropertyCell> cache_cell = + factory()->NewJSGlobalPropertyCell(factory()->the_hole_value()); + __ cmp(map, Operand::Cell(cache_cell)); // Patched to cached map. __ j(not_equal, &cache_miss, Label::kNear); __ mov(eax, factory()->the_hole_value()); // Patched to either true or false. __ jmp(&done); @@ -3016,6 +3014,29 @@ void LCodeGen::DoPower(LPower* instr) { } +void LCodeGen::DoRandom(LRandom* instr) { + // Having marked this instruction as a call we can use any + // registers. + ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); + ASSERT(ToRegister(instr->InputAt(0)).is(eax)); + + __ PrepareCallCFunction(1, ebx); + __ mov(eax, FieldOperand(eax, GlobalObject::kGlobalContextOffset)); + __ mov(Operand(esp, 0), eax); + __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); + + // Convert 32 random bits in eax to 0.(32 random bits) in a double + // by computing: + // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). + __ mov(ebx, Immediate(0x49800000)); // 1.0 x 2^20 as single. + __ movd(xmm2, ebx); + __ movd(xmm1, eax); + __ cvtss2sd(xmm2, xmm2); + __ xorps(xmm1, xmm2); + __ subsd(xmm1, xmm2); +} + + void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { ASSERT(instr->value()->Equals(instr->result())); XMMRegister input_reg = ToDoubleRegister(instr->value()); @@ -3678,8 +3699,10 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) { void LCodeGen::EmitNumberUntagD(Register input_reg, + Register temp_reg, XMMRegister result_reg, bool deoptimize_on_undefined, + bool deoptimize_on_minus_zero, LEnvironment* env) { Label load_smi, done; @@ -3708,6 +3731,15 @@ void LCodeGen::EmitNumberUntagD(Register input_reg, } // Heap number to XMM conversion. __ movdbl(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); + if (deoptimize_on_minus_zero) { + XMMRegister xmm_scratch = xmm0; + __ xorps(xmm_scratch, xmm_scratch); + __ ucomisd(result_reg, xmm_scratch); + __ j(not_zero, &done, Label::kNear); + __ movmskpd(temp_reg, result_reg); + __ test_b(temp_reg, 1); + DeoptimizeIf(not_zero, env); + } __ jmp(&done, Label::kNear); // Smi to XMM conversion @@ -3830,14 +3862,23 @@ void LCodeGen::DoTaggedToI(LTaggedToI* instr) { void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { LOperand* input = instr->InputAt(0); ASSERT(input->IsRegister()); + LOperand* temp = instr->TempAt(0); + ASSERT(temp == NULL || temp->IsRegister()); LOperand* result = instr->result(); ASSERT(result->IsDoubleRegister()); Register input_reg = ToRegister(input); XMMRegister result_reg = ToDoubleRegister(result); - EmitNumberUntagD(input_reg, result_reg, + bool deoptimize_on_minus_zero = + instr->hydrogen()->deoptimize_on_minus_zero(); + Register temp_reg = deoptimize_on_minus_zero ? ToRegister(temp) : no_reg; + + EmitNumberUntagD(input_reg, + temp_reg, + result_reg, instr->hydrogen()->deoptimize_on_undefined(), + deoptimize_on_minus_zero, instr->environment()); } @@ -4033,13 +4074,23 @@ void LCodeGen::DoCheckFunction(LCheckFunction* instr) { } +void LCodeGen::DoCheckMapCommon(Register reg, + Handle<Map> map, + CompareMapMode mode, + LEnvironment* env) { + Label success; + __ CompareMap(reg, map, &success, mode); + DeoptimizeIf(not_equal, env); + __ bind(&success); +} + + void LCodeGen::DoCheckMap(LCheckMap* instr) { LOperand* input = instr->InputAt(0); ASSERT(input->IsRegister()); Register reg = ToRegister(input); - __ cmp(FieldOperand(reg, HeapObject::kMapOffset), - instr->hydrogen()->map()); - DeoptimizeIf(not_equal, instr->environment()); + Handle<Map> map = instr->hydrogen()->map(); + DoCheckMapCommon(reg, map, instr->hydrogen()->mode(), instr->environment()); } @@ -4102,9 +4153,9 @@ void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { // Check prototype maps up to the holder. while (!current_prototype.is_identical_to(holder)) { - __ cmp(FieldOperand(reg, HeapObject::kMapOffset), - Handle<Map>(current_prototype->map())); - DeoptimizeIf(not_equal, instr->environment()); + DoCheckMapCommon(reg, Handle<Map>(current_prototype->map()), + ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment()); + current_prototype = Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype())); // Load next prototype object. @@ -4112,9 +4163,8 @@ void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { } // Check the holder map. - __ cmp(FieldOperand(reg, HeapObject::kMapOffset), - Handle<Map>(current_prototype->map())); - DeoptimizeIf(not_equal, instr->environment()); + DoCheckMapCommon(reg, Handle<Map>(current_prototype->map()), + ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment()); } @@ -4139,7 +4189,7 @@ void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { DeoptimizeIf(not_equal, instr->environment()); } - // Setup the parameters to the stub/runtime call. + // Set up the parameters to the stub/runtime call. __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); __ push(FieldOperand(eax, JSFunction::kLiteralsOffset)); __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); @@ -4247,7 +4297,7 @@ void LCodeGen::DoObjectLiteralGeneric(LObjectLiteralGeneric* instr) { Handle<FixedArray> constant_properties = instr->hydrogen()->constant_properties(); - // Setup the parameters to the stub/runtime call. + // Set up the parameters to the stub/runtime call. __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); __ push(FieldOperand(eax, JSFunction::kLiteralsOffset)); __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); diff --git a/deps/v8/src/ia32/lithium-codegen-ia32.h b/deps/v8/src/ia32/lithium-codegen-ia32.h index 375f137d7bb..d86d48cd8cd 100644 --- a/deps/v8/src/ia32/lithium-codegen-ia32.h +++ b/deps/v8/src/ia32/lithium-codegen-ia32.h @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -110,6 +110,9 @@ class LCodeGen BASE_EMBEDDED { void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, Label* map_check); + void DoCheckMapCommon(Register reg, Handle<Map> map, + CompareMapMode mode, LEnvironment* env); + // Parallel move support. void DoParallelMove(LParallelMove* move); void DoGap(LGap* instr); @@ -265,8 +268,10 @@ class LCodeGen BASE_EMBEDDED { void EmitGoto(int block); void EmitBranch(int left_block, int right_block, Condition cc); void EmitNumberUntagD(Register input, + Register temp, XMMRegister result, bool deoptimize_on_undefined, + bool deoptimize_on_minus_zero, LEnvironment* env); // Emits optimized code for typeof x == "y". Modifies input register. @@ -380,7 +385,7 @@ class LDeferredCode: public ZoneObject { virtual void Generate() = 0; virtual LInstruction* instr() = 0; - void SetExit(Label *exit) { external_exit_ = exit; } + void SetExit(Label* exit) { external_exit_ = exit; } Label* entry() { return &entry_; } Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; } int instruction_index() const { return instruction_index_; } diff --git a/deps/v8/src/ia32/lithium-ia32.cc b/deps/v8/src/ia32/lithium-ia32.cc index 5cd276f3001..8435a3c2a13 100644 --- a/deps/v8/src/ia32/lithium-ia32.cc +++ b/deps/v8/src/ia32/lithium-ia32.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -1047,22 +1047,31 @@ LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { - HValue* v = instr->value(); - if (v->EmitAtUses()) { - ASSERT(v->IsConstant()); - ASSERT(!v->representation().IsDouble()); - HBasicBlock* successor = HConstant::cast(v)->ToBoolean() + HValue* value = instr->value(); + if (value->EmitAtUses()) { + ASSERT(value->IsConstant()); + ASSERT(!value->representation().IsDouble()); + HBasicBlock* successor = HConstant::cast(value)->ToBoolean() ? instr->FirstSuccessor() : instr->SecondSuccessor(); return new(zone()) LGoto(successor->block_id()); } + + // Untagged integers or doubles, smis and booleans don't require a + // deoptimization environment nor a temp register. + Representation rep = value->representation(); + HType type = value->type(); + if (!rep.IsTagged() || type.IsSmi() || type.IsBoolean()) { + return new(zone()) LBranch(UseRegister(value), NULL); + } + ToBooleanStub::Types expected = instr->expected_input_types(); // We need a temporary register when we have to access the map *or* we have // no type info yet, in which case we handle all cases (including the ones // involving maps). bool needs_temp = expected.NeedsMap() || expected.IsEmpty(); LOperand* temp = needs_temp ? TempRegister() : NULL; - return AssignEnvironment(new(zone()) LBranch(UseRegister(v), temp)); + return AssignEnvironment(new(zone()) LBranch(UseRegister(value), temp)); } @@ -1388,7 +1397,11 @@ LInstruction* LChunkBuilder::DoMul(HMul* instr) { temp = TempRegister(); } LMulI* mul = new(zone()) LMulI(left, right, temp); - return AssignEnvironment(DefineSameAsFirst(mul)); + if (instr->CheckFlag(HValue::kCanOverflow) || + instr->CheckFlag(HValue::kBailoutOnMinusZero)) { + AssignEnvironment(mul); + } + return DefineSameAsFirst(mul); } else if (instr->representation().IsDouble()) { return DoArithmeticD(Token::MUL, instr); } else { @@ -1456,6 +1469,15 @@ LInstruction* LChunkBuilder::DoPower(HPower* instr) { } +LInstruction* LChunkBuilder::DoRandom(HRandom* instr) { + ASSERT(instr->representation().IsDouble()); + ASSERT(instr->global_object()->representation().IsTagged()); + LOperand* global_object = UseFixed(instr->global_object(), eax); + LRandom* result = new(zone()) LRandom(global_object); + return MarkAsCall(DefineFixedDouble(result, xmm1), instr); +} + + LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) { ASSERT(instr->left()->representation().IsTagged()); ASSERT(instr->right()->representation().IsTagged()); @@ -1588,9 +1610,9 @@ LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch( LInstruction* LChunkBuilder::DoClassOfTestAndBranch( HClassOfTestAndBranch* instr) { ASSERT(instr->value()->representation().IsTagged()); - return new(zone()) LClassOfTestAndBranch(UseTempRegister(instr->value()), - TempRegister(), - TempRegister()); + return new(zone()) LClassOfTestAndBranch(UseRegister(instr->value()), + TempRegister(), + TempRegister()); } @@ -1616,7 +1638,7 @@ LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) { LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) { LOperand* object = UseRegister(instr->value()); LValueOf* result = new(zone()) LValueOf(object, TempRegister()); - return AssignEnvironment(DefineSameAsFirst(result)); + return DefineSameAsFirst(result); } @@ -1660,7 +1682,11 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { if (from.IsTagged()) { if (to.IsDouble()) { LOperand* value = UseRegister(instr->value()); - LNumberUntagD* res = new(zone()) LNumberUntagD(value); + // Temp register only necessary for minus zero check. + LOperand* temp = instr->deoptimize_on_minus_zero() + ? TempRegister() + : NULL; + LNumberUntagD* res = new(zone()) LNumberUntagD(value, temp); return AssignEnvironment(DefineAsRegister(res)); } else { ASSERT(to.IsInteger32()); @@ -1956,7 +1982,8 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement( LOperand* obj = UseRegisterAtStart(instr->object()); LOperand* key = UseRegisterOrConstantAtStart(instr->key()); LLoadKeyedFastElement* result = new(zone()) LLoadKeyedFastElement(obj, key); - return AssignEnvironment(DefineAsRegister(result)); + if (instr->RequiresHoleCheck()) AssignEnvironment(result); + return DefineAsRegister(result); } diff --git a/deps/v8/src/ia32/lithium-ia32.h b/deps/v8/src/ia32/lithium-ia32.h index cc3762d7ab4..67bf9376c71 100644 --- a/deps/v8/src/ia32/lithium-ia32.h +++ b/deps/v8/src/ia32/lithium-ia32.h @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -135,6 +135,7 @@ class LCodeGen; V(OuterContext) \ V(Parameter) \ V(Power) \ + V(Random) \ V(PushArgument) \ V(RegExpLiteral) \ V(Return) \ @@ -1043,6 +1044,17 @@ class LPower: public LTemplateInstruction<1, 2, 0> { }; +class LRandom: public LTemplateInstruction<1, 1, 0> { + public: + explicit LRandom(LOperand* global_object) { + inputs_[0] = global_object; + } + + DECLARE_CONCRETE_INSTRUCTION(Random, "random") + DECLARE_HYDROGEN_ACCESSOR(Random) +}; + + class LArithmeticD: public LTemplateInstruction<1, 2, 0> { public: LArithmeticD(Token::Value op, LOperand* left, LOperand* right) @@ -1612,10 +1624,11 @@ class LSmiTag: public LTemplateInstruction<1, 1, 0> { }; -class LNumberUntagD: public LTemplateInstruction<1, 1, 0> { +class LNumberUntagD: public LTemplateInstruction<1, 1, 1> { public: - explicit LNumberUntagD(LOperand* value) { + explicit LNumberUntagD(LOperand* value, LOperand* temp) { inputs_[0] = value; + temps_[0] = temp; } DECLARE_CONCRETE_INSTRUCTION(NumberUntagD, "double-untag") diff --git a/deps/v8/src/ia32/macro-assembler-ia32.cc b/deps/v8/src/ia32/macro-assembler-ia32.cc index 3356e818922..43f265cf01e 100644 --- a/deps/v8/src/ia32/macro-assembler-ia32.cc +++ b/deps/v8/src/ia32/macro-assembler-ia32.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -487,15 +487,48 @@ void MacroAssembler::StoreNumberToDoubleElements( } +void MacroAssembler::CompareMap(Register obj, + Handle<Map> map, + Label* early_success, + CompareMapMode mode) { + cmp(FieldOperand(obj, HeapObject::kMapOffset), map); + if (mode == ALLOW_ELEMENT_TRANSITION_MAPS) { + Map* transitioned_fast_element_map( + map->LookupElementsTransitionMap(FAST_ELEMENTS, NULL)); + ASSERT(transitioned_fast_element_map == NULL || + map->elements_kind() != FAST_ELEMENTS); + if (transitioned_fast_element_map != NULL) { + j(equal, early_success, Label::kNear); + cmp(FieldOperand(obj, HeapObject::kMapOffset), + Handle<Map>(transitioned_fast_element_map)); + } + + Map* transitioned_double_map( + map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, NULL)); + ASSERT(transitioned_double_map == NULL || + map->elements_kind() == FAST_SMI_ONLY_ELEMENTS); + if (transitioned_double_map != NULL) { + j(equal, early_success, Label::kNear); + cmp(FieldOperand(obj, HeapObject::kMapOffset), + Handle<Map>(transitioned_double_map)); + } + } +} + + void MacroAssembler::CheckMap(Register obj, Handle<Map> map, Label* fail, - SmiCheckType smi_check_type) { + SmiCheckType smi_check_type, + CompareMapMode mode) { if (smi_check_type == DO_SMI_CHECK) { JumpIfSmi(obj, fail); } - cmp(FieldOperand(obj, HeapObject::kMapOffset), Immediate(map)); + + Label success; + CompareMap(obj, map, &success, mode); j(not_equal, fail); + bind(&success); } @@ -616,7 +649,7 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) { void MacroAssembler::EnterExitFramePrologue() { - // Setup the frame structure on the stack. + // Set up the frame structure on the stack. ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize); ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize); @@ -668,7 +701,7 @@ void MacroAssembler::EnterExitFrameEpilogue(int argc, bool save_doubles) { void MacroAssembler::EnterExitFrame(bool save_doubles) { EnterExitFramePrologue(); - // Setup argc and argv in callee-saved registers. + // Set up argc and argv in callee-saved registers. int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; mov(edi, eax); lea(esi, Operand(ebp, eax, times_4, offset)); @@ -959,6 +992,50 @@ void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, } +// Compute the hash code from the untagged key. This must be kept in sync +// with ComputeIntegerHash in utils.h. +// +// Note: r0 will contain hash code +void MacroAssembler::GetNumberHash(Register r0, Register scratch) { + // Xor original key with a seed. + if (Serializer::enabled()) { + ExternalReference roots_array_start = + ExternalReference::roots_array_start(isolate()); + mov(scratch, Immediate(Heap::kHashSeedRootIndex)); + mov(scratch, + Operand::StaticArray(scratch, times_pointer_size, roots_array_start)); + SmiUntag(scratch); + xor_(r0, scratch); + } else { + int32_t seed = isolate()->heap()->HashSeed(); + xor_(r0, Immediate(seed)); + } + + // hash = ~hash + (hash << 15); + mov(scratch, r0); + not_(r0); + shl(scratch, 15); + add(r0, scratch); + // hash = hash ^ (hash >> 12); + mov(scratch, r0); + shr(scratch, 12); + xor_(r0, scratch); + // hash = hash + (hash << 2); + lea(r0, Operand(r0, r0, times_4, 0)); + // hash = hash ^ (hash >> 4); + mov(scratch, r0); + shr(scratch, 4); + xor_(r0, scratch); + // hash = hash * 2057; + imul(r0, r0, 2057); + // hash = hash ^ (hash >> 16); + mov(scratch, r0); + shr(scratch, 16); + xor_(r0, scratch); +} + + + void MacroAssembler::LoadFromNumberDictionary(Label* miss, Register elements, Register key, @@ -984,33 +1061,10 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, Label done; - // Compute the hash code from the untagged key. This must be kept in sync - // with ComputeIntegerHash in utils.h. - // - // hash = ~hash + (hash << 15); - mov(r1, r0); - not_(r0); - shl(r1, 15); - add(r0, r1); - // hash = hash ^ (hash >> 12); - mov(r1, r0); - shr(r1, 12); - xor_(r0, r1); - // hash = hash + (hash << 2); - lea(r0, Operand(r0, r0, times_4, 0)); - // hash = hash ^ (hash >> 4); - mov(r1, r0); - shr(r1, 4); - xor_(r0, r1); - // hash = hash * 2057; - imul(r0, r0, 2057); - // hash = hash ^ (hash >> 16); - mov(r1, r0); - shr(r1, 16); - xor_(r0, r1); + GetNumberHash(r0, r1); // Compute capacity mask. - mov(r1, FieldOperand(elements, NumberDictionary::kCapacityOffset)); + mov(r1, FieldOperand(elements, SeededNumberDictionary::kCapacityOffset)); shr(r1, kSmiTagSize); // convert smi to int dec(r1); @@ -1021,19 +1075,19 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, mov(r2, r0); // Compute the masked index: (hash + i + i * i) & mask. if (i > 0) { - add(r2, Immediate(NumberDictionary::GetProbeOffset(i))); + add(r2, Immediate(SeededNumberDictionary::GetProbeOffset(i))); } and_(r2, r1); // Scale the index by multiplying by the entry size. - ASSERT(NumberDictionary::kEntrySize == 3); + ASSERT(SeededNumberDictionary::kEntrySize == 3); lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 // Check if the key matches. cmp(key, FieldOperand(elements, r2, times_pointer_size, - NumberDictionary::kElementsStartOffset)); + SeededNumberDictionary::kElementsStartOffset)); if (i != (kProbes - 1)) { j(equal, &done); } else { @@ -1044,7 +1098,7 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, bind(&done); // Check that the value is a normal propety. const int kDetailsOffset = - NumberDictionary::kElementsStartOffset + 2 * kPointerSize; + SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize; ASSERT_EQ(NORMAL, 0); test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), Immediate(PropertyDetails::TypeField::kMask << kSmiTagSize)); @@ -1052,7 +1106,7 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, // Get the value at the masked, scaled index. const int kValueOffset = - NumberDictionary::kElementsStartOffset + kPointerSize; + SeededNumberDictionary::kElementsStartOffset + kPointerSize; mov(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); } diff --git a/deps/v8/src/ia32/macro-assembler-ia32.h b/deps/v8/src/ia32/macro-assembler-ia32.h index e6a17417d83..c969a6f71bc 100644 --- a/deps/v8/src/ia32/macro-assembler-ia32.h +++ b/deps/v8/src/ia32/macro-assembler-ia32.h @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -251,7 +251,7 @@ class MacroAssembler: public Assembler { // --------------------------------------------------------------------------- // JavaScript invokes - // Setup call kind marking in ecx. The method takes ecx as an + // Set up call kind marking in ecx. The method takes ecx as an // explicit first parameter to make the code more readable at the // call sites. void SetCallKind(Register dst, CallKind kind); @@ -356,13 +356,24 @@ class MacroAssembler: public Assembler { Label* fail, bool specialize_for_processor); + // Compare an object's map with the specified map and its transitioned + // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. FLAGS are set with + // result of map compare. If multiple map compares are required, the compare + // sequences branches to early_success. + void CompareMap(Register obj, + Handle<Map> map, + Label* early_success, + CompareMapMode mode = REQUIRE_EXACT_MAP); + // Check if the map of an object is equal to a specified map and branch to // label if not. Skip the smi check if not required (object is known to be a - // heap object) + // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match + // against maps that are ElementsKind transition maps of the specificed map. void CheckMap(Register obj, Handle<Map> map, Label* fail, - SmiCheckType smi_check_type); + SmiCheckType smi_check_type, + CompareMapMode mode = REQUIRE_EXACT_MAP); // Check if the map of an object is equal to a specified map and branch to a // specified target if equal. Skip the smi check if not required (object is @@ -486,6 +497,7 @@ class MacroAssembler: public Assembler { Register scratch, Label* miss); + void GetNumberHash(Register r0, Register scratch); void LoadFromNumberDictionary(Label* miss, Register elements, diff --git a/deps/v8/src/ia32/stub-cache-ia32.cc b/deps/v8/src/ia32/stub-cache-ia32.cc index c27a60fd065..0da51c857e5 100644 --- a/deps/v8/src/ia32/stub-cache-ia32.cc +++ b/deps/v8/src/ia32/stub-cache-ia32.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -695,13 +695,9 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm, Register name_reg, Register scratch, Label* miss_label) { - // Check that the object isn't a smi. - __ JumpIfSmi(receiver_reg, miss_label); - // Check that the map of the object hasn't changed. - __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset), - Immediate(Handle<Map>(object->map()))); - __ j(not_equal, miss_label); + __ CheckMap(receiver_reg, Handle<Map>(object->map()), + miss_label, DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); // Perform global security token check if needed. if (object->IsJSGlobalProxy()) { @@ -878,13 +874,10 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object, if (in_new_space) { // Save the map in scratch1 for later. __ mov(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); - __ cmp(scratch1, Immediate(current_map)); - } else { - __ cmp(FieldOperand(reg, HeapObject::kMapOffset), - Immediate(current_map)); } - // Branch on the result of the map check. - __ j(not_equal, miss); + __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK, + ALLOW_ELEMENT_TRANSITION_MAPS); + // 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. @@ -916,9 +909,8 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object, LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); // Check the holder map. - __ cmp(FieldOperand(reg, HeapObject::kMapOffset), - Immediate(Handle<Map>(holder->map()))); - __ j(not_equal, miss); + __ CheckMap(reg, Handle<Map>(holder->map()), + miss, DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); // Perform security check for access to the global object. ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); @@ -2338,7 +2330,7 @@ Handle<Code> CallStubCompiler::CompileCallGlobal( __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); } - // Setup the context (function already in edi). + // Set up the context (function already in edi). __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); // Jump to the cached code (tail call). @@ -2403,13 +2395,9 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback( // ----------------------------------- Label miss; - // Check that the object isn't a smi. - __ JumpIfSmi(edx, &miss); - // Check that the map of the object hasn't changed. - __ cmp(FieldOperand(edx, HeapObject::kMapOffset), - Immediate(Handle<Map>(object->map()))); - __ j(not_equal, &miss); + __ CheckMap(edx, Handle<Map>(object->map()), + &miss, DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); // Perform global security token check if needed. if (object->IsJSGlobalProxy()) { @@ -2453,13 +2441,9 @@ Handle<Code> StoreStubCompiler::CompileStoreInterceptor( // ----------------------------------- Label miss; - // Check that the object isn't a smi. - __ JumpIfSmi(edx, &miss); - // Check that the map of the object hasn't changed. - __ cmp(FieldOperand(edx, HeapObject::kMapOffset), - Immediate(Handle<Map>(receiver->map()))); - __ j(not_equal, &miss); + __ CheckMap(edx, Handle<Map>(receiver->map()), + &miss, DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); // Perform global security token check if needed. if (receiver->IsJSGlobalProxy()) { diff --git a/deps/v8/src/ic.cc b/deps/v8/src/ic.cc index 624ecd7f581..9024605da54 100644 --- a/deps/v8/src/ic.cc +++ b/deps/v8/src/ic.cc @@ -1267,7 +1267,8 @@ MaybeObject* StoreIC::Store(State state, // Check if the given name is an array index. uint32_t index; if (name->AsArrayIndex(&index)) { - Handle<Object> result = SetElement(receiver, index, value, strict_mode); + Handle<Object> result = + JSObject::SetElement(receiver, index, value, strict_mode); RETURN_IF_EMPTY_HANDLE(isolate(), result); return *value; } @@ -1644,7 +1645,8 @@ MaybeObject* KeyedStoreIC::Store(State state, // Check if the given name is an array index. uint32_t index; if (name->AsArrayIndex(&index)) { - Handle<Object> result = SetElement(receiver, index, value, strict_mode); + Handle<Object> result = + JSObject::SetElement(receiver, index, value, strict_mode); RETURN_IF_EMPTY_HANDLE(isolate(), result); return *value; } diff --git a/deps/v8/src/incremental-marking.cc b/deps/v8/src/incremental-marking.cc index 8fca3050577..f6d5a5963db 100644 --- a/deps/v8/src/incremental-marking.cc +++ b/deps/v8/src/incremental-marking.cc @@ -418,7 +418,7 @@ void IncrementalMarking::ActivateGeneratedStub(Code* stub) { static void PatchIncrementalMarkingRecordWriteStubs( Heap* heap, RecordWriteStub::Mode mode) { - NumberDictionary* stubs = heap->code_stubs(); + UnseededNumberDictionary* stubs = heap->code_stubs(); int capacity = stubs->Capacity(); for (int i = 0; i < capacity; i++) { diff --git a/deps/v8/src/incremental-marking.h b/deps/v8/src/incremental-marking.h index 25def870686..4f8fa6b1275 100644 --- a/deps/v8/src/incremental-marking.h +++ b/deps/v8/src/incremental-marking.h @@ -56,6 +56,7 @@ class IncrementalMarking { } bool should_hurry() { return should_hurry_; } + void set_should_hurry(bool val) { should_hurry_ = val; } inline bool IsStopped() { return state() == STOPPED; } @@ -219,10 +220,6 @@ class IncrementalMarking { void UncommitMarkingDeque(); private: - void set_should_hurry(bool val) { - should_hurry_ = val; - } - int64_t SpaceLeftInOldSpace(); void ResetStepCounters(); diff --git a/deps/v8/src/inspector.cc b/deps/v8/src/inspector.cc index 8fb80f1a229..833d3384396 100644 --- a/deps/v8/src/inspector.cc +++ b/deps/v8/src/inspector.cc @@ -38,11 +38,11 @@ namespace internal { //============================================================================ // The Inspector. -void Inspector::DumpObjectType(FILE* out, Object *obj, bool print_more) { +void Inspector::DumpObjectType(FILE* out, Object* obj, bool print_more) { // Dump the object pointer. OS::FPrint(out, "%p:", reinterpret_cast<void*>(obj)); if (obj->IsHeapObject()) { - HeapObject *hobj = HeapObject::cast(obj); + HeapObject* hobj = HeapObject::cast(obj); OS::FPrint(out, " size %d :", hobj->Size()); } diff --git a/deps/v8/src/inspector.h b/deps/v8/src/inspector.h index e328bcdfa5e..6962e21f4f0 100644 --- a/deps/v8/src/inspector.h +++ b/deps/v8/src/inspector.h @@ -41,14 +41,14 @@ namespace internal { class Inspector { public: - static void DumpObjectType(FILE* out, Object *obj, bool print_more); - static void DumpObjectType(FILE* out, Object *obj) { + static void DumpObjectType(FILE* out, Object* obj, bool print_more); + static void DumpObjectType(FILE* out, Object* obj) { DumpObjectType(out, obj, false); } - static void DumpObjectType(Object *obj, bool print_more) { + static void DumpObjectType(Object* obj, bool print_more) { DumpObjectType(stdout, obj, print_more); } - static void DumpObjectType(Object *obj) { + static void DumpObjectType(Object* obj) { DumpObjectType(stdout, obj, false); } }; diff --git a/deps/v8/src/isolate.cc b/deps/v8/src/isolate.cc index c235a23439d..35e9e284f9b 100644 --- a/deps/v8/src/isolate.cc +++ b/deps/v8/src/isolate.cc @@ -570,7 +570,7 @@ Handle<JSArray> Isolate::CaptureCurrentStackTrace( frame->Summarize(&frames); for (int i = frames.length() - 1; i >= 0 && frames_seen < limit; i--) { // Create a JSObject to hold the information for the StackFrame. - Handle<JSObject> stackFrame = factory()->NewJSObject(object_function()); + Handle<JSObject> stack_frame = factory()->NewJSObject(object_function()); Handle<JSFunction> fun = frames[i].function(); Handle<Script> script(Script::cast(fun->shared()->script())); @@ -591,16 +591,24 @@ Handle<JSArray> Isolate::CaptureCurrentStackTrace( // tag. column_offset += script->column_offset()->value(); } - SetLocalPropertyNoThrow(stackFrame, column_key, - Handle<Smi>(Smi::FromInt(column_offset + 1))); + CHECK_NOT_EMPTY_HANDLE( + this, + JSObject::SetLocalPropertyIgnoreAttributes( + stack_frame, column_key, + Handle<Smi>(Smi::FromInt(column_offset + 1)), NONE)); } - SetLocalPropertyNoThrow(stackFrame, line_key, - Handle<Smi>(Smi::FromInt(line_number + 1))); + CHECK_NOT_EMPTY_HANDLE( + this, + JSObject::SetLocalPropertyIgnoreAttributes( + stack_frame, line_key, + Handle<Smi>(Smi::FromInt(line_number + 1)), NONE)); } if (options & StackTrace::kScriptName) { Handle<Object> script_name(script->name(), this); - SetLocalPropertyNoThrow(stackFrame, script_key, script_name); + CHECK_NOT_EMPTY_HANDLE(this, + JSObject::SetLocalPropertyIgnoreAttributes( + stack_frame, script_key, script_name, NONE)); } if (options & StackTrace::kScriptNameOrSourceURL) { @@ -616,8 +624,10 @@ Handle<JSArray> Isolate::CaptureCurrentStackTrace( if (caught_exception) { result = factory()->undefined_value(); } - SetLocalPropertyNoThrow(stackFrame, script_name_or_source_url_key, - result); + CHECK_NOT_EMPTY_HANDLE(this, + JSObject::SetLocalPropertyIgnoreAttributes( + stack_frame, script_name_or_source_url_key, + result, NONE)); } if (options & StackTrace::kFunctionName) { @@ -625,23 +635,30 @@ Handle<JSArray> Isolate::CaptureCurrentStackTrace( if (fun_name->ToBoolean()->IsFalse()) { fun_name = Handle<Object>(fun->shared()->inferred_name(), this); } - SetLocalPropertyNoThrow(stackFrame, function_key, fun_name); + CHECK_NOT_EMPTY_HANDLE(this, + JSObject::SetLocalPropertyIgnoreAttributes( + stack_frame, function_key, fun_name, NONE)); } if (options & StackTrace::kIsEval) { int type = Smi::cast(script->compilation_type())->value(); Handle<Object> is_eval = (type == Script::COMPILATION_TYPE_EVAL) ? factory()->true_value() : factory()->false_value(); - SetLocalPropertyNoThrow(stackFrame, eval_key, is_eval); + CHECK_NOT_EMPTY_HANDLE(this, + JSObject::SetLocalPropertyIgnoreAttributes( + stack_frame, eval_key, is_eval, NONE)); } if (options & StackTrace::kIsConstructor) { Handle<Object> is_constructor = (frames[i].is_constructor()) ? factory()->true_value() : factory()->false_value(); - SetLocalPropertyNoThrow(stackFrame, constructor_key, is_constructor); + CHECK_NOT_EMPTY_HANDLE(this, + JSObject::SetLocalPropertyIgnoreAttributes( + stack_frame, constructor_key, + is_constructor, NONE)); } - FixedArray::cast(stack_trace->elements())->set(frames_seen, *stackFrame); + FixedArray::cast(stack_trace->elements())->set(frames_seen, *stack_frame); frames_seen++; } it.Advance(); @@ -1734,10 +1751,10 @@ bool Isolate::Init(Deserializer* des) { regexp_stack_->isolate_ = this; // Enable logging before setting up the heap - logger_->Setup(); + logger_->SetUp(); - CpuProfiler::Setup(); - HeapProfiler::Setup(); + CpuProfiler::SetUp(); + HeapProfiler::SetUp(); // Initialize other runtime facilities #if defined(USE_SIMULATOR) @@ -1754,10 +1771,10 @@ bool Isolate::Init(Deserializer* des) { stack_guard_.InitThread(lock); } - // Setup the object heap. + // SetUp the object heap. const bool create_heap_objects = (des == NULL); - ASSERT(!heap_.HasBeenSetup()); - if (!heap_.Setup(create_heap_objects)) { + ASSERT(!heap_.HasBeenSetUp()); + if (!heap_.SetUp(create_heap_objects)) { V8::SetFatalError(); return false; } @@ -1765,7 +1782,7 @@ bool Isolate::Init(Deserializer* des) { InitializeThreadLocal(); bootstrapper_->Initialize(create_heap_objects); - builtins_.Setup(create_heap_objects); + builtins_.SetUp(create_heap_objects); // Only preallocate on the first initialization. if (FLAG_preallocate_message_memory && preallocated_message_space_ == NULL) { @@ -1784,7 +1801,7 @@ bool Isolate::Init(Deserializer* des) { } #ifdef ENABLE_DEBUGGER_SUPPORT - debug_->Setup(create_heap_objects); + debug_->SetUp(create_heap_objects); #endif stub_cache_->Initialize(create_heap_objects); @@ -1805,7 +1822,7 @@ bool Isolate::Init(Deserializer* des) { deoptimizer_data_ = new DeoptimizerData; runtime_profiler_ = new RuntimeProfiler(this); - runtime_profiler_->Setup(); + runtime_profiler_->SetUp(); // If we are deserializing, log non-function code objects and compiled // functions found in the snapshot. diff --git a/deps/v8/src/isolate.h b/deps/v8/src/isolate.h index c044e1f5789..4e5c7dbf513 100644 --- a/deps/v8/src/isolate.h +++ b/deps/v8/src/isolate.h @@ -122,6 +122,13 @@ typedef ZoneList<Handle<Object> > ZoneObjectList; } \ } while (false) +#define CHECK_NOT_EMPTY_HANDLE(isolate, call) \ + do { \ + ASSERT(!(isolate)->has_pending_exception()); \ + CHECK(!(call).is_null()); \ + CHECK(!(isolate)->has_pending_exception()); \ + } while (false) + #define RETURN_IF_EMPTY_HANDLE(isolate, call) \ RETURN_IF_EMPTY_HANDLE_VALUE(isolate, call, Failure::Exception()) diff --git a/deps/v8/src/json-parser.h b/deps/v8/src/json-parser.h index ca796a69907..2b7077e1944 100644 --- a/deps/v8/src/json-parser.h +++ b/deps/v8/src/json-parser.h @@ -303,11 +303,12 @@ Handle<Object> JsonParser<seq_ascii>::ParseJsonObject() { uint32_t index; if (key->AsArrayIndex(&index)) { - SetOwnElement(json_object, index, value, kNonStrictMode); + JSObject::SetOwnElement(json_object, index, value, kNonStrictMode); } else if (key->Equals(isolate()->heap()->Proto_symbol())) { SetPrototype(json_object, value); } else { - SetLocalPropertyIgnoreAttributes(json_object, key, value, NONE); + JSObject::SetLocalPropertyIgnoreAttributes( + json_object, key, value, NONE); } } while (MatchSkipWhiteSpace(',')); if (c0_ != '}') { diff --git a/deps/v8/src/jsregexp.cc b/deps/v8/src/jsregexp.cc index 18ff2570e6e..15b80d92ceb 100644 --- a/deps/v8/src/jsregexp.cc +++ b/deps/v8/src/jsregexp.cc @@ -2636,7 +2636,7 @@ void TextNode::MakeCaseIndependent(bool is_ascii) { TextElement elm = elms_->at(i); if (elm.type == TextElement::CHAR_CLASS) { RegExpCharacterClass* cc = elm.data.u_char_class; - // None of the standard character classses is different in the case + // None of the standard character classes is different in the case // independent case and it slows us down if we don't know that. if (cc->is_standard()) continue; ZoneList<CharacterRange>* ranges = cc->ranges(); diff --git a/deps/v8/src/lithium-allocator.cc b/deps/v8/src/lithium-allocator.cc index c4d8b1e5b7b..1601dcf14ee 100644 --- a/deps/v8/src/lithium-allocator.cc +++ b/deps/v8/src/lithium-allocator.cc @@ -49,13 +49,13 @@ namespace internal { #define DEFINE_OPERAND_CACHE(name, type) \ name name::cache[name::kNumCachedOperands]; \ - void name::SetupCache() { \ + void name::SetUpCache() { \ for (int i = 0; i < kNumCachedOperands; i++) { \ cache[i].ConvertTo(type, i); \ } \ } \ static bool name##_initialize() { \ - name::SetupCache(); \ + name::SetUpCache(); \ return true; \ } \ static bool name##_cache_initialized = name##_initialize(); diff --git a/deps/v8/src/lithium.h b/deps/v8/src/lithium.h index b605eb97bd3..3253520090e 100644 --- a/deps/v8/src/lithium.h +++ b/deps/v8/src/lithium.h @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -265,7 +265,7 @@ class LConstantOperand: public LOperand { return reinterpret_cast<LConstantOperand*>(op); } - static void SetupCache(); + static void SetUpCache(); private: static const int kNumCachedOperands = 128; @@ -300,7 +300,7 @@ class LStackSlot: public LOperand { return reinterpret_cast<LStackSlot*>(op); } - static void SetupCache(); + static void SetUpCache(); private: static const int kNumCachedOperands = 128; @@ -324,7 +324,7 @@ class LDoubleStackSlot: public LOperand { return reinterpret_cast<LDoubleStackSlot*>(op); } - static void SetupCache(); + static void SetUpCache(); private: static const int kNumCachedOperands = 128; @@ -348,7 +348,7 @@ class LRegister: public LOperand { return reinterpret_cast<LRegister*>(op); } - static void SetupCache(); + static void SetUpCache(); private: static const int kNumCachedOperands = 16; @@ -372,7 +372,7 @@ class LDoubleRegister: public LOperand { return reinterpret_cast<LDoubleRegister*>(op); } - static void SetupCache(); + static void SetUpCache(); private: static const int kNumCachedOperands = 16; @@ -523,8 +523,6 @@ class LEnvironment: public ZoneObject { LOperand** spilled_double_registers_; LEnvironment* outer_; - - friend class LCodegen; }; diff --git a/deps/v8/src/liveedit.cc b/deps/v8/src/liveedit.cc index eb183dac5e7..5ff8ff9d3bd 100644 --- a/deps/v8/src/liveedit.cc +++ b/deps/v8/src/liveedit.cc @@ -54,7 +54,7 @@ void SetElementNonStrict(Handle<JSObject> object, // are element setters causing exceptions and the debugger context has none // of these. Handle<Object> no_failure; - no_failure = SetElement(object, index, value, kNonStrictMode); + no_failure = JSObject::SetElement(object, index, value, kNonStrictMode); ASSERT(!no_failure.is_null()); USE(no_failure); } @@ -1228,7 +1228,7 @@ class RelocInfoBuffer { V8::FatalProcessOutOfMemory("RelocInfoBuffer::GrowBuffer"); } - // Setup new buffer. + // Set up new buffer. byte* new_buffer = NewArray<byte>(new_buffer_size); // Copy the data. diff --git a/deps/v8/src/liveobjectlist-inl.h b/deps/v8/src/liveobjectlist-inl.h index f742de3a03c..2bc2296e29c 100644 --- a/deps/v8/src/liveobjectlist-inl.h +++ b/deps/v8/src/liveobjectlist-inl.h @@ -59,7 +59,7 @@ void LiveObjectList::IterateElements(ObjectVisitor* v) { } -void LiveObjectList::ProcessNonLive(HeapObject *obj) { +void LiveObjectList::ProcessNonLive(HeapObject* obj) { // Only do work if we have at least one list to process. if (last()) DoProcessNonLive(obj); } @@ -93,7 +93,7 @@ LiveObjectList* LiveObjectList::FindLolForId(int id, template <typename T> inline LiveObjectList::Element* LiveObjectList::FindElementFor(T (*GetValue)(LiveObjectList::Element*), T key) { - LiveObjectList *lol = last(); + LiveObjectList* lol = last(); while (lol != NULL) { Element* elements = lol->elements_; for (int i = 0; i < lol->obj_count_; i++) { diff --git a/deps/v8/src/liveobjectlist.cc b/deps/v8/src/liveobjectlist.cc index 408e2a3160f..436204e3fac 100644 --- a/deps/v8/src/liveobjectlist.cc +++ b/deps/v8/src/liveobjectlist.cc @@ -165,7 +165,7 @@ const char* GetObjectTypeDesc(HeapObject* heap_obj) { } -bool IsOfType(LiveObjectType type, HeapObject *obj) { +bool IsOfType(LiveObjectType type, HeapObject* obj) { // Note: there are types that are more general (e.g. JSObject) that would // have passed the Is##type_() test for more specialized types (e.g. // JSFunction). If we find a more specialized match but we're looking for @@ -211,7 +211,7 @@ static AllocationSpace FindSpaceFor(String* space_str) { } -static bool InSpace(AllocationSpace space, HeapObject *heap_obj) { +static bool InSpace(AllocationSpace space, HeapObject* heap_obj) { Heap* heap = ISOLATE->heap(); if (space != LO_SPACE) { return heap->InSpace(heap_obj, space); @@ -498,7 +498,7 @@ static void GenerateObjectDesc(HeapObject* obj, length); } else if (obj->IsString()) { - String *str = String::cast(obj); + String* str = String::cast(obj); // Only grab up to 160 chars in case they are double byte. // We'll only dump 80 of them after we compact them. const int kMaxCharToDump = 80; @@ -842,7 +842,7 @@ class LiveObjectSummary { bool found_root_; bool found_weak_root_; - LolFilter *filter_; + LolFilter* filter_; }; @@ -857,8 +857,8 @@ class SummaryWriter { // A summary writer for filling in a summary of lol lists and diffs. class LolSummaryWriter: public SummaryWriter { public: - LolSummaryWriter(LiveObjectList *older_lol, - LiveObjectList *newer_lol) + LolSummaryWriter(LiveObjectList* older_lol, + LiveObjectList* newer_lol) : older_(older_lol), newer_(newer_lol) { } @@ -944,7 +944,7 @@ LiveObjectList::~LiveObjectList() { int LiveObjectList::GetTotalObjCountAndSize(int* size_p) { int size = 0; int count = 0; - LiveObjectList *lol = this; + LiveObjectList* lol = this; do { // Only compute total size if requested i.e. when size_p is not null. if (size_p != NULL) { @@ -1183,7 +1183,7 @@ MaybeObject* LiveObjectList::Capture() { // only time we'll actually delete the lol is when we Reset() or if the lol is // invisible, and its element count reaches 0. bool LiveObjectList::Delete(int id) { - LiveObjectList *lol = last(); + LiveObjectList* lol = last(); while (lol != NULL) { if (lol->id() == id) { break; @@ -1246,8 +1246,8 @@ MaybeObject* LiveObjectList::Dump(int older_id, newer_id = temp; } - LiveObjectList *newer_lol = FindLolForId(newer_id, last()); - LiveObjectList *older_lol = FindLolForId(older_id, newer_lol); + LiveObjectList* newer_lol = FindLolForId(newer_id, last()); + LiveObjectList* older_lol = FindLolForId(older_id, newer_lol); // If the id is defined, and we can't find a LOL for it, then we have an // invalid id. @@ -1365,8 +1365,8 @@ MaybeObject* LiveObjectList::Summarize(int older_id, newer_id = temp; } - LiveObjectList *newer_lol = FindLolForId(newer_id, last()); - LiveObjectList *older_lol = FindLolForId(older_id, newer_lol); + LiveObjectList* newer_lol = FindLolForId(newer_id, last()); + LiveObjectList* older_lol = FindLolForId(older_id, newer_lol); // If the id is defined, and we can't find a LOL for it, then we have an // invalid id. @@ -1626,7 +1626,7 @@ MaybeObject* LiveObjectList::Info(int start_idx, int dump_limit) { // Deletes all captured lols. void LiveObjectList::Reset() { - LiveObjectList *lol = last(); + LiveObjectList* lol = last(); // Just delete the last. Each lol will delete it's prev automatically. delete lol; @@ -1715,8 +1715,8 @@ class LolVisitor: public ObjectVisitor { inline bool AddRootRetainerIfFound(const LolVisitor& visitor, LolFilter* filter, - LiveObjectSummary *summary, - void (*SetRootFound)(LiveObjectSummary *s), + LiveObjectSummary* summary, + void (*SetRootFound)(LiveObjectSummary* s), int start, int dump_limit, int* total_count, @@ -1762,12 +1762,12 @@ inline bool AddRootRetainerIfFound(const LolVisitor& visitor, } -inline void SetFoundRoot(LiveObjectSummary *summary) { +inline void SetFoundRoot(LiveObjectSummary* summary) { summary->set_found_root(); } -inline void SetFoundWeakRoot(LiveObjectSummary *summary) { +inline void SetFoundWeakRoot(LiveObjectSummary* summary) { summary->set_found_weak_root(); } @@ -1779,7 +1779,7 @@ int LiveObjectList::GetRetainers(Handle<HeapObject> target, int dump_limit, int* total_count, LolFilter* filter, - LiveObjectSummary *summary, + LiveObjectSummary* summary, JSFunction* arguments_function, Handle<Object> error) { HandleScope scope; @@ -2267,7 +2267,7 @@ Object* LiveObjectList::GetPath(int obj_id1, } -void LiveObjectList::DoProcessNonLive(HeapObject *obj) { +void LiveObjectList::DoProcessNonLive(HeapObject* obj) { // We should only be called if we have at least one lol to search. ASSERT(last() != NULL); Element* element = last()->Find(obj); @@ -2284,7 +2284,7 @@ void LiveObjectList::IterateElementsPrivate(ObjectVisitor* v) { int count = lol->obj_count_; for (int i = 0; i < count; i++) { HeapObject** p = &elements[i].obj_; - v->VisitPointer(reinterpret_cast<Object **>(p)); + v->VisitPointer(reinterpret_cast<Object** >(p)); } lol = lol->prev_; } @@ -2389,11 +2389,11 @@ void LiveObjectList::GCEpiloguePrivate() { PurgeDuplicates(); // After the GC, sweep away all free'd Elements and compact. - LiveObjectList *prev = NULL; - LiveObjectList *next = NULL; + LiveObjectList* prev = NULL; + LiveObjectList* next = NULL; // Iterating from the youngest lol to the oldest lol. - for (LiveObjectList *lol = last(); lol; lol = prev) { + for (LiveObjectList* lol = last(); lol; lol = prev) { Element* elements = lol->elements_; prev = lol->prev(); // Save the prev. @@ -2446,7 +2446,7 @@ void LiveObjectList::GCEpiloguePrivate() { const int kMaxUnusedSpace = 64; if (diff > kMaxUnusedSpace) { // Threshold for shrinking. // Shrink the list. - Element *new_elements = NewArray<Element>(new_count); + Element* new_elements = NewArray<Element>(new_count); memcpy(new_elements, elements, new_count * sizeof(Element)); DeleteArray<Element>(elements); diff --git a/deps/v8/src/liveobjectlist.h b/deps/v8/src/liveobjectlist.h index 65470d7ad9b..1aa91960512 100644 --- a/deps/v8/src/liveobjectlist.h +++ b/deps/v8/src/liveobjectlist.h @@ -77,7 +77,7 @@ class LiveObjectList { inline static void GCEpilogue(); inline static void GCPrologue(); inline static void IterateElements(ObjectVisitor* v); - inline static void ProcessNonLive(HeapObject *obj); + inline static void ProcessNonLive(HeapObject* obj); inline static void UpdateReferencesForScavengeGC(); // Note: LOLs can be listed by calling Dump(0, <lol id>), and 2 LOLs can be @@ -125,7 +125,7 @@ class LiveObjectList { static void GCEpiloguePrivate(); static void IterateElementsPrivate(ObjectVisitor* v); - static void DoProcessNonLive(HeapObject *obj); + static void DoProcessNonLive(HeapObject* obj); static int CompareElement(const Element* a, const Element* b); @@ -138,7 +138,7 @@ class LiveObjectList { int dump_limit, int* total_count, LolFilter* filter, - LiveObjectSummary *summary, + LiveObjectSummary* summary, JSFunction* arguments_function, Handle<Object> error); @@ -151,7 +151,7 @@ class LiveObjectList { bool is_tracking_roots); static bool NeedLOLProcessing() { return (last() != NULL); } - static void NullifyNonLivePointer(HeapObject **p) { + static void NullifyNonLivePointer(HeapObject** p) { // Mask out the low bit that marks this as a heap object. We'll use this // cleared bit as an indicator that this pointer needs to be collected. // @@ -202,7 +202,7 @@ class LiveObjectList { int id_; int capacity_; int obj_count_; - Element *elements_; + Element* elements_; // Statics for managing all the lists. static uint32_t next_element_id_; diff --git a/deps/v8/src/log.cc b/deps/v8/src/log.cc index eab26392e34..5e82872da1e 100644 --- a/deps/v8/src/log.cc +++ b/deps/v8/src/log.cc @@ -1615,7 +1615,7 @@ void Logger::LogAccessorCallbacks() { } -bool Logger::Setup() { +bool Logger::SetUp() { // Tests and EnsureInitialize() can call this twice in a row. It's harmless. if (is_initialized_) return true; is_initialized_ = true; @@ -1708,9 +1708,9 @@ FILE* Logger::TearDown() { void Logger::EnableSlidingStateWindow() { - // If the ticker is NULL, Logger::Setup has not been called yet. In + // If the ticker is NULL, Logger::SetUp has not been called yet. In // that case, we set the sliding_state_window flag so that the - // sliding window computation will be started when Logger::Setup is + // sliding window computation will be started when Logger::SetUp is // called. if (ticker_ == NULL) { FLAG_sliding_state_window = true; diff --git a/deps/v8/src/log.h b/deps/v8/src/log.h index 677dada03a8..86bcad69aa6 100644 --- a/deps/v8/src/log.h +++ b/deps/v8/src/log.h @@ -150,14 +150,14 @@ class Logger { #undef DECLARE_ENUM // Acquires resources for logging if the right flags are set. - bool Setup(); + bool SetUp(); void EnsureTickerStarted(); void EnsureTickerStopped(); Sampler* sampler(); - // Frees resources acquired in Setup. + // Frees resources acquired in SetUp. // When a temporary file is used for the log, returns its stream descriptor, // leaving the file open. FILE* TearDown(); @@ -411,7 +411,7 @@ class Logger { NameMap* address_to_name_map_; // Guards against multiple calls to TearDown() that can happen in some tests. - // 'true' between Setup() and TearDown(). + // 'true' between SetUp() and TearDown(). bool is_initialized_; // Support for 'incremental addresses' in compressed logs: diff --git a/deps/v8/src/mark-compact.cc b/deps/v8/src/mark-compact.cc index 1fb5d5f438b..6d7fbdff2b5 100644 --- a/deps/v8/src/mark-compact.cc +++ b/deps/v8/src/mark-compact.cc @@ -3641,6 +3641,7 @@ void MarkCompactCollector::SweepSpace(PagedSpace* space, SweeperType sweeper) { PrintF("Sweeping 0x%" V8PRIxPTR " lazily postponed.\n", reinterpret_cast<intptr_t>(p)); } + space->MarkPageForLazySweeping(p); continue; } diff --git a/deps/v8/src/mips/assembler-mips-inl.h b/deps/v8/src/mips/assembler-mips-inl.h index 2ba9760e2ab..0788e73ef69 100644 --- a/deps/v8/src/mips/assembler-mips-inl.h +++ b/deps/v8/src/mips/assembler-mips-inl.h @@ -133,7 +133,7 @@ Object* RelocInfo::target_object() { } -Handle<Object> RelocInfo::target_object_handle(Assembler *origin) { +Handle<Object> RelocInfo::target_object_handle(Assembler* origin) { ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); return Handle<Object>(reinterpret_cast<Object**>( Assembler::target_address_at(pc_))); diff --git a/deps/v8/src/mips/assembler-mips.cc b/deps/v8/src/mips/assembler-mips.cc index e933181d415..85b6ed802a2 100644 --- a/deps/v8/src/mips/assembler-mips.cc +++ b/deps/v8/src/mips/assembler-mips.cc @@ -301,7 +301,7 @@ Assembler::Assembler(Isolate* arg_isolate, void* buffer, int buffer_size) own_buffer_ = false; } - // Setup buffer pointers. + // Set up buffer pointers. ASSERT(buffer_ != NULL); pc_ = buffer_; reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); @@ -337,7 +337,7 @@ Assembler::~Assembler() { void Assembler::GetCode(CodeDesc* desc) { ASSERT(pc_ <= reloc_info_writer.pos()); // No overlap. - // Setup code descriptor. + // Set up code descriptor. desc->buffer = buffer_; desc->buffer_size = buffer_size_; desc->instr_size = pc_offset(); @@ -1970,7 +1970,7 @@ void Assembler::GrowBuffer() { } CHECK_GT(desc.buffer_size, 0); // No overflow. - // Setup new buffer. + // Set up new buffer. desc.buffer = NewArray<byte>(desc.buffer_size); desc.instr_size = pc_offset(); diff --git a/deps/v8/src/mips/builtins-mips.cc b/deps/v8/src/mips/builtins-mips.cc index 46a912bd596..9e108c9d1f4 100644 --- a/deps/v8/src/mips/builtins-mips.cc +++ b/deps/v8/src/mips/builtins-mips.cc @@ -339,7 +339,7 @@ static void ArrayNativeCode(MacroAssembler* masm, t1, call_generic_code); __ IncrementCounter(counters->array_function_native(), 1, a3, t0); - // Setup return value, remove receiver from stack and return. + // Set up return value, remove receiver from stack and return. __ mov(v0, a2); __ Addu(sp, sp, Operand(kPointerSize)); __ Ret(); @@ -382,7 +382,7 @@ static void ArrayNativeCode(MacroAssembler* masm, call_generic_code); __ IncrementCounter(counters->array_function_native(), 1, a2, t0); - // Setup return value, remove receiver and argument from stack and return. + // Set up return value, remove receiver and argument from stack and return. __ mov(v0, a3); __ Addu(sp, sp, Operand(2 * kPointerSize)); __ Ret(); @@ -981,10 +981,10 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, // sp[4]: number of arguments (smi-tagged) __ lw(a3, MemOperand(sp, 4 * kPointerSize)); - // Setup pointer to last argument. + // Set up pointer to last argument. __ Addu(a2, fp, Operand(StandardFrameConstants::kCallerSPOffset)); - // Setup number of arguments for function call below. + // Set up number of arguments for function call below. __ srl(a0, a3, kSmiTagSize); // Copy arguments and receiver to the expression stack. @@ -1114,10 +1114,7 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, // Set up the context from the function argument. __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); - // Set up the roots register. - ExternalReference roots_array_start = - ExternalReference::roots_array_start(masm->isolate()); - __ li(s6, Operand(roots_array_start)); + __ InitializeRootRegister(); // Push the function and the receiver onto the stack. __ Push(a1, a2); diff --git a/deps/v8/src/mips/code-stubs-mips.cc b/deps/v8/src/mips/code-stubs-mips.cc index 3e811bd7cbd..57091ef60bd 100644 --- a/deps/v8/src/mips/code-stubs-mips.cc +++ b/deps/v8/src/mips/code-stubs-mips.cc @@ -157,13 +157,13 @@ void FastNewContextStub::Generate(MacroAssembler* masm) { // Load the function from the stack. __ lw(a3, MemOperand(sp, 0)); - // Setup the object header. + // Set up the object header. __ LoadRoot(a2, Heap::kFunctionContextMapRootIndex); __ sw(a2, FieldMemOperand(v0, HeapObject::kMapOffset)); __ li(a2, Operand(Smi::FromInt(length))); __ sw(a2, FieldMemOperand(v0, FixedArray::kLengthOffset)); - // Setup the fixed slots. + // Set up the fixed slots. __ li(a1, Operand(Smi::FromInt(0))); __ sw(a3, MemOperand(v0, Context::SlotOffset(Context::CLOSURE_INDEX))); __ sw(cp, MemOperand(v0, Context::SlotOffset(Context::PREVIOUS_INDEX))); @@ -208,7 +208,7 @@ void FastNewBlockContextStub::Generate(MacroAssembler* masm) { // Load the serialized scope info from the stack. __ lw(a1, MemOperand(sp, 1 * kPointerSize)); - // Setup the object header. + // Set up the object header. __ LoadRoot(a2, Heap::kBlockContextMapRootIndex); __ sw(a2, FieldMemOperand(v0, HeapObject::kMapOffset)); __ li(a2, Operand(Smi::FromInt(length))); @@ -229,7 +229,7 @@ void FastNewBlockContextStub::Generate(MacroAssembler* masm) { __ lw(a3, ContextOperand(a3, Context::CLOSURE_INDEX)); __ bind(&after_sentinel); - // Setup the fixed slots. + // Set up the fixed slots. __ sw(a3, ContextOperand(v0, Context::CLOSURE_INDEX)); __ sw(cp, ContextOperand(v0, Context::PREVIOUS_INDEX)); __ sw(a1, ContextOperand(v0, Context::EXTENSION_INDEX)); @@ -726,7 +726,7 @@ void FloatingPointHelper::ConvertIntToDouble(MacroAssembler* masm, __ Subu(int_scratch, zero_reg, int_scratch); __ bind(&skip_sub); - // Get mantisssa[51:20]. + // Get mantissa[51:20]. // Get the position of the first set bit. __ clz(dst1, int_scratch); @@ -971,7 +971,7 @@ void FloatingPointHelper::DoubleIs32BitInteger(MacroAssembler* masm, // non zero bits left. So we need the (30 - exponent) last bits of the // 31 higher bits of the mantissa to be null. // Because bits [21:0] are null, we can check instead that the - // (32 - exponent) last bits of the 32 higher bits of the mantisssa are null. + // (32 - exponent) last bits of the 32 higher bits of the mantissa are null. // Get the 32 higher bits of the mantissa in dst. __ Ext(dst, @@ -4005,7 +4005,7 @@ void CEntryStub::Generate(MacroAssembler* masm) { FrameScope scope(masm, StackFrame::MANUAL); __ EnterExitFrame(save_doubles_); - // Setup argc and the builtin function in callee-saved registers. + // Set up argc and the builtin function in callee-saved registers. __ mov(s0, a0); __ mov(s2, a1); @@ -4097,7 +4097,7 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { isolate))); __ lw(t0, MemOperand(t0)); __ Push(t3, t2, t1, t0); - // Setup frame pointer for the frame to be pushed. + // Set up frame pointer for the frame to be pushed. __ addiu(fp, sp, -EntryFrameConstants::kCallerFPOffset); // Registers: @@ -4584,7 +4584,7 @@ void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) { __ sw(a3, FieldMemOperand(v0, i)); } - // Setup the callee in-object property. + // Set up the callee in-object property. STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); __ lw(a3, MemOperand(sp, 2 * kPointerSize)); const int kCalleeOffset = JSObject::kHeaderSize + @@ -4597,7 +4597,7 @@ void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) { Heap::kArgumentsLengthIndex * kPointerSize; __ sw(a2, FieldMemOperand(v0, kLengthOffset)); - // Setup the elements pointer in the allocated arguments object. + // Set up the elements pointer in the allocated arguments object. // If we allocated a parameter map, t0 will point there, otherwise // it will point to the backing store. __ Addu(t0, v0, Operand(Heap::kArgumentsObjectSize)); @@ -4699,7 +4699,7 @@ void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) { __ Ret(); // Do the runtime call to allocate the arguments object. - // a2 = argument count (taggged) + // a2 = argument count (tagged) __ bind(&runtime); __ sw(a2, MemOperand(sp, 0 * kPointerSize)); // Patch argument count. __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); @@ -4774,7 +4774,7 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { // Get the parameters pointer from the stack. __ lw(a2, MemOperand(sp, 1 * kPointerSize)); - // Setup the elements pointer in the allocated arguments object and + // Set up the elements pointer in the allocated arguments object and // initialize the header in the elements fixed array. __ Addu(t0, v0, Operand(Heap::kArgumentsObjectSizeStrict)); __ sw(t0, FieldMemOperand(v0, JSObject::kElementsOffset)); @@ -4786,7 +4786,7 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { // Copy the fixed array slots. Label loop; - // Setup t0 to point to the first array slot. + // Set up t0 to point to the first array slot. __ Addu(t0, t0, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); __ bind(&loop); // Pre-decrement a2 with kPointerSize on each iteration. @@ -5425,7 +5425,7 @@ void CallFunctionStub::Generate(MacroAssembler* masm) { // of the original receiver from the call site). __ bind(&non_function); __ sw(a1, MemOperand(sp, argc_ * kPointerSize)); - __ li(a0, Operand(argc_)); // Setup the number of arguments. + __ li(a0, Operand(argc_)); // Set up the number of arguments. __ mov(a2, zero_reg); __ GetBuiltinEntry(a3, Builtins::CALL_NON_FUNCTION); __ SetCallKind(t1, CALL_AS_METHOD); @@ -5927,7 +5927,7 @@ void StringHelper::GenerateHashInit(MacroAssembler* masm, Register hash, Register character) { // hash = seed + character + ((seed + character) << 10); - __ LoadRoot(hash, Heap::kStringHashSeedRootIndex); + __ LoadRoot(hash, Heap::kHashSeedRootIndex); // Untag smi seed and add the character. __ SmiUntag(hash); __ addu(hash, hash, character); @@ -5954,7 +5954,7 @@ void StringHelper::GenerateHashAddCharacter(MacroAssembler* masm, void StringHelper::GenerateHashGetHash(MacroAssembler* masm, - Register hash) { + Register hash) { // hash += hash << 3; __ sll(at, hash, 3); __ addu(hash, hash, at); @@ -5965,12 +5965,11 @@ void StringHelper::GenerateHashGetHash(MacroAssembler* masm, __ sll(at, hash, 15); __ addu(hash, hash, at); - uint32_t kHashShiftCutOffMask = (1 << (32 - String::kHashShift)) - 1; - __ li(at, Operand(kHashShiftCutOffMask)); + __ li(at, Operand(String::kHashBitMask)); __ and_(hash, hash, at); // if (hash == 0) hash = 27; - __ ori(at, zero_reg, 27); + __ ori(at, zero_reg, StringHasher::kZeroHash); __ movz(hash, at, hash); } diff --git a/deps/v8/src/mips/constants-mips.h b/deps/v8/src/mips/constants-mips.h index 4f486c1c04e..210becb449f 100644 --- a/deps/v8/src/mips/constants-mips.h +++ b/deps/v8/src/mips/constants-mips.h @@ -125,7 +125,7 @@ class Registers { struct RegisterAlias { int reg; - const char *name; + const char* name; }; static const int32_t kMaxValue = 0x7fffffff; @@ -147,7 +147,7 @@ class FPURegisters { struct RegisterAlias { int creg; - const char *name; + const char* name; }; private: diff --git a/deps/v8/src/mips/cpu-mips.cc b/deps/v8/src/mips/cpu-mips.cc index 26e95fb24c5..a1e062c803d 100644 --- a/deps/v8/src/mips/cpu-mips.cc +++ b/deps/v8/src/mips/cpu-mips.cc @@ -47,7 +47,7 @@ namespace v8 { namespace internal { -void CPU::Setup() { +void CPU::SetUp() { CpuFeatures::Probe(); } diff --git a/deps/v8/src/mips/deoptimizer-mips.cc b/deps/v8/src/mips/deoptimizer-mips.cc index a27c61cb2da..44af3d7b294 100644 --- a/deps/v8/src/mips/deoptimizer-mips.cc +++ b/deps/v8/src/mips/deoptimizer-mips.cc @@ -326,7 +326,7 @@ void Deoptimizer::DoComputeOsrOutputFrame() { output_[0] = input_; output_[0]->SetPc(reinterpret_cast<uint32_t>(from_)); } else { - // Setup the frame pointer and the context pointer. + // Set up the frame pointer and the context pointer. output_[0]->SetRegister(fp.code(), input_->GetRegister(fp.code())); output_[0]->SetRegister(cp.code(), input_->GetRegister(cp.code())); @@ -733,10 +733,7 @@ void Deoptimizer::EntryGenerator::Generate() { } } - // Set up the roots register. - ExternalReference roots_array_start = - ExternalReference::roots_array_start(isolate); - __ li(roots, Operand(roots_array_start)); + __ InitializeRootRegister(); __ pop(at); // Get continuation, leave pc on stack. __ pop(ra); diff --git a/deps/v8/src/mips/full-codegen-mips.cc b/deps/v8/src/mips/full-codegen-mips.cc index 1e950e5f510..7394077f0ae 100644 --- a/deps/v8/src/mips/full-codegen-mips.cc +++ b/deps/v8/src/mips/full-codegen-mips.cc @@ -1017,7 +1017,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ lw(a1, FieldMemOperand(a1, DescriptorArray::kEnumerationIndexOffset)); __ lw(a2, FieldMemOperand(a1, DescriptorArray::kEnumCacheBridgeCacheOffset)); - // Setup the four remaining stack slots. + // Set up the four remaining stack slots. __ push(v0); // Map. __ lw(a1, FieldMemOperand(a2, FixedArray::kLengthOffset)); __ li(a0, Operand(Smi::FromInt(0))); diff --git a/deps/v8/src/mips/lithium-codegen-mips.cc b/deps/v8/src/mips/lithium-codegen-mips.cc index 06e886c6bb1..de6400708f6 100644 --- a/deps/v8/src/mips/lithium-codegen-mips.cc +++ b/deps/v8/src/mips/lithium-codegen-mips.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -2794,7 +2794,7 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function, __ lw(at, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); __ Call(at); - // Setup deoptimization. + // Set up deoptimization. RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); // Restore context. @@ -3095,6 +3095,27 @@ void LCodeGen::DoPower(LPower* instr) { } +void LCodeGen::DoRandom(LRandom* instr) { + // Having marked this instruction as a call we can use any + // registers. + ASSERT(ToDoubleRegister(instr->result()).is(f0)); + ASSERT(ToRegister(instr->InputAt(0)).is(a0)); + + __ PrepareCallCFunction(1, a1); + __ lw(a0, FieldMemOperand(a0, GlobalObject::kGlobalContextOffset)); + __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); + + // 0x41300000 is the top half of 1.0 x 2^20 as a double. + __ li(a2, Operand(0x41300000)); + // Move 0x41300000xxxxxxxx (x = random bits in v0) to FPU. + __ Move(f12, v0, a2); + // Move 0x4130000000000000 to FPU. + __ Move(f14, zero_reg, a2); + // Subtract to get the result. + __ sub_d(f0, f12, f14); +} + + void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { ASSERT(ToDoubleRegister(instr->result()).is(f4)); TranscendentalCacheStub stub(TranscendentalCache::LOG, diff --git a/deps/v8/src/mips/lithium-codegen-mips.h b/deps/v8/src/mips/lithium-codegen-mips.h index 68a7c5b1aa8..2a54681990b 100644 --- a/deps/v8/src/mips/lithium-codegen-mips.h +++ b/deps/v8/src/mips/lithium-codegen-mips.h @@ -148,9 +148,9 @@ class LCodeGen BASE_EMBEDDED { Scope* scope() const { return scope_; } HGraph* graph() const { return chunk_->graph(); } - Register scratch0() { return lithiumScratchReg; } - Register scratch1() { return lithiumScratchReg2; } - DoubleRegister double_scratch0() { return lithiumScratchDouble; } + Register scratch0() { return kLithiumScratchReg; } + Register scratch1() { return kLithiumScratchReg2; } + DoubleRegister double_scratch0() { return kLithiumScratchDouble; } int GetNextEmittedBlock(int block); LInstruction* GetNextInstruction(); @@ -423,7 +423,7 @@ class LDeferredCode: public ZoneObject { virtual void Generate() = 0; virtual LInstruction* instr() = 0; - void SetExit(Label *exit) { external_exit_ = exit; } + void SetExit(Label* exit) { external_exit_ = exit; } Label* entry() { return &entry_; } Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; } int instruction_index() const { return instruction_index_; } diff --git a/deps/v8/src/mips/lithium-gap-resolver-mips.cc b/deps/v8/src/mips/lithium-gap-resolver-mips.cc index 2e5c64e7a2e..279a95ece49 100644 --- a/deps/v8/src/mips/lithium-gap-resolver-mips.cc +++ b/deps/v8/src/mips/lithium-gap-resolver-mips.cc @@ -33,8 +33,8 @@ namespace v8 { namespace internal { -static const Register kSavedValueRegister = lithiumScratchReg; -static const DoubleRegister kSavedDoubleValueRegister = lithiumScratchDouble; +static const Register kSavedValueRegister = kLithiumScratchReg; +static const DoubleRegister kSavedDoubleValueRegister = kLithiumScratchDouble; LGapResolver::LGapResolver(LCodeGen* owner) : cgen_(owner), diff --git a/deps/v8/src/mips/lithium-mips.cc b/deps/v8/src/mips/lithium-mips.cc index 634b7061089..b66b98f208e 100644 --- a/deps/v8/src/mips/lithium-mips.cc +++ b/deps/v8/src/mips/lithium-mips.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -1038,14 +1038,23 @@ LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { - HValue* v = instr->value(); - if (v->EmitAtUses()) { - HBasicBlock* successor = HConstant::cast(v)->ToBoolean() + HValue* value = instr->value(); + if (value->EmitAtUses()) { + HBasicBlock* successor = HConstant::cast(value)->ToBoolean() ? instr->FirstSuccessor() : instr->SecondSuccessor(); return new LGoto(successor->block_id()); } - return AssignEnvironment(new LBranch(UseRegister(v))); + + LBranch* result = new LBranch(UseRegister(value)); + // Tagged values that are not known smis or booleans require a + // deoptimization environment. + Representation rep = value->representation(); + HType type = value->type(); + if (rep.IsTagged() && !type.IsSmi() && !type.IsBoolean()) { + return AssignEnvironment(result); + } + return result; } @@ -1345,7 +1354,12 @@ LInstruction* LChunkBuilder::DoMul(HMul* instr) { } else { left = UseRegisterAtStart(instr->LeastConstantOperand()); } - return AssignEnvironment(DefineAsRegister(new LMulI(left, right, temp))); + LMulI* mul = new LMulI(left, right, temp); + if (instr->CheckFlag(HValue::kCanOverflow) || + instr->CheckFlag(HValue::kBailoutOnMinusZero)) { + AssignEnvironment(mul); + } + return DefineAsRegister(mul); } else if (instr->representation().IsDouble()) { return DoArithmeticD(Token::MUL, instr); @@ -1414,6 +1428,15 @@ LInstruction* LChunkBuilder::DoPower(HPower* instr) { } +LInstruction* LChunkBuilder::DoRandom(HRandom* instr) { + ASSERT(instr->representation().IsDouble()); + ASSERT(instr->global_object()->representation().IsTagged()); + LOperand* global_object = UseFixed(instr->global_object(), a0); + LRandom* result = new LRandom(global_object); + return MarkAsCall(DefineFixedDouble(result, f0), instr); +} + + LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) { Representation r = instr->GetInputRepresentation(); ASSERT(instr->left()->representation().IsTagged()); @@ -1558,7 +1581,7 @@ LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) { LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) { LOperand* object = UseRegister(instr->value()); LValueOf* result = new LValueOf(object, TempRegister()); - return AssignEnvironment(DefineAsRegister(result)); + return DefineAsRegister(result); } @@ -1877,7 +1900,8 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement( LOperand* obj = UseRegisterAtStart(instr->object()); LOperand* key = UseRegisterAtStart(instr->key()); LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key); - return AssignEnvironment(DefineAsRegister(result)); + if (instr->RequiresHoleCheck()) AssignEnvironment(result); + return DefineAsRegister(result); } diff --git a/deps/v8/src/mips/lithium-mips.h b/deps/v8/src/mips/lithium-mips.h index da59dd8b0c2..069a0251fda 100644 --- a/deps/v8/src/mips/lithium-mips.h +++ b/deps/v8/src/mips/lithium-mips.h @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -141,6 +141,7 @@ class LCodeGen; V(Parameter) \ V(Power) \ V(PushArgument) \ + V(Random) \ V(RegExpLiteral) \ V(Return) \ V(ShiftI) \ @@ -1026,6 +1027,17 @@ class LPower: public LTemplateInstruction<1, 2, 0> { }; +class LRandom: public LTemplateInstruction<1, 1, 0> { + public: + explicit LRandom(LOperand* global_object) { + inputs_[0] = global_object; + } + + DECLARE_CONCRETE_INSTRUCTION(Random, "random") + DECLARE_HYDROGEN_ACCESSOR(Random) +}; + + class LArithmeticD: public LTemplateInstruction<1, 2, 0> { public: LArithmeticD(Token::Value op, LOperand* left, LOperand* right) diff --git a/deps/v8/src/mips/macro-assembler-mips.cc b/deps/v8/src/mips/macro-assembler-mips.cc index cdacbf3c0d8..4517fe18188 100644 --- a/deps/v8/src/mips/macro-assembler-mips.cc +++ b/deps/v8/src/mips/macro-assembler-mips.cc @@ -252,6 +252,12 @@ void MacroAssembler::RecordWrite(Register object, // registers are cp. ASSERT(!address.is(cp) && !value.is(cp)); + if (emit_debug_code()) { + lw(at, MemOperand(address)); + Assert( + eq, "Wrong address or value passed to RecordWrite", at, Operand(value)); + } + Label done; if (smi_check == INLINE_SMI_CHECK) { @@ -297,7 +303,7 @@ void MacroAssembler::RememberedSetHelper(Register object, // For debug tests. SaveFPRegsMode fp_mode, RememberedSetFinalAction and_then) { Label done; - if (FLAG_debug_code) { + if (emit_debug_code()) { Label ok; JumpIfNotInNewSpace(object, scratch, &ok); stop("Remembered set pointer is in new space"); @@ -409,6 +415,44 @@ void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, } +void MacroAssembler::GetNumberHash(Register reg0, Register scratch) { + // First of all we assign the hash seed to scratch. + LoadRoot(scratch, Heap::kHashSeedRootIndex); + SmiUntag(scratch); + + // Xor original key with a seed. + xor_(reg0, reg0, scratch); + + // Compute the hash code from the untagged key. This must be kept in sync + // with ComputeIntegerHash in utils.h. + // + // hash = ~hash + (hash << 15); + nor(scratch, reg0, zero_reg); + sll(at, reg0, 15); + addu(reg0, scratch, at); + + // hash = hash ^ (hash >> 12); + srl(at, reg0, 12); + xor_(reg0, reg0, at); + + // hash = hash + (hash << 2); + sll(at, reg0, 2); + addu(reg0, reg0, at); + + // hash = hash ^ (hash >> 4); + srl(at, reg0, 4); + xor_(reg0, reg0, at); + + // hash = hash * 2057; + li(scratch, Operand(2057)); + mul(reg0, reg0, scratch); + + // hash = hash ^ (hash >> 16); + srl(at, reg0, 16); + xor_(reg0, reg0, at); +} + + void MacroAssembler::LoadFromNumberDictionary(Label* miss, Register elements, Register key, @@ -440,36 +484,10 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, // at - Temporary (avoid MacroAssembler instructions also using 'at'). Label done; - // Compute the hash code from the untagged key. This must be kept in sync - // with ComputeIntegerHash in utils.h. - // - // hash = ~hash + (hash << 15); - nor(reg1, reg0, zero_reg); - sll(at, reg0, 15); - addu(reg0, reg1, at); - - // hash = hash ^ (hash >> 12); - srl(at, reg0, 12); - xor_(reg0, reg0, at); - - // hash = hash + (hash << 2); - sll(at, reg0, 2); - addu(reg0, reg0, at); - - // hash = hash ^ (hash >> 4); - srl(at, reg0, 4); - xor_(reg0, reg0, at); - - // hash = hash * 2057; - li(reg1, Operand(2057)); - mul(reg0, reg0, reg1); - - // hash = hash ^ (hash >> 16); - srl(at, reg0, 16); - xor_(reg0, reg0, at); + GetNumberHash(reg0, reg1); // Compute the capacity mask. - lw(reg1, FieldMemOperand(elements, NumberDictionary::kCapacityOffset)); + lw(reg1, FieldMemOperand(elements, SeededNumberDictionary::kCapacityOffset)); sra(reg1, reg1, kSmiTagSize); Subu(reg1, reg1, Operand(1)); @@ -480,12 +498,12 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, mov(reg2, reg0); // Compute the masked index: (hash + i + i * i) & mask. if (i > 0) { - Addu(reg2, reg2, Operand(NumberDictionary::GetProbeOffset(i))); + Addu(reg2, reg2, Operand(SeededNumberDictionary::GetProbeOffset(i))); } and_(reg2, reg2, reg1); // Scale the index by multiplying by the element size. - ASSERT(NumberDictionary::kEntrySize == 3); + ASSERT(SeededNumberDictionary::kEntrySize == 3); sll(at, reg2, 1); // 2x. addu(reg2, reg2, at); // reg2 = reg2 * 3. @@ -493,7 +511,7 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, sll(at, reg2, kPointerSizeLog2); addu(reg2, elements, at); - lw(at, FieldMemOperand(reg2, NumberDictionary::kElementsStartOffset)); + lw(at, FieldMemOperand(reg2, SeededNumberDictionary::kElementsStartOffset)); if (i != kProbes - 1) { Branch(&done, eq, key, Operand(at)); } else { @@ -505,14 +523,14 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, // Check that the value is a normal property. // reg2: elements + (index * kPointerSize). const int kDetailsOffset = - NumberDictionary::kElementsStartOffset + 2 * kPointerSize; + SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize; lw(reg1, FieldMemOperand(reg2, kDetailsOffset)); And(at, reg1, Operand(Smi::FromInt(PropertyDetails::TypeField::kMask))); Branch(miss, ne, at, Operand(zero_reg)); // Get the value at the masked, scaled index and return. const int kValueOffset = - NumberDictionary::kElementsStartOffset + kPointerSize; + SeededNumberDictionary::kElementsStartOffset + kPointerSize; lw(result, FieldMemOperand(reg2, kValueOffset)); } @@ -4261,7 +4279,7 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) { void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) { - // Setup the frame structure on the stack. + // Set up the frame structure on the stack. STATIC_ASSERT(2 * kPointerSize == ExitFrameConstants::kCallerSPDisplacement); STATIC_ASSERT(1 * kPointerSize == ExitFrameConstants::kCallerPCOffset); STATIC_ASSERT(0 * kPointerSize == ExitFrameConstants::kCallerFPOffset); @@ -4279,7 +4297,7 @@ void MacroAssembler::EnterExitFrame(bool save_doubles, addiu(sp, sp, -4 * kPointerSize); sw(ra, MemOperand(sp, 3 * kPointerSize)); sw(fp, MemOperand(sp, 2 * kPointerSize)); - addiu(fp, sp, 2 * kPointerSize); // Setup new frame pointer. + addiu(fp, sp, 2 * kPointerSize); // Set up new frame pointer. if (emit_debug_code()) { sw(zero_reg, MemOperand(fp, ExitFrameConstants::kSPOffset)); @@ -4826,7 +4844,7 @@ void MacroAssembler::EnsureNotWhite( And(t8, mask_scratch, load_scratch); Branch(&done, ne, t8, Operand(zero_reg)); - if (FLAG_debug_code) { + if (emit_debug_code()) { // Check for impossible bit pattern. Label ok; // sll may overflow, making the check conservative. diff --git a/deps/v8/src/mips/macro-assembler-mips.h b/deps/v8/src/mips/macro-assembler-mips.h index bd5b94f57c6..eb9cf6e574d 100644 --- a/deps/v8/src/mips/macro-assembler-mips.h +++ b/deps/v8/src/mips/macro-assembler-mips.h @@ -53,13 +53,13 @@ class JumpTarget; // Register aliases. // cp is assumed to be a callee saved register. -const Register lithiumScratchReg = s3; // Scratch register. -const Register lithiumScratchReg2 = s4; // Scratch register. -const Register condReg = s5; // Simulated (partial) condition code for mips. -const Register roots = s6; // Roots array pointer. +const Register kLithiumScratchReg = s3; // Scratch register. +const Register kLithiumScratchReg2 = s4; // Scratch register. +const Register kCondReg = s5; // Simulated (partial) condition code for mips. +const Register kRootRegister = s6; // Roots array pointer. const Register cp = s7; // JavaScript context pointer. const Register fp = s8_fp; // Alias for fp. -const DoubleRegister lithiumScratchDouble = f30; // Double scratch register. +const DoubleRegister kLithiumScratchDouble = f30; // Double scratch register. // Flags used for the AllocateInNewSpace functions. enum AllocationFlags { @@ -405,6 +405,7 @@ class MacroAssembler: public Assembler { Register scratch, Label* miss); + void GetNumberHash(Register reg0, Register scratch); void LoadFromNumberDictionary(Label* miss, Register elements, @@ -789,11 +790,16 @@ class MacroAssembler: public Assembler { Register map, Register scratch); + void InitializeRootRegister() { + ExternalReference roots_array_start = + ExternalReference::roots_array_start(isolate()); + li(kRootRegister, Operand(roots_array_start)); + } // ------------------------------------------------------------------------- // JavaScript invokes. - // Setup call kind marking in t1. The method takes t1 as an + // Set up call kind marking in t1. The method takes t1 as an // explicit first parameter to make the code more readable at the // call sites. void SetCallKind(Register dst, CallKind kind); diff --git a/deps/v8/src/mips/simulator-mips.cc b/deps/v8/src/mips/simulator-mips.cc index f70775d86be..191c2cafd52 100644 --- a/deps/v8/src/mips/simulator-mips.cc +++ b/deps/v8/src/mips/simulator-mips.cc @@ -888,7 +888,7 @@ Simulator::Simulator(Isolate* isolate) : isolate_(isolate) { isolate_->set_simulator_i_cache(i_cache_); } Initialize(isolate); - // Setup simulator support first. Some of this information is needed to + // Set up simulator support first. Some of this information is needed to // setup the architecture state. stack_ = reinterpret_cast<char*>(malloc(stack_size_)); pc_modified_ = false; @@ -897,7 +897,7 @@ Simulator::Simulator(Isolate* isolate) : isolate_(isolate) { break_pc_ = NULL; break_instr_ = 0; - // Setup architecture state. + // Set up architecture state. // All registers are initialized to zero to start with. for (int i = 0; i < kNumSimuRegisters; i++) { registers_[i] = 0; @@ -1944,7 +1944,7 @@ void Simulator::DecodeTypeRegister(Instruction* instr) { // Next pc int32_t next_pc = 0; - // Setup the variables if needed before executing the instruction. + // Set up the variables if needed before executing the instruction. ConfigureTypeRegister(instr, alu_out, i64hilo, @@ -2711,7 +2711,7 @@ void Simulator::Execute() { int32_t Simulator::Call(byte* entry, int argument_count, ...) { va_list parameters; va_start(parameters, argument_count); - // Setup arguments. + // Set up arguments. // First four arguments passed in registers. ASSERT(argument_count >= 4); @@ -2758,7 +2758,7 @@ int32_t Simulator::Call(byte* entry, int argument_count, ...) { int32_t sp_val = get_register(sp); int32_t fp_val = get_register(fp); - // Setup the callee-saved registers with a known value. To be able to check + // Set up the callee-saved registers with a known value. To be able to check // that they are preserved properly across JS execution. int32_t callee_saved_value = icount_; set_register(s0, callee_saved_value); diff --git a/deps/v8/src/mips/stub-cache-mips.cc b/deps/v8/src/mips/stub-cache-mips.cc index a94e277a50b..bf01861a613 100644 --- a/deps/v8/src/mips/stub-cache-mips.cc +++ b/deps/v8/src/mips/stub-cache-mips.cc @@ -1173,7 +1173,7 @@ void StubCompiler::GenerateLoadCallback(Handle<JSObject> object, __ EnterExitFrame(false, kApiStackSpace); // Create AccessorInfo instance on the stack above the exit frame with - // scratch2 (internal::Object **args_) as the data. + // scratch2 (internal::Object** args_) as the data. __ sw(a2, MemOperand(sp, kPointerSize)); // a2 (second argument - see note above) = AccessorInfo& __ Addu(a2, sp, kPointerSize); @@ -2430,7 +2430,7 @@ Handle<Code> CallStubCompiler::CompileCallGlobal( __ sw(a3, MemOperand(sp, argc * kPointerSize)); } - // Setup the context (function already in r1). + // Set up the context (function already in r1). __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); // Jump to the cached code (tail call). diff --git a/deps/v8/src/objects-debug.cc b/deps/v8/src/objects-debug.cc index 64bda9473f6..5c68ddff7fc 100644 --- a/deps/v8/src/objects-debug.cc +++ b/deps/v8/src/objects-debug.cc @@ -602,6 +602,13 @@ void AccessorInfo::AccessorInfoVerify() { } +void AccessorPair::AccessorPairVerify() { + CHECK(IsAccessorPair()); + VerifyPointer(getter()); + VerifyPointer(setter()); +} + + void AccessCheckInfo::AccessCheckInfoVerify() { CHECK(IsAccessCheckInfo()); VerifyPointer(named_callback()); @@ -739,7 +746,7 @@ void JSObject::IncrementSpillStatistics(SpillInformation* info) { break; } case DICTIONARY_ELEMENTS: { - NumberDictionary* dict = element_dictionary(); + SeededNumberDictionary* dict = element_dictionary(); info->number_of_slow_used_elements_ += dict->NumberOfElements(); info->number_of_slow_unused_elements_ += dict->Capacity() - dict->NumberOfElements(); diff --git a/deps/v8/src/objects-inl.h b/deps/v8/src/objects-inl.h index c5cf060829f..2e9ccc1fa2e 100644 --- a/deps/v8/src/objects-inl.h +++ b/deps/v8/src/objects-inl.h @@ -1725,7 +1725,7 @@ void FixedDoubleArray::Initialize(FixedArray* from) { } -void FixedDoubleArray::Initialize(NumberDictionary* from) { +void FixedDoubleArray::Initialize(SeededNumberDictionary* from) { int offset = kHeaderSize; for (int current = 0; current < length(); ++current) { WRITE_DOUBLE_FIELD(this, offset, hole_nan_as_double()); @@ -2057,7 +2057,7 @@ int HashTable<Shape, Key>::FindEntry(Key key) { template<typename Shape, typename Key> int HashTable<Shape, Key>::FindEntry(Isolate* isolate, Key key) { uint32_t capacity = Capacity(); - uint32_t entry = FirstProbe(Shape::Hash(key), capacity); + uint32_t entry = FirstProbe(HashTable<Shape, Key>::Hash(key), capacity); uint32_t count = 1; // EnsureCapacity will guarantee the hash table is never full. while (true) { @@ -2072,14 +2072,14 @@ int HashTable<Shape, Key>::FindEntry(Isolate* isolate, Key key) { } -bool NumberDictionary::requires_slow_elements() { +bool SeededNumberDictionary::requires_slow_elements() { Object* max_index_object = get(kMaxNumberKeyIndex); if (!max_index_object->IsSmi()) return false; return 0 != (Smi::cast(max_index_object)->value() & kRequiresSlowElementsMask); } -uint32_t NumberDictionary::max_number_key() { +uint32_t SeededNumberDictionary::max_number_key() { ASSERT(!requires_slow_elements()); Object* max_index_object = get(kMaxNumberKeyIndex); if (!max_index_object->IsSmi()) return 0; @@ -2087,7 +2087,7 @@ uint32_t NumberDictionary::max_number_key() { return value >> kRequiresSlowElementsTagSize; } -void NumberDictionary::set_requires_slow_elements() { +void SeededNumberDictionary::set_requires_slow_elements() { set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask)); } @@ -3386,6 +3386,9 @@ ACCESSORS(AccessorInfo, data, Object, kDataOffset) ACCESSORS(AccessorInfo, name, Object, kNameOffset) ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset) +ACCESSORS(AccessorPair, getter, Object, kGetterOffset) +ACCESSORS(AccessorPair, setter, Object, kSetterOffset) + ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset) ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset) ACCESSORS(AccessCheckInfo, data, Object, kDataOffset) @@ -4296,9 +4299,9 @@ StringDictionary* JSObject::property_dictionary() { } -NumberDictionary* JSObject::element_dictionary() { +SeededNumberDictionary* JSObject::element_dictionary() { ASSERT(HasDictionaryElements()); - return NumberDictionary::cast(elements()); + return SeededNumberDictionary::cast(elements()); } @@ -4328,7 +4331,7 @@ StringHasher::StringHasher(int length, uint32_t seed) is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize), is_first_char_(true), is_valid_(true) { - ASSERT(FLAG_randomize_string_hashes || raw_running_hash_ == 0); + ASSERT(FLAG_randomize_hashes || raw_running_hash_ == 0); } @@ -4535,16 +4538,27 @@ bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) { } -uint32_t NumberDictionaryShape::Hash(uint32_t key) { - return ComputeIntegerHash(key); +uint32_t UnseededNumberDictionaryShape::Hash(uint32_t key) { + return ComputeIntegerHash(key, 0); } -uint32_t NumberDictionaryShape::HashForObject(uint32_t key, Object* other) { +uint32_t UnseededNumberDictionaryShape::HashForObject(uint32_t key, + Object* other) { ASSERT(other->IsNumber()); - return ComputeIntegerHash(static_cast<uint32_t>(other->Number())); + return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), 0); +} + +uint32_t SeededNumberDictionaryShape::SeededHash(uint32_t key, uint32_t seed) { + return ComputeIntegerHash(key, seed); } +uint32_t SeededNumberDictionaryShape::SeededHashForObject(uint32_t key, + uint32_t seed, + Object* other) { + ASSERT(other->IsNumber()); + return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), seed); +} MaybeObject* NumberDictionaryShape::AsObject(uint32_t key) { return Isolate::Current()->heap()->NumberFromUint32(key); diff --git a/deps/v8/src/objects-printer.cc b/deps/v8/src/objects-printer.cc index 4b5d049f51b..e558e583e49 100644 --- a/deps/v8/src/objects-printer.cc +++ b/deps/v8/src/objects-printer.cc @@ -786,6 +786,15 @@ void AccessorInfo::AccessorInfoPrint(FILE* out) { } +void AccessorPair::AccessorPairPrint(FILE* out) { + HeapObject::PrintHeader(out, "AccessorPair"); + PrintF(out, "\n - getter: "); + getter()->ShortPrint(out); + PrintF(out, "\n - setter: "); + setter()->ShortPrint(out); +} + + void AccessCheckInfo::AccessCheckInfoPrint(FILE* out) { HeapObject::PrintHeader(out, "AccessCheckInfo"); PrintF(out, "\n - named_callback: "); diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc index 36879099e0b..abeeec9e2fe 100644 --- a/deps/v8/src/objects.cc +++ b/deps/v8/src/objects.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -246,8 +246,8 @@ MaybeObject* JSObject::GetPropertyWithCallback(Object* receiver, } // __defineGetter__ callback - if (structure->IsFixedArray()) { - Object* getter = FixedArray::cast(structure)->get(kGetterIndex); + if (structure->IsAccessorPair()) { + Object* getter = AccessorPair::cast(structure)->getter(); if (getter->IsSpecFunction()) { // TODO(rossberg): nicer would be to cast to some JSCallable here... return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter)); @@ -485,6 +485,16 @@ Object* JSObject::SetNormalizedProperty(LookupResult* result, Object* value) { } +Handle<Object> JSObject::SetNormalizedProperty(Handle<JSObject> object, + Handle<String> key, + Handle<Object> value, + PropertyDetails details) { + CALL_HEAP_FUNCTION(object->GetIsolate(), + object->SetNormalizedProperty(*key, *value, details), + Object); +} + + MaybeObject* JSObject::SetNormalizedProperty(String* name, Object* value, PropertyDetails details) { @@ -1961,6 +1971,17 @@ MaybeObject* JSObject::SetPropertyWithInterceptor( } +Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, + Handle<String> key, + Handle<Object> value, + PropertyAttributes attributes, + StrictModeFlag strict_mode) { + CALL_HEAP_FUNCTION(object->GetIsolate(), + object->SetProperty(*key, *value, attributes, strict_mode), + Object); +} + + MaybeObject* JSReceiver::SetProperty(String* name, Object* value, PropertyAttributes attributes, @@ -2018,8 +2039,8 @@ MaybeObject* JSObject::SetPropertyWithCallback(Object* structure, return *value_handle; } - if (structure->IsFixedArray()) { - Object* setter = FixedArray::cast(structure)->get(kSetterIndex); + if (structure->IsAccessorPair()) { + Object* setter = AccessorPair::cast(structure)->setter(); if (setter->IsSpecFunction()) { // TODO(rossberg): nicer would be to cast to some JSCallable here... return SetPropertyWithDefinedSetter(JSReceiver::cast(setter), value); @@ -2107,9 +2128,10 @@ MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes( if (!JSObject::cast(pt)->HasDictionaryElements()) { continue; } - NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary(); + SeededNumberDictionary* dictionary = + JSObject::cast(pt)->element_dictionary(); int entry = dictionary->FindEntry(index); - if (entry != NumberDictionary::kNotFound) { + if (entry != SeededNumberDictionary::kNotFound) { PropertyDetails details = dictionary->DetailsAt(entry); if (details.type() == CALLBACKS) { *found = true; @@ -2342,7 +2364,9 @@ Object* Map::GetDescriptorContents(String* sentinel_name, if (details.type() == ELEMENTS_TRANSITION) { return descriptors->GetValue(index); } else { - *safe_to_add_transition = false; + if (safe_to_add_transition != NULL) { + *safe_to_add_transition = false; + } } } return NULL; @@ -3024,6 +3048,18 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* result, // Note that this method cannot be used to set the prototype of a function // because ConvertDescriptorToField() which is called in "case CALLBACKS:" // doesn't handle function prototypes correctly. +Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes( + Handle<JSObject> object, + Handle<String> key, + Handle<Object> value, + PropertyAttributes attributes) { + CALL_HEAP_FUNCTION( + object->GetIsolate(), + object->SetLocalPropertyIgnoreAttributes(*key, *value, attributes), + Object); +} + + MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( String* name, Object* value, @@ -3314,6 +3350,15 @@ MaybeObject* JSObject::UpdateMapCodeCache(String* name, Code* code) { } +void JSObject::NormalizeProperties(Handle<JSObject> object, + PropertyNormalizationMode mode, + int expected_additional_properties) { + CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), + object->NormalizeProperties( + mode, expected_additional_properties)); +} + + MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode, int expected_additional_properties) { if (!HasFastProperties()) return this; @@ -3436,6 +3481,14 @@ MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode, } +void JSObject::TransformToFastProperties(Handle<JSObject> object, + int unused_property_fields) { + CALL_HEAP_FUNCTION_VOID( + object->GetIsolate(), + object->TransformToFastProperties(unused_property_fields)); +} + + MaybeObject* JSObject::TransformToFastProperties(int unused_property_fields) { if (HasFastProperties()) return this; ASSERT(!IsGlobalObject()); @@ -3444,6 +3497,14 @@ MaybeObject* JSObject::TransformToFastProperties(int unused_property_fields) { } +Handle<SeededNumberDictionary> JSObject::NormalizeElements( + Handle<JSObject> object) { + CALL_HEAP_FUNCTION(object->GetIsolate(), + object->NormalizeElements(), + SeededNumberDictionary); +} + + MaybeObject* JSObject::NormalizeElements() { ASSERT(!HasExternalArrayElements()); @@ -3468,11 +3529,11 @@ MaybeObject* JSObject::NormalizeElements() { int old_capacity = 0; int used_elements = 0; GetElementsCapacityAndUsage(&old_capacity, &used_elements); - NumberDictionary* dictionary = NULL; + SeededNumberDictionary* dictionary = NULL; { Object* object; - MaybeObject* maybe = NumberDictionary::Allocate(used_elements); + MaybeObject* maybe = SeededNumberDictionary::Allocate(used_elements); if (!maybe->ToObject(&object)) return maybe; - dictionary = NumberDictionary::cast(object); + dictionary = SeededNumberDictionary::cast(object); } // Copy the elements to the new backing store. @@ -3503,7 +3564,7 @@ MaybeObject* JSObject::NormalizeElements() { MaybeObject* maybe_result = dictionary->AddNumberEntry(i, value, details); if (!maybe_result->ToObject(&result)) return maybe_result; - dictionary = NumberDictionary::cast(result); + dictionary = SeededNumberDictionary::cast(result); } } @@ -3560,6 +3621,14 @@ MaybeObject* JSObject::SetIdentityHash(Object* hash, CreationFlag flag) { } +int JSObject::GetIdentityHash(Handle<JSObject> obj) { + CALL_AND_RETRY(obj->GetIsolate(), + obj->GetIdentityHash(ALLOW_CREATION), + return Smi::cast(__object__)->value(), + return 0); +} + + MaybeObject* JSObject::GetIdentityHash(CreationFlag flag) { Object* stored_value = GetHiddenProperty(GetHeap()->identity_hash_symbol()); if (stored_value->IsSmi()) return stored_value; @@ -3612,6 +3681,15 @@ Object* JSObject::GetHiddenProperty(String* key) { } +Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> obj, + Handle<String> key, + Handle<Object> value) { + CALL_HEAP_FUNCTION(obj->GetIsolate(), + obj->SetHiddenProperty(*key, *value), + Object); +} + + MaybeObject* JSObject::SetHiddenProperty(String* key, Object* value) { if (IsJSGlobalProxy()) { // For a proxy, use the prototype as target object. @@ -3839,6 +3917,14 @@ MaybeObject* JSObject::DeleteElementWithInterceptor(uint32_t index) { } +Handle<Object> JSObject::DeleteElement(Handle<JSObject> obj, + uint32_t index) { + CALL_HEAP_FUNCTION(obj->GetIsolate(), + obj->DeleteElement(index, JSObject::NORMAL_DELETION), + Object); +} + + MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) { Isolate* isolate = GetIsolate(); // Check access rights if needed. @@ -3867,19 +3953,11 @@ MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) { } -MaybeObject* JSReceiver::DeleteProperty(String* name, DeleteMode mode) { - if (IsJSProxy()) { - return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode); - } - return JSObject::cast(this)->DeleteProperty(name, mode); -} - - -MaybeObject* JSReceiver::DeleteElement(uint32_t index, DeleteMode mode) { - if (IsJSProxy()) { - return JSProxy::cast(this)->DeleteElementWithHandler(index, mode); - } - return JSObject::cast(this)->DeleteElement(index, mode); +Handle<Object> JSObject::DeleteProperty(Handle<JSObject> obj, + Handle<String> prop) { + CALL_HEAP_FUNCTION(obj->GetIsolate(), + obj->DeleteProperty(*prop, JSObject::NORMAL_DELETION), + Object); } @@ -3940,6 +4018,22 @@ MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) { } +MaybeObject* JSReceiver::DeleteElement(uint32_t index, DeleteMode mode) { + if (IsJSProxy()) { + return JSProxy::cast(this)->DeleteElementWithHandler(index, mode); + } + return JSObject::cast(this)->DeleteElement(index, mode); +} + + +MaybeObject* JSReceiver::DeleteProperty(String* name, DeleteMode mode) { + if (IsJSProxy()) { + return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode); + } + return JSObject::cast(this)->DeleteProperty(name, mode); +} + + bool JSObject::ReferencesObjectFromElements(FixedArray* elements, ElementsKind kind, Object* object) { @@ -3954,7 +4048,8 @@ bool JSObject::ReferencesObjectFromElements(FixedArray* elements, if (!element->IsTheHole() && element == object) return true; } } else { - Object* key = NumberDictionary::cast(elements)->SlowReverseLookup(object); + Object* key = + SeededNumberDictionary::cast(elements)->SlowReverseLookup(object); if (!key->IsUndefined()) return true; } return false; @@ -4066,6 +4161,11 @@ bool JSObject::ReferencesObject(Object* obj) { } +Handle<Object> JSObject::PreventExtensions(Handle<JSObject> object) { + CALL_HEAP_FUNCTION(object->GetIsolate(), object->PreventExtensions(), Object); +} + + MaybeObject* JSObject::PreventExtensions() { Isolate* isolate = GetIsolate(); if (IsAccessCheckNeeded() && @@ -4095,9 +4195,9 @@ MaybeObject* JSObject::PreventExtensions() { } // If there are fast elements we normalize. - NumberDictionary* dictionary = NULL; + SeededNumberDictionary* dictionary = NULL; { MaybeObject* maybe = NormalizeElements(); - if (!maybe->To<NumberDictionary>(&dictionary)) return maybe; + if (!maybe->To<SeededNumberDictionary>(&dictionary)) return maybe; } ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); // Make sure that we never go back to fast case. @@ -4257,21 +4357,21 @@ void JSObject::LookupCallback(String* name, LookupResult* result) { // Search for a getter or setter in an elements dictionary and update its -// attributes. Returns either undefined if the element is non-deletable, or -// the getter/setter pair (fixed array) if there is an existing one, or the -// hole value if the element does not exist or is a normal non-getter/setter -// data element. -static Object* UpdateGetterSetterInDictionary(NumberDictionary* dictionary, - uint32_t index, - PropertyAttributes attributes, - Heap* heap) { +// attributes. Returns either undefined if the element is non-deletable, or the +// getter/setter pair if there is an existing one, or the hole value if the +// element does not exist or is a normal non-getter/setter data element. +static Object* UpdateGetterSetterInDictionary( + SeededNumberDictionary* dictionary, + uint32_t index, + PropertyAttributes attributes, + Heap* heap) { int entry = dictionary->FindEntry(index); - if (entry != NumberDictionary::kNotFound) { + if (entry != SeededNumberDictionary::kNotFound) { Object* result = dictionary->ValueAt(entry); PropertyDetails details = dictionary->DetailsAt(entry); // TODO(mstarzinger): We should check for details.IsDontDelete() here once // we only call into the runtime once to set both getter and setter. - if (details.type() == CALLBACKS && result->IsFixedArray()) { + if (details.type() == CALLBACKS && result->IsAccessorPair()) { if (details.attributes() != attributes) { dictionary->DetailsAtPut(entry, PropertyDetails(attributes, CALLBACKS, index)); @@ -4338,7 +4438,8 @@ MaybeObject* JSObject::DefineGetterSetter(String* name, if (probe == NULL || probe->IsTheHole()) { FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); if (arguments->IsDictionary()) { - NumberDictionary* dictionary = NumberDictionary::cast(arguments); + SeededNumberDictionary* dictionary = + SeededNumberDictionary::cast(arguments); probe = UpdateGetterSetterInDictionary(dictionary, index, attributes, @@ -4359,7 +4460,7 @@ MaybeObject* JSObject::DefineGetterSetter(String* name, if (result.type() == CALLBACKS) { Object* obj = result.GetCallbackObject(); // Need to preserve old getters/setters. - if (obj->IsFixedArray()) { + if (obj->IsAccessorPair()) { // Use set to update attributes. return SetPropertyCallback(name, obj, attributes); } @@ -4367,16 +4468,15 @@ MaybeObject* JSObject::DefineGetterSetter(String* name, } } - // Allocate the fixed array to hold getter and setter. - Object* structure; - { MaybeObject* maybe_structure = heap->AllocateFixedArray(2, TENURED); - if (!maybe_structure->ToObject(&structure)) return maybe_structure; + AccessorPair* accessors; + { MaybeObject* maybe_accessors = heap->AllocateAccessorPair(); + if (!maybe_accessors->To<AccessorPair>(&accessors)) return maybe_accessors; } if (is_element) { - return SetElementCallback(index, structure, attributes); + return SetElementCallback(index, accessors, attributes); } else { - return SetPropertyCallback(name, structure, attributes); + return SetPropertyCallback(name, accessors, attributes); } } @@ -4411,11 +4511,11 @@ MaybeObject* JSObject::SetElementCallback(uint32_t index, PropertyDetails details = PropertyDetails(attributes, CALLBACKS); // Normalize elements to make this operation simple. - NumberDictionary* dictionary = NULL; + SeededNumberDictionary* dictionary = NULL; { Object* result; MaybeObject* maybe = NormalizeElements(); if (!maybe->ToObject(&result)) return maybe; - dictionary = NumberDictionary::cast(result); + dictionary = SeededNumberDictionary::cast(result); } ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); @@ -4423,7 +4523,7 @@ MaybeObject* JSObject::SetElementCallback(uint32_t index, { Object* result; MaybeObject* maybe = dictionary->Set(index, structure, details); if (!maybe->ToObject(&result)) return maybe; - dictionary = NumberDictionary::cast(result); + dictionary = SeededNumberDictionary::cast(result); } dictionary->set_requires_slow_elements(); @@ -4512,12 +4612,16 @@ MaybeObject* JSObject::DefineAccessor(String* name, fun, attributes); } - Object* array; - { MaybeObject* maybe_array = DefineGetterSetter(name, attributes); - if (!maybe_array->ToObject(&array)) return maybe_array; + Object* accessors; + { MaybeObject* maybe_accessors = DefineGetterSetter(name, attributes); + if (!maybe_accessors->To<Object>(&accessors)) return maybe_accessors; + } + if (accessors->IsUndefined()) return accessors; + if (is_getter) { + AccessorPair::cast(accessors)->set_getter(fun); + } else { + AccessorPair::cast(accessors)->set_setter(fun); } - if (array->IsUndefined()) return array; - FixedArray::cast(array)->set(is_getter ? 0 : 1, fun); return this; } @@ -4621,11 +4725,6 @@ Object* JSObject::LookupAccessor(String* name, bool is_getter) { } // Make the lookup and include prototypes. - // Introducing constants below makes static constants usage purely static - // and avoids linker errors in debug build using gcc. - const int getter_index = kGetterIndex; - const int setter_index = kSetterIndex; - int accessor_index = is_getter ? getter_index : setter_index; uint32_t index = 0; if (name->AsArrayIndex(&index)) { for (Object* obj = this; @@ -4633,14 +4732,15 @@ Object* JSObject::LookupAccessor(String* name, bool is_getter) { obj = JSObject::cast(obj)->GetPrototype()) { JSObject* js_object = JSObject::cast(obj); if (js_object->HasDictionaryElements()) { - NumberDictionary* dictionary = js_object->element_dictionary(); + SeededNumberDictionary* dictionary = js_object->element_dictionary(); int entry = dictionary->FindEntry(index); - if (entry != NumberDictionary::kNotFound) { + if (entry != SeededNumberDictionary::kNotFound) { Object* element = dictionary->ValueAt(entry); PropertyDetails details = dictionary->DetailsAt(entry); if (details.type() == CALLBACKS) { - if (element->IsFixedArray()) { - return FixedArray::cast(element)->get(accessor_index); + if (element->IsAccessorPair()) { + AccessorPair* accessors = AccessorPair::cast(element); + return is_getter ? accessors->getter() : accessors->setter(); } } } @@ -4656,8 +4756,9 @@ Object* JSObject::LookupAccessor(String* name, bool is_getter) { if (result.IsReadOnly()) return heap->undefined_value(); if (result.type() == CALLBACKS) { Object* obj = result.GetCallbackObject(); - if (obj->IsFixedArray()) { - return FixedArray::cast(obj)->get(accessor_index); + if (obj->IsAccessorPair()) { + AccessorPair* accessors = AccessorPair::cast(obj); + return is_getter ? accessors->getter() : accessors->setter(); } } } @@ -6833,14 +6934,14 @@ uint32_t String::ComputeAndSetHash() { if (StringShape(this).IsSequentialAscii()) { field = HashSequentialString(SeqAsciiString::cast(this)->GetChars(), len, - GetHeap()->StringHashSeed()); + GetHeap()->HashSeed()); } else if (StringShape(this).IsSequentialTwoByte()) { field = HashSequentialString(SeqTwoByteString::cast(this)->GetChars(), len, - GetHeap()->StringHashSeed()); + GetHeap()->HashSeed()); } else { StringInputBuffer buffer(this); - field = ComputeHashField(&buffer, len, GetHeap()->StringHashSeed()); + field = ComputeHashField(&buffer, len, GetHeap()->HashSeed()); } // Store the hash code in the object. @@ -8171,7 +8272,7 @@ static void CopyFastElementsToFast(FixedArray* source, } -static void CopySlowElementsToFast(NumberDictionary* source, +static void CopySlowElementsToFast(SeededNumberDictionary* source, FixedArray* destination, WriteBarrierMode mode) { int destination_length = destination->length(); @@ -8237,7 +8338,7 @@ MaybeObject* JSObject::SetFastElementsCapacityAndLength( case DICTIONARY_ELEMENTS: { AssertNoAllocation no_gc; WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc); - CopySlowElementsToFast(NumberDictionary::cast(old_elements_raw), + CopySlowElementsToFast(SeededNumberDictionary::cast(old_elements_raw), new_elements, mode); set_map_and_elements(new_map, new_elements); @@ -8251,7 +8352,7 @@ MaybeObject* JSObject::SetFastElementsCapacityAndLength( FixedArray* parameter_map = FixedArray::cast(old_elements_raw); FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); if (arguments->IsDictionary()) { - CopySlowElementsToFast(NumberDictionary::cast(arguments), + CopySlowElementsToFast(SeededNumberDictionary::cast(arguments), new_elements, mode); } else { @@ -8347,7 +8448,7 @@ MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength( break; } case DICTIONARY_ELEMENTS: { - elems->Initialize(NumberDictionary::cast(old_elements)); + elems->Initialize(SeededNumberDictionary::cast(old_elements)); break; } default: @@ -8607,7 +8708,7 @@ bool JSObject::HasElementPostInterceptor(JSReceiver* receiver, uint32_t index) { } case DICTIONARY_ELEMENTS: { if (element_dictionary()->FindEntry(index) - != NumberDictionary::kNotFound) { + != SeededNumberDictionary::kNotFound) { return true; } break; @@ -8745,7 +8846,7 @@ JSObject::LocalElementType JSObject::HasLocalElement(uint32_t index) { } case DICTIONARY_ELEMENTS: { if (element_dictionary()->FindEntry(index) != - NumberDictionary::kNotFound) { + SeededNumberDictionary::kNotFound) { return DICTIONARY_ELEMENT; } break; @@ -8762,8 +8863,9 @@ JSObject::LocalElementType JSObject::HasLocalElement(uint32_t index) { // If not aliased, check the arguments. FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); if (arguments->IsDictionary()) { - NumberDictionary* dictionary = NumberDictionary::cast(arguments); - if (dictionary->FindEntry(index) != NumberDictionary::kNotFound) { + SeededNumberDictionary* dictionary = + SeededNumberDictionary::cast(arguments); + if (dictionary->FindEntry(index) != SeededNumberDictionary::kNotFound) { return DICTIONARY_ELEMENT; } } else { @@ -8792,8 +8894,8 @@ bool JSObject::HasElementInElements(FixedArray* elements, return true; } } else { - if (NumberDictionary::cast(elements)->FindEntry(index) != - NumberDictionary::kNotFound) { + if (SeededNumberDictionary::cast(elements)->FindEntry(index) != + SeededNumberDictionary::kNotFound) { return true; } } @@ -8860,7 +8962,7 @@ bool JSObject::HasElementWithReceiver(JSReceiver* receiver, uint32_t index) { } case DICTIONARY_ELEMENTS: { if (element_dictionary()->FindEntry(index) - != NumberDictionary::kNotFound) { + != SeededNumberDictionary::kNotFound) { return true; } break; @@ -8964,8 +9066,8 @@ MaybeObject* JSObject::GetElementWithCallback(Object* receiver, } // __defineGetter__ callback - if (structure->IsFixedArray()) { - Object* getter = FixedArray::cast(structure)->get(kGetterIndex); + if (structure->IsAccessorPair()) { + Object* getter = AccessorPair::cast(structure)->getter(); if (getter->IsSpecFunction()) { // TODO(rossberg): nicer would be to cast to some JSCallable here... return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter)); @@ -9021,8 +9123,8 @@ MaybeObject* JSObject::SetElementWithCallback(Object* structure, return *value_handle; } - if (structure->IsFixedArray()) { - Handle<Object> setter(FixedArray::cast(structure)->get(kSetterIndex)); + if (structure->IsAccessorPair()) { + Handle<Object> setter(AccessorPair::cast(structure)->setter()); if (setter->IsSpecFunction()) { // TODO(rossberg): nicer would be to cast to some JSCallable here... return SetPropertyWithDefinedSetter(JSReceiver::cast(*setter), value); @@ -9183,15 +9285,15 @@ MaybeObject* JSObject::SetDictionaryElement(uint32_t index, FixedArray* elements = FixedArray::cast(this->elements()); bool is_arguments = (elements->map() == heap->non_strict_arguments_elements_map()); - NumberDictionary* dictionary = NULL; + SeededNumberDictionary* dictionary = NULL; if (is_arguments) { - dictionary = NumberDictionary::cast(elements->get(1)); + dictionary = SeededNumberDictionary::cast(elements->get(1)); } else { - dictionary = NumberDictionary::cast(elements); + dictionary = SeededNumberDictionary::cast(elements); } int entry = dictionary->FindEntry(index); - if (entry != NumberDictionary::kNotFound) { + if (entry != SeededNumberDictionary::kNotFound) { Object* element = dictionary->ValueAt(entry); PropertyDetails details = dictionary->DetailsAt(entry); if (details.type() == CALLBACKS) { @@ -9236,13 +9338,13 @@ MaybeObject* JSObject::SetDictionaryElement(uint32_t index, FixedArrayBase* new_dictionary; MaybeObject* maybe = dictionary->AtNumberPut(index, value); if (!maybe->To<FixedArrayBase>(&new_dictionary)) return maybe; - if (dictionary != NumberDictionary::cast(new_dictionary)) { + if (dictionary != SeededNumberDictionary::cast(new_dictionary)) { if (is_arguments) { elements->set(1, new_dictionary); } else { set_elements(new_dictionary); } - dictionary = NumberDictionary::cast(new_dictionary); + dictionary = SeededNumberDictionary::cast(new_dictionary); } } @@ -9388,6 +9490,35 @@ MaybeObject* JSReceiver::SetElement(uint32_t index, } +Handle<Object> JSObject::SetOwnElement(Handle<JSObject> object, + uint32_t index, + Handle<Object> value, + StrictModeFlag strict_mode) { + ASSERT(!object->HasExternalArrayElements()); + CALL_HEAP_FUNCTION(object->GetIsolate(), + object->SetElement(index, *value, strict_mode, false), + Object); +} + + +Handle<Object> JSObject::SetElement(Handle<JSObject> object, + uint32_t index, + Handle<Object> value, + StrictModeFlag strict_mode) { + if (object->HasExternalArrayElements()) { + if (!value->IsSmi() && !value->IsHeapNumber() && !value->IsUndefined()) { + bool has_exception; + Handle<Object> number = Execution::ToNumber(value, &has_exception); + if (has_exception) return Handle<Object>(); + value = number; + } + } + CALL_HEAP_FUNCTION(object->GetIsolate(), + object->SetElement(index, *value, strict_mode, true), + Object); +} + + MaybeObject* JSObject::SetElement(uint32_t index, Object* value, StrictModeFlag strict_mode, @@ -9510,6 +9641,14 @@ MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, } +Handle<Object> JSObject::TransitionElementsKind(Handle<JSObject> object, + ElementsKind to_kind) { + CALL_HEAP_FUNCTION(object->GetIsolate(), + object->TransitionElementsKind(to_kind), + Object); +} + + MUST_USE_RESULT MaybeObject* JSObject::TransitionElementsKind( ElementsKind to_kind) { ElementsKind from_kind = map()->elements_kind(); @@ -9653,7 +9792,8 @@ void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) { FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); backing_store = FixedArray::cast(backing_store_base); if (backing_store->IsDictionary()) { - NumberDictionary* dictionary = NumberDictionary::cast(backing_store); + SeededNumberDictionary* dictionary = + SeededNumberDictionary::cast(backing_store); *capacity = dictionary->Capacity(); *used = dictionary->NumberOfElements(); break; @@ -9668,8 +9808,8 @@ void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) { } break; case DICTIONARY_ELEMENTS: { - NumberDictionary* dictionary = - NumberDictionary::cast(FixedArray::cast(elements())); + SeededNumberDictionary* dictionary = + SeededNumberDictionary::cast(FixedArray::cast(elements())); *capacity = dictionary->Capacity(); *used = dictionary->NumberOfElements(); break; @@ -9714,8 +9854,8 @@ bool JSObject::ShouldConvertToSlowElements(int new_capacity) { int old_capacity = 0; int used_elements = 0; GetElementsCapacityAndUsage(&old_capacity, &used_elements); - int dictionary_size = NumberDictionary::ComputeCapacity(used_elements) * - NumberDictionary::kEntrySize; + int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) * + SeededNumberDictionary::kEntrySize; return 3 * dictionary_size <= new_capacity; } @@ -9729,11 +9869,11 @@ bool JSObject::ShouldConvertToFastElements() { if (IsAccessCheckNeeded()) return false; FixedArray* elements = FixedArray::cast(this->elements()); - NumberDictionary* dictionary = NULL; + SeededNumberDictionary* dictionary = NULL; if (elements->map() == GetHeap()->non_strict_arguments_elements_map()) { - dictionary = NumberDictionary::cast(elements->get(1)); + dictionary = SeededNumberDictionary::cast(elements->get(1)); } else { - dictionary = NumberDictionary::cast(elements); + dictionary = SeededNumberDictionary::cast(elements); } // If an element has been added at a very high index in the elements // dictionary, we cannot go back to fast case. @@ -9748,7 +9888,7 @@ bool JSObject::ShouldConvertToFastElements() { array_size = dictionary->max_number_key(); } uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) * - NumberDictionary::kEntrySize; + SeededNumberDictionary::kEntrySize; return 2 * dictionary_size >= array_size; } @@ -9758,7 +9898,8 @@ bool JSObject::ShouldConvertToFastDoubleElements( *has_smi_only_elements = false; if (FLAG_unbox_double_arrays) { ASSERT(HasDictionaryElements()); - NumberDictionary* dictionary = NumberDictionary::cast(elements()); + SeededNumberDictionary* dictionary = + SeededNumberDictionary::cast(elements()); bool found_double = false; for (int i = 0; i < dictionary->Capacity(); i++) { Object* key = dictionary->KeyAt(i); @@ -9978,7 +10119,7 @@ bool JSObject::HasRealElementProperty(uint32_t index) { } case DICTIONARY_ELEMENTS: { return element_dictionary()->FindEntry(index) - != NumberDictionary::kNotFound; + != SeededNumberDictionary::kNotFound; } case NON_STRICT_ARGUMENTS_ELEMENTS: UNIMPLEMENTED(); @@ -10247,7 +10388,7 @@ int JSObject::GetLocalElementKeys(FixedArray* storage, if (storage != NULL) { element_dictionary()->CopyKeysTo(storage, filter, - NumberDictionary::SORTED); + SeededNumberDictionary::SORTED); } counter += element_dictionary()->NumberOfElementsFilterAttributes(filter); break; @@ -10259,9 +10400,11 @@ int JSObject::GetLocalElementKeys(FixedArray* storage, if (arguments->IsDictionary()) { // Copy the keys from arguments first, because Dictionary::CopyKeysTo // will insert in storage starting at index 0. - NumberDictionary* dictionary = NumberDictionary::cast(arguments); + SeededNumberDictionary* dictionary = + SeededNumberDictionary::cast(arguments); if (storage != NULL) { - dictionary->CopyKeysTo(storage, filter, NumberDictionary::UNSORTED); + dictionary->CopyKeysTo( + storage, filter, SeededNumberDictionary::UNSORTED); } counter += dictionary->NumberOfElementsFilterAttributes(filter); for (int i = 0; i < mapped_length; ++i) { @@ -10585,7 +10728,7 @@ class SubStringAsciiSymbolKey : public HashTableKey { uint32_t Hash() { ASSERT(length_ >= 0); ASSERT(from_ + length_ <= string_->length()); - StringHasher hasher(length_, string_->GetHeap()->StringHashSeed()); + StringHasher hasher(length_, string_->GetHeap()->HashSeed()); // Very long strings have a trivial hash that doesn't inspect the // string contents. @@ -10794,7 +10937,7 @@ MaybeObject* HashTable<Shape, Key>::Rehash(HashTable* new_table, Key key) { uint32_t from_index = EntryToIndex(i); Object* k = get(from_index); if (IsKey(k)) { - uint32_t hash = Shape::HashForObject(key, k); + uint32_t hash = HashTable<Shape, Key>::HashForObject(key, k); uint32_t insertion_index = EntryToIndex(new_table->FindInsertionEntry(hash)); for (int j = 0; j < Shape::kEntrySize; j++) { @@ -10892,38 +11035,46 @@ template class HashTable<ObjectHashTableShape<2>, Object*>; template class Dictionary<StringDictionaryShape, String*>; -template class Dictionary<NumberDictionaryShape, uint32_t>; +template class Dictionary<SeededNumberDictionaryShape, uint32_t>; -template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::Allocate( - int); +template class Dictionary<UnseededNumberDictionaryShape, uint32_t>; + +template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>:: + Allocate(int at_least_space_for); + +template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>:: + Allocate(int at_least_space_for); template MaybeObject* Dictionary<StringDictionaryShape, String*>::Allocate( int); -template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::AtPut( +template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::AtPut( uint32_t, Object*); -template Object* Dictionary<NumberDictionaryShape, uint32_t>::SlowReverseLookup( - Object*); +template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>:: + AtPut(uint32_t, Object*); + +template Object* Dictionary<UnseededNumberDictionaryShape, uint32_t>:: + SlowReverseLookup(Object* value); template Object* Dictionary<StringDictionaryShape, String*>::SlowReverseLookup( Object*); -template void Dictionary<NumberDictionaryShape, uint32_t>::CopyKeysTo( +template void Dictionary<SeededNumberDictionaryShape, uint32_t>::CopyKeysTo( FixedArray*, PropertyAttributes, - Dictionary<NumberDictionaryShape, uint32_t>::SortMode); + Dictionary<SeededNumberDictionaryShape, uint32_t>::SortMode); template Object* Dictionary<StringDictionaryShape, String*>::DeleteProperty( int, JSObject::DeleteMode); -template Object* Dictionary<NumberDictionaryShape, uint32_t>::DeleteProperty( - int, JSObject::DeleteMode); +template Object* Dictionary<SeededNumberDictionaryShape, uint32_t>:: + DeleteProperty(int, JSObject::DeleteMode); template MaybeObject* Dictionary<StringDictionaryShape, String*>::Shrink( String*); -template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::Shrink( +template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::Shrink( uint32_t); template void Dictionary<StringDictionaryShape, String*>::CopyKeysTo( @@ -10942,32 +11093,41 @@ template MaybeObject* Dictionary<StringDictionaryShape, String*>::GenerateNewEnumerationIndices(); template int -Dictionary<NumberDictionaryShape, uint32_t>::NumberOfElementsFilterAttributes( - PropertyAttributes); +Dictionary<SeededNumberDictionaryShape, uint32_t>:: + NumberOfElementsFilterAttributes(PropertyAttributes); -template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::Add( +template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::Add( uint32_t, Object*, PropertyDetails); -template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>:: +template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::Add( + uint32_t, Object*, PropertyDetails); + +template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>:: + EnsureCapacity(int, uint32_t); + +template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>:: EnsureCapacity(int, uint32_t); template MaybeObject* Dictionary<StringDictionaryShape, String*>:: EnsureCapacity(int, String*); -template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::AddEntry( - uint32_t, Object*, PropertyDetails, uint32_t); +template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>:: + AddEntry(uint32_t, Object*, PropertyDetails, uint32_t); + +template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>:: + AddEntry(uint32_t, Object*, PropertyDetails, uint32_t); template MaybeObject* Dictionary<StringDictionaryShape, String*>::AddEntry( String*, Object*, PropertyDetails, uint32_t); template -int Dictionary<NumberDictionaryShape, uint32_t>::NumberOfEnumElements(); +int Dictionary<SeededNumberDictionaryShape, uint32_t>::NumberOfEnumElements(); template int Dictionary<StringDictionaryShape, String*>::NumberOfEnumElements(); template -int HashTable<NumberDictionaryShape, uint32_t>::FindEntry(uint32_t); +int HashTable<SeededNumberDictionaryShape, uint32_t>::FindEntry(uint32_t); // Collates undefined and unexisting elements below limit from position @@ -10977,7 +11137,7 @@ MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) { // Must stay in dictionary mode, either because of requires_slow_elements, // or because we are not going to sort (and therefore compact) all of the // elements. - NumberDictionary* dict = element_dictionary(); + SeededNumberDictionary* dict = element_dictionary(); HeapNumber* result_double = NULL; if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { // Allocate space for result before we start mutating the object. @@ -10990,10 +11150,10 @@ MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) { Object* obj; { MaybeObject* maybe_obj = - NumberDictionary::Allocate(dict->NumberOfElements()); + SeededNumberDictionary::Allocate(dict->NumberOfElements()); if (!maybe_obj->ToObject(&obj)) return maybe_obj; } - NumberDictionary* new_dict = NumberDictionary::cast(obj); + SeededNumberDictionary* new_dict = SeededNumberDictionary::cast(obj); AssertNoAllocation no_alloc; @@ -11077,7 +11237,7 @@ MaybeObject* JSObject::PrepareElementsForSort(uint32_t limit) { if (HasDictionaryElements()) { // Convert to fast elements containing only the existing properties. // Ordering is irrelevant, since we are going to sort anyway. - NumberDictionary* dict = element_dictionary(); + SeededNumberDictionary* dict = element_dictionary(); if (IsJSArray() || dict->requires_slow_elements() || dict->max_number_key() >= limit) { return PrepareSlowElementsForSort(limit); @@ -11444,7 +11604,7 @@ class TwoCharHashTableKey : public HashTableKey { hash += hash << 3; hash ^= hash >> 11; hash += hash << 15; - if ((hash & String::kHashBitMask) == 0) hash = 27; + if ((hash & String::kHashBitMask) == 0) hash = String::kZeroHash; #ifdef DEBUG StringHasher hasher(2, seed); hasher.AddCharacter(c1); @@ -11503,7 +11663,7 @@ bool SymbolTable::LookupSymbolIfExists(String* string, String** symbol) { bool SymbolTable::LookupTwoCharsSymbolIfExists(uint32_t c1, uint32_t c2, String** symbol) { - TwoCharHashTableKey key(c1, c2, GetHeap()->StringHashSeed()); + TwoCharHashTableKey key(c1, c2, GetHeap()->HashSeed()); int entry = FindEntry(&key); if (entry == kNotFound) { return false; @@ -11518,14 +11678,14 @@ bool SymbolTable::LookupTwoCharsSymbolIfExists(uint32_t c1, MaybeObject* SymbolTable::LookupSymbol(Vector<const char> str, Object** s) { - Utf8SymbolKey key(str, GetHeap()->StringHashSeed()); + Utf8SymbolKey key(str, GetHeap()->HashSeed()); return LookupKey(&key, s); } MaybeObject* SymbolTable::LookupAsciiSymbol(Vector<const char> str, Object** s) { - AsciiSymbolKey key(str, GetHeap()->StringHashSeed()); + AsciiSymbolKey key(str, GetHeap()->HashSeed()); return LookupKey(&key, s); } @@ -11534,14 +11694,14 @@ MaybeObject* SymbolTable::LookupSubStringAsciiSymbol(Handle<SeqAsciiString> str, int from, int length, Object** s) { - SubStringAsciiSymbolKey key(str, from, length, GetHeap()->StringHashSeed()); + SubStringAsciiSymbolKey key(str, from, length, GetHeap()->HashSeed()); return LookupKey(&key, s); } MaybeObject* SymbolTable::LookupTwoByteSymbol(Vector<const uc16> str, Object** s) { - TwoByteSymbolKey key(str, GetHeap()->StringHashSeed()); + TwoByteSymbolKey key(str, GetHeap()->HashSeed()); return LookupKey(&key, s); } @@ -11880,8 +12040,9 @@ MaybeObject* Dictionary<Shape, Key>::AtPut(Key key, Object* value) { if (!maybe_k->ToObject(&k)) return maybe_k; } PropertyDetails details = PropertyDetails(NONE, NORMAL); - return Dictionary<Shape, Key>::cast(obj)-> - AddEntry(key, value, details, Shape::Hash(key)); + + return Dictionary<Shape, Key>::cast(obj)->AddEntry(key, value, details, + Dictionary<Shape, Key>::Hash(key)); } @@ -11896,8 +12057,9 @@ MaybeObject* Dictionary<Shape, Key>::Add(Key key, { MaybeObject* maybe_obj = EnsureCapacity(1, key); if (!maybe_obj->ToObject(&obj)) return maybe_obj; } - return Dictionary<Shape, Key>::cast(obj)-> - AddEntry(key, value, details, Shape::Hash(key)); + + return Dictionary<Shape, Key>::cast(obj)->AddEntry(key, value, details, + Dictionary<Shape, Key>::Hash(key)); } @@ -11930,7 +12092,7 @@ MaybeObject* Dictionary<Shape, Key>::AddEntry(Key key, } -void NumberDictionary::UpdateMaxNumberKey(uint32_t key) { +void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) { // If the dictionary requires slow elements an element has already // been added at a high index. if (requires_slow_elements()) return; @@ -11949,31 +12111,65 @@ void NumberDictionary::UpdateMaxNumberKey(uint32_t key) { } -MaybeObject* NumberDictionary::AddNumberEntry(uint32_t key, - Object* value, - PropertyDetails details) { +MaybeObject* SeededNumberDictionary::AddNumberEntry(uint32_t key, + Object* value, + PropertyDetails details) { UpdateMaxNumberKey(key); SLOW_ASSERT(this->FindEntry(key) == kNotFound); return Add(key, value, details); } -MaybeObject* NumberDictionary::AtNumberPut(uint32_t key, Object* value) { +MaybeObject* UnseededNumberDictionary::AddNumberEntry(uint32_t key, + Object* value) { + SLOW_ASSERT(this->FindEntry(key) == kNotFound); + return Add(key, value, PropertyDetails(NONE, NORMAL)); +} + + +MaybeObject* SeededNumberDictionary::AtNumberPut(uint32_t key, Object* value) { UpdateMaxNumberKey(key); return AtPut(key, value); } -MaybeObject* NumberDictionary::Set(uint32_t key, - Object* value, - PropertyDetails details) { +MaybeObject* UnseededNumberDictionary::AtNumberPut(uint32_t key, + Object* value) { + return AtPut(key, value); +} + + +Handle<SeededNumberDictionary> SeededNumberDictionary::Set( + Handle<SeededNumberDictionary> dictionary, + uint32_t index, + Handle<Object> value, + PropertyDetails details) { + CALL_HEAP_FUNCTION(dictionary->GetIsolate(), + dictionary->Set(index, *value, details), + SeededNumberDictionary); +} + + +Handle<UnseededNumberDictionary> UnseededNumberDictionary::Set( + Handle<UnseededNumberDictionary> dictionary, + uint32_t index, + Handle<Object> value) { + CALL_HEAP_FUNCTION(dictionary->GetIsolate(), + dictionary->Set(index, *value), + UnseededNumberDictionary); +} + + +MaybeObject* SeededNumberDictionary::Set(uint32_t key, + Object* value, + PropertyDetails details) { int entry = FindEntry(key); if (entry == kNotFound) return AddNumberEntry(key, value, details); // Preserve enumeration index. details = PropertyDetails(details.attributes(), details.type(), DetailsAt(entry).index()); - MaybeObject* maybe_object_key = NumberDictionaryShape::AsObject(key); + MaybeObject* maybe_object_key = SeededNumberDictionaryShape::AsObject(key); Object* object_key; if (!maybe_object_key->ToObject(&object_key)) return maybe_object_key; SetEntry(entry, object_key, value, details); @@ -11981,6 +12177,18 @@ MaybeObject* NumberDictionary::Set(uint32_t key, } +MaybeObject* UnseededNumberDictionary::Set(uint32_t key, + Object* value) { + int entry = FindEntry(key); + if (entry == kNotFound) return AddNumberEntry(key, value); + MaybeObject* maybe_object_key = UnseededNumberDictionaryShape::AsObject(key); + Object* object_key; + if (!maybe_object_key->ToObject(&object_key)) return maybe_object_key; + SetEntry(entry, object_key, value); + return this; +} + + template<typename Shape, typename Key> int Dictionary<Shape, Key>::NumberOfElementsFilterAttributes( diff --git a/deps/v8/src/objects.h b/deps/v8/src/objects.h index 541334a5dc1..791aeb36474 100644 --- a/deps/v8/src/objects.h +++ b/deps/v8/src/objects.h @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -107,6 +107,7 @@ // - SharedFunctionInfo // - Struct // - AccessorInfo +// - AccessorPair // - AccessCheckInfo // - InterceptorInfo // - CallHandlerInfo @@ -162,6 +163,11 @@ enum ElementsKind { LAST_ELEMENTS_KIND = EXTERNAL_PIXEL_ELEMENTS }; +enum CompareMapMode { + REQUIRE_EXACT_MAP, + ALLOW_ELEMENT_TRANSITION_MAPS +}; + const int kElementsKindCount = LAST_ELEMENTS_KIND - FIRST_ELEMENTS_KIND + 1; void PrintElementsKind(FILE* out, ElementsKind kind); @@ -270,6 +276,7 @@ const int kVariableSizeSentinel = 0; V(FILLER_TYPE) \ \ V(ACCESSOR_INFO_TYPE) \ + V(ACCESSOR_PAIR_TYPE) \ V(ACCESS_CHECK_INFO_TYPE) \ V(INTERCEPTOR_INFO_TYPE) \ V(CALL_HANDLER_INFO_TYPE) \ @@ -417,6 +424,7 @@ const int kVariableSizeSentinel = 0; // manually. #define STRUCT_LIST_ALL(V) \ V(ACCESSOR_INFO, AccessorInfo, accessor_info) \ + V(ACCESSOR_PAIR, AccessorPair, accessor_pair) \ V(ACCESS_CHECK_INFO, AccessCheckInfo, access_check_info) \ V(INTERCEPTOR_INFO, InterceptorInfo, interceptor_info) \ V(CALL_HANDLER_INFO, CallHandlerInfo, call_handler_info) \ @@ -570,6 +578,7 @@ enum InstanceType { // Structs. ACCESSOR_INFO_TYPE, + ACCESSOR_PAIR_TYPE, ACCESS_CHECK_INFO_TYPE, INTERCEPTOR_INFO_TYPE, CALL_HANDLER_INFO_TYPE, @@ -1342,6 +1351,11 @@ class JSReceiver: public HeapObject { // Casting. static inline JSReceiver* cast(Object* obj); + static Handle<Object> SetProperty(Handle<JSReceiver> object, + Handle<String> key, + Handle<Object> value, + PropertyAttributes attributes, + StrictModeFlag strict_mode); // Can cause GC. MUST_USE_RESULT MaybeObject* SetProperty(String* key, Object* value, @@ -1471,7 +1485,7 @@ class JSObject: public JSReceiver { inline bool HasExternalDoubleElements(); bool HasFastArgumentsElements(); bool HasDictionaryArgumentsElements(); - inline NumberDictionary* element_dictionary(); // Gets slow elements. + inline SeededNumberDictionary* element_dictionary(); // Gets slow elements. inline void set_map_and_elements( Map* map, @@ -1521,6 +1535,14 @@ class JSObject: public JSReceiver { Object* value, PropertyAttributes attributes, StrictModeFlag strict_mode); + + static Handle<Object> SetLocalPropertyIgnoreAttributes( + Handle<JSObject> object, + Handle<String> key, + Handle<Object> value, + PropertyAttributes attributes); + + // Can cause GC. MUST_USE_RESULT MaybeObject* SetLocalPropertyIgnoreAttributes( String* key, Object* value, @@ -1536,6 +1558,11 @@ class JSObject: public JSReceiver { // Sets the property value in a normalized object given (key, value, details). // Handles the special representation of JS global objects. + static Handle<Object> SetNormalizedProperty(Handle<JSObject> object, + Handle<String> key, + Handle<Object> value, + PropertyDetails details); + MUST_USE_RESULT MaybeObject* SetNormalizedProperty(String* name, Object* value, PropertyDetails details); @@ -1605,8 +1632,11 @@ class JSObject: public JSReceiver { // hidden properties. // Sets a hidden property on this object. Returns this object if successful, - // undefined if called on a detached proxy, and a failure if a GC - // is required + // undefined if called on a detached proxy. + static Handle<Object> SetHiddenProperty(Handle<JSObject> obj, + Handle<String> key, + Handle<Object> value); + // Returns a failure if a GC is required. MaybeObject* SetHiddenProperty(String* key, Object* value); // Gets the value of a hidden property with the given key. Returns undefined // if the property doesn't exist (or if called on a detached proxy), @@ -1618,10 +1648,15 @@ class JSObject: public JSReceiver { // Returns true if the object has a property with the hidden symbol as name. bool HasHiddenProperties(); + static int GetIdentityHash(Handle<JSObject> obj); MUST_USE_RESULT MaybeObject* GetIdentityHash(CreationFlag flag); MUST_USE_RESULT MaybeObject* SetIdentityHash(Object* hash, CreationFlag flag); + static Handle<Object> DeleteProperty(Handle<JSObject> obj, + Handle<String> name); MUST_USE_RESULT MaybeObject* DeleteProperty(String* name, DeleteMode mode); + + static Handle<Object> DeleteElement(Handle<JSObject> obj, uint32_t index); MUST_USE_RESULT MaybeObject* DeleteElement(uint32_t index, DeleteMode mode); inline void ValidateSmiOnlyElements(); @@ -1701,7 +1736,18 @@ class JSObject: public JSReceiver { StrictModeFlag strict_mode, bool check_prototype = true); - // Set the index'th array element. + + static Handle<Object> SetOwnElement(Handle<JSObject> object, + uint32_t index, + Handle<Object> value, + StrictModeFlag strict_mode); + + // Empty handle is returned if the element cannot be set to the given value. + static MUST_USE_RESULT Handle<Object> SetElement(Handle<JSObject> object, + uint32_t index, + Handle<Object> value, + StrictModeFlag strict_mode); + // A Failure object is returned if GC is needed. MUST_USE_RESULT MaybeObject* SetElement(uint32_t index, Object* value, @@ -1811,6 +1857,9 @@ class JSObject: public JSReceiver { MUST_USE_RESULT MaybeObject* GetElementsTransitionMap( ElementsKind elements_kind); + static Handle<Object> TransitionElementsKind(Handle<JSObject> object, + ElementsKind to_kind); + MUST_USE_RESULT MaybeObject* TransitionElementsKind(ElementsKind to_kind); // Converts a descriptor of any other type to a real field, @@ -1851,12 +1900,19 @@ class JSObject: public JSReceiver { // representation. If the object is expected to have additional properties // added this number can be indicated to have the backing store allocated to // an initial capacity for holding these properties. + static void NormalizeProperties(Handle<JSObject> object, + PropertyNormalizationMode mode, + int expected_additional_properties); + MUST_USE_RESULT MaybeObject* NormalizeProperties( PropertyNormalizationMode mode, int expected_additional_properties); - // Convert and update the elements backing store to be a NumberDictionary - // dictionary. Returns the backing after conversion. + // Convert and update the elements backing store to be a + // SeededNumberDictionary dictionary. Returns the backing after conversion. + static Handle<SeededNumberDictionary> NormalizeElements( + Handle<JSObject> object); + MUST_USE_RESULT MaybeObject* NormalizeElements(); static void UpdateMapCodeCache(Handle<JSObject> object, @@ -1867,6 +1923,9 @@ class JSObject: public JSReceiver { // Transform slow named properties to fast variants. // Returns failure if allocation failed. + static void TransformToFastProperties(Handle<JSObject> object, + int unused_property_fields); + MUST_USE_RESULT MaybeObject* TransformToFastProperties( int unused_property_fields); @@ -1898,6 +1957,7 @@ class JSObject: public JSReceiver { static inline JSObject* cast(Object* obj); // Disalow further properties to be added to the object. + static Handle<Object> PreventExtensions(Handle<JSObject> object); MUST_USE_RESULT MaybeObject* PreventExtensions(); @@ -1951,11 +2011,6 @@ class JSObject: public JSReceiver { #endif Object* SlowReverseLookup(Object* value); - // Getters and setters are stored in a fixed array property. - // These are constants for their indices. - static const int kGetterIndex = 0; - static const int kSetterIndex = 1; - // Maximal number of fast properties for the JSObject. Used to // restrict the number of map transitions to avoid an explosion in // the number of maps for objects used as dictionaries. @@ -2223,7 +2278,7 @@ class FixedDoubleArray: public FixedArrayBase { public: inline void Initialize(FixedArray* from); inline void Initialize(FixedDoubleArray* from); - inline void Initialize(NumberDictionary* from); + inline void Initialize(SeededNumberDictionary* from); // Setter and getter for elements. inline double get_scalar(int index); @@ -2538,9 +2593,44 @@ class DescriptorArray: public FixedArray { // beginning of the backing storage that can be used for non-element // information by subclasses. +template<typename Key> +class BaseShape { + public: + static const bool UsesSeed = false; + static uint32_t Hash(Key key) { return 0; } + static uint32_t SeededHash(Key key, uint32_t seed) { + ASSERT(UsesSeed); + return Hash(key); + } + static uint32_t HashForObject(Key key, Object* object) { return 0; } + static uint32_t SeededHashForObject(Key key, uint32_t seed, Object* object) { + ASSERT(UsesSeed); + return HashForObject(key, object); + } +}; + template<typename Shape, typename Key> class HashTable: public FixedArray { public: + // Wrapper methods + inline uint32_t Hash(Key key) { + if (Shape::UsesSeed) { + return Shape::SeededHash(key, + GetHeap()->HashSeed()); + } else { + return Shape::Hash(key); + } + } + + inline uint32_t HashForObject(Key key, Object* object) { + if (Shape::UsesSeed) { + return Shape::SeededHashForObject(key, + GetHeap()->HashSeed(), object); + } else { + return Shape::HashForObject(key, object); + } + } + // Returns the number of elements in the hash table. int NumberOfElements() { return Smi::cast(get(kNumberOfElementsIndex))->value(); @@ -2682,7 +2772,6 @@ class HashTable: public FixedArray { }; - // HashTableKey is an abstract superclass for virtual key behavior. class HashTableKey { public: @@ -2699,7 +2788,8 @@ class HashTableKey { virtual ~HashTableKey() {} }; -class SymbolTableShape { + +class SymbolTableShape : public BaseShape<HashTableKey*> { public: static inline bool IsMatch(HashTableKey* key, Object* value) { return key->IsMatch(value); @@ -2758,7 +2848,7 @@ class SymbolTable: public HashTable<SymbolTableShape, HashTableKey*> { }; -class MapCacheShape { +class MapCacheShape : public BaseShape<HashTableKey*> { public: static inline bool IsMatch(HashTableKey* key, Object* value) { return key->IsMatch(value); @@ -2914,7 +3004,7 @@ class Dictionary: public HashTable<Shape, Key> { }; -class StringDictionaryShape { +class StringDictionaryShape : public BaseShape<String*> { public: static inline bool IsMatch(String* key, Object* other); static inline uint32_t Hash(String* key); @@ -2947,23 +3037,42 @@ class StringDictionary: public Dictionary<StringDictionaryShape, String*> { }; -class NumberDictionaryShape { +class NumberDictionaryShape : public BaseShape<uint32_t> { public: static inline bool IsMatch(uint32_t key, Object* other); - static inline uint32_t Hash(uint32_t key); - static inline uint32_t HashForObject(uint32_t key, Object* object); MUST_USE_RESULT static inline MaybeObject* AsObject(uint32_t key); - static const int kPrefixSize = 2; static const int kEntrySize = 3; static const bool kIsEnumerable = false; }; -class NumberDictionary: public Dictionary<NumberDictionaryShape, uint32_t> { +class SeededNumberDictionaryShape : public NumberDictionaryShape { + public: + static const bool UsesSeed = true; + static const int kPrefixSize = 2; + + static inline uint32_t SeededHash(uint32_t key, uint32_t seed); + static inline uint32_t SeededHashForObject(uint32_t key, + uint32_t seed, + Object* object); +}; + + +class UnseededNumberDictionaryShape : public NumberDictionaryShape { public: - static NumberDictionary* cast(Object* obj) { + static const int kPrefixSize = 0; + + static inline uint32_t Hash(uint32_t key); + static inline uint32_t HashForObject(uint32_t key, Object* object); +}; + + +class SeededNumberDictionary + : public Dictionary<SeededNumberDictionaryShape, uint32_t> { + public: + static SeededNumberDictionary* cast(Object* obj) { ASSERT(obj->IsDictionary()); - return reinterpret_cast<NumberDictionary*>(obj); + return reinterpret_cast<SeededNumberDictionary*>(obj); } // Type specific at put (default NONE attributes is used when adding). @@ -2973,6 +3082,13 @@ class NumberDictionary: public Dictionary<NumberDictionaryShape, uint32_t> { PropertyDetails details); // Set an existing entry or add a new one if needed. + // Return the updated dictionary. + MUST_USE_RESULT static Handle<SeededNumberDictionary> Set( + Handle<SeededNumberDictionary> dictionary, + uint32_t index, + Handle<Object> value, + PropertyDetails details); + MUST_USE_RESULT MaybeObject* Set(uint32_t key, Object* value, PropertyDetails details); @@ -2999,8 +3115,31 @@ class NumberDictionary: public Dictionary<NumberDictionaryShape, uint32_t> { }; +class UnseededNumberDictionary + : public Dictionary<UnseededNumberDictionaryShape, uint32_t> { + public: + static UnseededNumberDictionary* cast(Object* obj) { + ASSERT(obj->IsDictionary()); + return reinterpret_cast<UnseededNumberDictionary*>(obj); + } + + // Type specific at put (default NONE attributes is used when adding). + MUST_USE_RESULT MaybeObject* AtNumberPut(uint32_t key, Object* value); + MUST_USE_RESULT MaybeObject* AddNumberEntry(uint32_t key, Object* value); + + // Set an existing entry or add a new one if needed. + // Return the updated dictionary. + MUST_USE_RESULT static Handle<UnseededNumberDictionary> Set( + Handle<UnseededNumberDictionary> dictionary, + uint32_t index, + Handle<Object> value); + + MUST_USE_RESULT MaybeObject* Set(uint32_t key, Object* value); +}; + + template <int entrysize> -class ObjectHashTableShape { +class ObjectHashTableShape : public BaseShape<Object*> { public: static inline bool IsMatch(Object* key, Object* other); static inline uint32_t Hash(Object* key); @@ -4791,7 +4930,10 @@ class Script: public Struct { V(Math, atan, MathATan) \ V(Math, exp, MathExp) \ V(Math, sqrt, MathSqrt) \ - V(Math, pow, MathPow) + V(Math, pow, MathPow) \ + V(Math, random, MathRandom) \ + V(Math, max, MathMax) \ + V(Math, min, MathMin) enum BuiltinFunctionId { @@ -5912,7 +6054,7 @@ class JSRegExp: public JSObject { }; -class CompilationCacheShape { +class CompilationCacheShape : public BaseShape<HashTableKey*> { public: static inline bool IsMatch(HashTableKey* key, Object* value) { return key->IsMatch(value); @@ -6016,7 +6158,7 @@ class CodeCache: public Struct { }; -class CodeCacheHashTableShape { +class CodeCacheHashTableShape : public BaseShape<HashTableKey*> { public: static inline bool IsMatch(HashTableKey* key, Object* value) { return key->IsMatch(value); @@ -6148,6 +6290,11 @@ class StringHasher { // value is represented decimal value. static uint32_t MakeArrayIndexHash(uint32_t value, int length); + // No string is allowed to have a hash of zero. That value is reserved + // for internal properties. If the hash calculation yields zero then we + // use 27 instead. + static const int kZeroHash = 27; + private: uint32_t array_index() { ASSERT(is_array_index()); @@ -7528,6 +7675,35 @@ class AccessorInfo: public Struct { }; +// Support for JavaScript accessors: A pair of a getter and a setter. Each +// accessor can either be +// * a pointer to a JavaScript function or proxy: a real accessor +// * undefined: considered an accessor by the spec, too, strangely enough +// * the hole: an accessor which has not been set +// * a pointer to a map: a transition used to ensure map sharing +class AccessorPair: public Struct { + public: + DECL_ACCESSORS(getter, Object) + DECL_ACCESSORS(setter, Object) + + static inline AccessorPair* cast(Object* obj); + +#ifdef OBJECT_PRINT + void AccessorPairPrint(FILE* out = stdout); +#endif +#ifdef DEBUG + void AccessorPairVerify(); +#endif + + static const int kGetterOffset = HeapObject::kHeaderSize; + static const int kSetterOffset = kGetterOffset + kPointerSize; + static const int kSize = kSetterOffset + kPointerSize; + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(AccessorPair); +}; + + class AccessCheckInfo: public Struct { public: DECL_ACCESSORS(named_callback, Object) diff --git a/deps/v8/src/parser.cc b/deps/v8/src/parser.cc index c1681cfbd09..777436ee045 100644 --- a/deps/v8/src/parser.cc +++ b/deps/v8/src/parser.cc @@ -1186,8 +1186,8 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor, if (directive_prologue) { // A shot at a directive. - ExpressionStatement *e_stat; - Literal *literal; + ExpressionStatement* e_stat; + Literal* literal; // Still processing directive prologue? if ((e_stat = stat->AsExpressionStatement()) != NULL && (literal = e_stat->expression()->AsLiteral()) != NULL && @@ -1562,7 +1562,7 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) { // TODO(1240846): It's weird that native function declarations are // introduced dynamically when we meet their declarations, whereas - // other functions are setup when entering the surrounding scope. + // other functions are set up when entering the surrounding scope. SharedFunctionInfoLiteral* lit = new(zone()) SharedFunctionInfoLiteral(isolate(), shared); VariableProxy* var = Declare(name, VAR, NULL, true, CHECK_OK); @@ -3003,7 +3003,19 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) { } case Token::LPAREN: { - int pos = scanner().location().beg_pos; + int pos; + if (scanner().current_token() == Token::IDENTIFIER) { + // For call of an identifier we want to report position of + // the identifier as position of the call in the stack trace. + pos = scanner().location().beg_pos; + } else { + // For other kinds of calls we record position of the parenthesis as + // position of the call. Note that this is extremely important for + // expressions of the form function(){...}() for which call position + // should not point to the closing brace otherwise it will intersect + // with positions recorded for function literal and confuse debugger. + pos = scanner().peek_location().beg_pos; + } ZoneList<Expression*>* args = ParseArguments(CHECK_OK); // Keep track of eval() calls since they disable all local variable @@ -3595,7 +3607,7 @@ void ObjectLiteralPropertyChecker::CheckProperty( ASSERT(property != NULL); - Literal *lit = property->key(); + Literal* lit = property->key(); Handle<Object> handle = lit->handle(); uint32_t hash; diff --git a/deps/v8/src/platform-cygwin.cc b/deps/v8/src/platform-cygwin.cc index a72f5da4b73..9b34de91ceb 100644 --- a/deps/v8/src/platform-cygwin.cc +++ b/deps/v8/src/platform-cygwin.cc @@ -61,7 +61,7 @@ double ceiling(double x) { static Mutex* limit_mutex = NULL; -void OS::Setup() { +void OS::SetUp() { // Seed the random number generator. // Convert the current time to a 64-bit integer first, before converting it // to an unsigned. Going directly can cause an overflow and the seed to be @@ -290,7 +290,7 @@ void OS::LogSharedLibraryAddresses() { } LOG(isolate, SharedLibraryEvent(lib_name, start, end)); } else { - // Entry not describing executable data. Skip to end of line to setup + // Entry not describing executable data. Skip to end of line to set up // reading the next entry. do { c = getc(fp); diff --git a/deps/v8/src/platform-freebsd.cc b/deps/v8/src/platform-freebsd.cc index 20bd8379312..7d0d8d026d9 100644 --- a/deps/v8/src/platform-freebsd.cc +++ b/deps/v8/src/platform-freebsd.cc @@ -79,7 +79,7 @@ double ceiling(double x) { static Mutex* limit_mutex = NULL; -void OS::Setup() { +void OS::SetUp() { // Seed the random number generator. // Convert the current time to a 64-bit integer first, before converting it // to an unsigned. Going directly can cause an overflow and the seed to be diff --git a/deps/v8/src/platform-linux.cc b/deps/v8/src/platform-linux.cc index e72d095b0ad..a3cdc031ef1 100644 --- a/deps/v8/src/platform-linux.cc +++ b/deps/v8/src/platform-linux.cc @@ -78,7 +78,7 @@ double ceiling(double x) { static Mutex* limit_mutex = NULL; -void OS::Setup() { +void OS::SetUp() { // Seed the random number generator. We preserve microsecond resolution. uint64_t seed = Ticks() ^ (getpid() << 16); srandom(static_cast<unsigned int>(seed)); @@ -512,7 +512,7 @@ void OS::LogSharedLibraryAddresses() { } LOG(isolate, SharedLibraryEvent(lib_name, start, end)); } else { - // Entry not describing executable data. Skip to end of line to setup + // Entry not describing executable data. Skip to end of line to set up // reading the next entry. do { c = getc(fp); diff --git a/deps/v8/src/platform-macos.cc b/deps/v8/src/platform-macos.cc index 6e5d29da2f9..417fb11ae12 100644 --- a/deps/v8/src/platform-macos.cc +++ b/deps/v8/src/platform-macos.cc @@ -93,7 +93,7 @@ double ceiling(double x) { static Mutex* limit_mutex = NULL; -void OS::Setup() { +void OS::SetUp() { // Seed the random number generator. We preserve microsecond resolution. uint64_t seed = Ticks() ^ (getpid() << 16); srandom(static_cast<unsigned int>(seed)); diff --git a/deps/v8/src/platform-nullos.cc b/deps/v8/src/platform-nullos.cc index 8c2a8633d73..094f950f72c 100644 --- a/deps/v8/src/platform-nullos.cc +++ b/deps/v8/src/platform-nullos.cc @@ -56,7 +56,7 @@ double modulo(double x, double y) { // Initialize OS class early in the V8 startup. -void OS::Setup() { +void OS::SetUp() { // Seed the random number generator. UNIMPLEMENTED(); } diff --git a/deps/v8/src/platform-openbsd.cc b/deps/v8/src/platform-openbsd.cc index 772d08b587c..6f582d43419 100644 --- a/deps/v8/src/platform-openbsd.cc +++ b/deps/v8/src/platform-openbsd.cc @@ -99,7 +99,7 @@ static void* GetRandomMmapAddr() { } -void OS::Setup() { +void OS::SetUp() { // Seed the random number generator. We preserve microsecond resolution. uint64_t seed = Ticks() ^ (getpid() << 16); srandom(static_cast<unsigned int>(seed)); @@ -312,7 +312,7 @@ void OS::LogSharedLibraryAddresses() { } LOG(isolate, SharedLibraryEvent(lib_name, start, end)); } else { - // Entry not describing executable data. Skip to end of line to setup + // Entry not describing executable data. Skip to end of line to set up // reading the next entry. do { c = getc(fp); diff --git a/deps/v8/src/platform-posix.cc b/deps/v8/src/platform-posix.cc index 08417ff9bcf..34fd5c44985 100644 --- a/deps/v8/src/platform-posix.cc +++ b/deps/v8/src/platform-posix.cc @@ -461,7 +461,7 @@ bool POSIXSocket::SetReuseAddress(bool reuse_address) { } -bool Socket::Setup() { +bool Socket::SetUp() { // Nothing to do on POSIX. return true; } diff --git a/deps/v8/src/platform-solaris.cc b/deps/v8/src/platform-solaris.cc index 035d394453f..d55ea8913bb 100644 --- a/deps/v8/src/platform-solaris.cc +++ b/deps/v8/src/platform-solaris.cc @@ -89,7 +89,7 @@ double ceiling(double x) { static Mutex* limit_mutex = NULL; -void OS::Setup() { +void OS::SetUp() { // Seed the random number generator. // Convert the current time to a 64-bit integer first, before converting it // to an unsigned. Going directly will cause an overflow and the seed to be diff --git a/deps/v8/src/platform-win32.cc b/deps/v8/src/platform-win32.cc index 822f3606427..c439ab91a0d 100644 --- a/deps/v8/src/platform-win32.cc +++ b/deps/v8/src/platform-win32.cc @@ -528,7 +528,7 @@ char* Time::LocalTimezone() { } -void OS::Setup() { +void OS::SetUp() { // Seed the random number generator. // Convert the current time to a 64-bit integer first, before converting it // to an unsigned. Going directly can cause an overflow and the seed to be @@ -1825,7 +1825,7 @@ bool Win32Socket::SetReuseAddress(bool reuse_address) { } -bool Socket::Setup() { +bool Socket::SetUp() { // Initialize Winsock32 int err; WSADATA winsock_data; diff --git a/deps/v8/src/platform.h b/deps/v8/src/platform.h index 127f788f9dd..fc12df2d7cf 100644 --- a/deps/v8/src/platform.h +++ b/deps/v8/src/platform.h @@ -109,7 +109,7 @@ class Socket; class OS { public: // Initializes the platform OS support. Called once at VM startup. - static void Setup(); + static void SetUp(); // Returns the accumulated user time for thread. This routine // can be used for profiling. The implementation should @@ -477,7 +477,7 @@ class Thread { PlatformData* data() { return data_; } private: - void set_name(const char *name); + void set_name(const char* name); PlatformData* data_; @@ -553,7 +553,7 @@ class Semaphore { virtual void Wait() = 0; // Suspends the calling thread until the counter is non zero or the timeout - // time has passsed. If timeout happens the return value is false and the + // time has passed. If timeout happens the return value is false and the // counter is unchanged. Otherwise the semaphore counter is decremented and // true is returned. The timeout value is specified in microseconds. virtual bool Wait(int timeout) = 0; @@ -593,7 +593,7 @@ class Socket { virtual bool IsValid() const = 0; - static bool Setup(); + static bool SetUp(); static int LastError(); static uint16_t HToN(uint16_t value); static uint16_t NToH(uint16_t value); diff --git a/deps/v8/src/preparser.h b/deps/v8/src/preparser.h index fc8a4a0ca8e..f17bac2eac8 100644 --- a/deps/v8/src/preparser.h +++ b/deps/v8/src/preparser.h @@ -630,7 +630,7 @@ class PreParser { void SetStrictModeViolation(i::Scanner::Location, const char* type, - bool *ok); + bool* ok); void CheckDelayedStrictModeViolation(int beg_pos, int end_pos, bool* ok); diff --git a/deps/v8/src/profile-generator.cc b/deps/v8/src/profile-generator.cc index 00fc7b736a7..97de08e5bf9 100644 --- a/deps/v8/src/profile-generator.cc +++ b/deps/v8/src/profile-generator.cc @@ -111,7 +111,7 @@ const char* StringsStorage::GetCopy(const char* src) { OS::StrNCpy(dst, src, len); dst[len] = '\0'; uint32_t hash = - HashSequentialString(dst.start(), len, HEAP->StringHashSeed()); + HashSequentialString(dst.start(), len, HEAP->HashSeed()); return AddOrDisposeString(dst.start(), hash); } @@ -145,7 +145,7 @@ const char* StringsStorage::GetVFormatted(const char* format, va_list args) { return format; } uint32_t hash = HashSequentialString( - str.start(), len, HEAP->StringHashSeed()); + str.start(), len, HEAP->HashSeed()); return AddOrDisposeString(str.start(), hash); } @@ -156,7 +156,7 @@ const char* StringsStorage::GetName(String* name) { SmartArrayPointer<char> data = name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL, 0, length); uint32_t hash = - HashSequentialString(*data, length, name->GetHeap()->StringHashSeed()); + HashSequentialString(*data, length, name->GetHeap()->HashSeed()); return AddOrDisposeString(data.Detach(), hash); } return ""; @@ -181,18 +181,21 @@ void CodeEntry::CopyData(const CodeEntry& source) { uint32_t CodeEntry::GetCallUid() const { - uint32_t hash = ComputeIntegerHash(tag_); + uint32_t hash = ComputeIntegerHash(tag_, v8::internal::kZeroHashSeed); if (shared_id_ != 0) { - hash ^= ComputeIntegerHash( - static_cast<uint32_t>(shared_id_)); + hash ^= ComputeIntegerHash(static_cast<uint32_t>(shared_id_), + v8::internal::kZeroHashSeed); } else { hash ^= ComputeIntegerHash( - static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name_prefix_))); + static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name_prefix_)), + v8::internal::kZeroHashSeed); hash ^= ComputeIntegerHash( - static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name_))); + static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name_)), + v8::internal::kZeroHashSeed); hash ^= ComputeIntegerHash( - static_cast<uint32_t>(reinterpret_cast<uintptr_t>(resource_name_))); - hash ^= ComputeIntegerHash(line_number_); + static_cast<uint32_t>(reinterpret_cast<uintptr_t>(resource_name_)), + v8::internal::kZeroHashSeed); + hash ^= ComputeIntegerHash(line_number_, v8::internal::kZeroHashSeed); } return hash; } @@ -901,7 +904,7 @@ void ProfileGenerator::RecordTickSample(const TickSample& sample) { entry++; } - for (const Address *stack_pos = sample.stack, + for (const Address* stack_pos = sample.stack, *stack_end = stack_pos + sample.frames_count; stack_pos != stack_end; ++stack_pos) { @@ -1228,10 +1231,10 @@ HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection, entries_sorted_(false) { STATIC_ASSERT( sizeof(HeapGraphEdge) == - SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapGraphEdgeSize); // NOLINT + SnapshotSizeConstants<kPointerSize>::kExpectedHeapGraphEdgeSize); STATIC_ASSERT( sizeof(HeapEntry) == - SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapEntrySize); // NOLINT + SnapshotSizeConstants<kPointerSize>::kExpectedHeapEntrySize); for (int i = 0; i < VisitorSynchronization::kNumberOfSyncTags; ++i) { gc_subroot_entries_[i] = NULL; } @@ -1506,10 +1509,11 @@ uint64_t HeapObjectsMap::GenerateId(v8::RetainedObjectInfo* info) { const char* label = info->GetLabel(); id ^= HashSequentialString(label, static_cast<int>(strlen(label)), - HEAP->StringHashSeed()); + HEAP->HashSeed()); intptr_t element_count = info->GetElementCount(); if (element_count != -1) - id ^= ComputeIntegerHash(static_cast<uint32_t>(element_count)); + id ^= ComputeIntegerHash(static_cast<uint32_t>(element_count), + v8::internal::kZeroHashSeed); return id << 1; } @@ -1591,7 +1595,7 @@ Handle<HeapObject> HeapSnapshotsCollection::FindHeapObjectById(uint64_t id) { } -HeapEntry *const HeapEntriesMap::kHeapEntryPlaceholder = +HeapEntry* const HeapEntriesMap::kHeapEntryPlaceholder = reinterpret_cast<HeapEntry*>(1); HeapEntriesMap::HeapEntriesMap() @@ -1720,16 +1724,16 @@ void HeapObjectsSet::SetTag(Object* obj, const char* tag) { } -HeapObject *const V8HeapExplorer::kInternalRootObject = +HeapObject* const V8HeapExplorer::kInternalRootObject = reinterpret_cast<HeapObject*>( static_cast<intptr_t>(HeapObjectsMap::kInternalRootObjectId)); -HeapObject *const V8HeapExplorer::kGcRootsObject = +HeapObject* const V8HeapExplorer::kGcRootsObject = reinterpret_cast<HeapObject*>( static_cast<intptr_t>(HeapObjectsMap::kGcRootsObjectId)); -HeapObject *const V8HeapExplorer::kFirstGcSubrootObject = +HeapObject* const V8HeapExplorer::kFirstGcSubrootObject = reinterpret_cast<HeapObject*>( static_cast<intptr_t>(HeapObjectsMap::kGcRootsFirstSubrootId)); -HeapObject *const V8HeapExplorer::kLastGcSubrootObject = +HeapObject* const V8HeapExplorer::kLastGcSubrootObject = reinterpret_cast<HeapObject*>( static_cast<intptr_t>(HeapObjectsMap::kFirstAvailableObjectId)); @@ -2226,13 +2230,13 @@ void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, break; case CALLBACKS: { Object* callback_obj = descs->GetValue(i); - if (callback_obj->IsFixedArray()) { - FixedArray* accessors = FixedArray::cast(callback_obj); - if (Object* getter = accessors->get(JSObject::kGetterIndex)) { + if (callback_obj->IsAccessorPair()) { + AccessorPair* accessors = AccessorPair::cast(callback_obj); + if (Object* getter = accessors->getter()) { SetPropertyReference(js_obj, entry, descs->GetKey(i), getter, "get-%s"); } - if (Object* setter = accessors->get(JSObject::kSetterIndex)) { + if (Object* setter = accessors->setter()) { SetPropertyReference(js_obj, entry, descs->GetKey(i), setter, "set-%s"); } @@ -2285,7 +2289,7 @@ void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj, } } } else if (js_obj->HasDictionaryElements()) { - NumberDictionary* dictionary = js_obj->element_dictionary(); + SeededNumberDictionary* dictionary = js_obj->element_dictionary(); int length = dictionary->Capacity(); for (int i = 0; i < length; ++i) { Object* k = dictionary->KeyAt(i); diff --git a/deps/v8/src/profile-generator.h b/deps/v8/src/profile-generator.h index b47ce8255a8..aefe1a0f607 100644 --- a/deps/v8/src/profile-generator.h +++ b/deps/v8/src/profile-generator.h @@ -750,7 +750,8 @@ class HeapObjectsMap { static uint32_t AddressHash(Address addr) { return ComputeIntegerHash( - static_cast<uint32_t>(reinterpret_cast<uintptr_t>(addr))); + static_cast<uint32_t>(reinterpret_cast<uintptr_t>(addr)), + v8::internal::kZeroHashSeed); } bool initial_fill_mode_; @@ -833,7 +834,7 @@ class HeapEntriesMap { int total_children_count() { return total_children_count_; } int total_retainers_count() { return total_retainers_count_; } - static HeapEntry *const kHeapEntryPlaceholder; + static HeapEntry* const kHeapEntryPlaceholder; private: struct EntryInfo { @@ -851,7 +852,8 @@ class HeapEntriesMap { static uint32_t Hash(HeapThing thing) { return ComputeIntegerHash( - static_cast<uint32_t>(reinterpret_cast<uintptr_t>(thing))); + static_cast<uint32_t>(reinterpret_cast<uintptr_t>(thing)), + v8::internal::kZeroHashSeed); } static bool HeapThingsMatch(HeapThing key1, HeapThing key2) { return key1 == key2; @@ -1047,7 +1049,8 @@ class NativeObjectsExplorer : public HeapEntriesAllocator { void VisitSubtreeWrapper(Object** p, uint16_t class_id); static uint32_t InfoHash(v8::RetainedObjectInfo* info) { - return ComputeIntegerHash(static_cast<uint32_t>(info->GetHash())); + return ComputeIntegerHash(static_cast<uint32_t>(info->GetHash()), + v8::internal::kZeroHashSeed); } static bool RetainedInfosMatch(void* key1, void* key2) { return key1 == key2 || @@ -1125,7 +1128,8 @@ class HeapSnapshotJSONSerializer { INLINE(static uint32_t ObjectHash(const void* key)) { return ComputeIntegerHash( - static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key))); + static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)), + v8::internal::kZeroHashSeed); } void EnumerateNodes(); diff --git a/deps/v8/src/runtime-profiler.cc b/deps/v8/src/runtime-profiler.cc index eaa6e15603a..f89d98529b0 100644 --- a/deps/v8/src/runtime-profiler.cc +++ b/deps/v8/src/runtime-profiler.cc @@ -65,7 +65,7 @@ Atomic32 RuntimeProfiler::state_ = 0; Semaphore* RuntimeProfiler::semaphore_ = OS::CreateSemaphore(0); #ifdef DEBUG -bool RuntimeProfiler::has_been_globally_setup_ = false; +bool RuntimeProfiler::has_been_globally_set_up_ = false; #endif bool RuntimeProfiler::enabled_ = false; @@ -82,10 +82,10 @@ RuntimeProfiler::RuntimeProfiler(Isolate* isolate) void RuntimeProfiler::GlobalSetup() { - ASSERT(!has_been_globally_setup_); + ASSERT(!has_been_globally_set_up_); enabled_ = V8::UseCrankshaft() && FLAG_opt; #ifdef DEBUG - has_been_globally_setup_ = true; + has_been_globally_set_up_ = true; #endif } @@ -245,8 +245,8 @@ void RuntimeProfiler::NotifyTick() { } -void RuntimeProfiler::Setup() { - ASSERT(has_been_globally_setup_); +void RuntimeProfiler::SetUp() { + ASSERT(has_been_globally_set_up_); ClearSampleBuffer(); // If the ticker hasn't already started, make sure to do so to get // the ticks for the runtime profiler. diff --git a/deps/v8/src/runtime-profiler.h b/deps/v8/src/runtime-profiler.h index 15c209713e9..d35b5df847a 100644 --- a/deps/v8/src/runtime-profiler.h +++ b/deps/v8/src/runtime-profiler.h @@ -46,7 +46,7 @@ class RuntimeProfiler { static void GlobalSetup(); static inline bool IsEnabled() { - ASSERT(has_been_globally_setup_); + ASSERT(has_been_globally_set_up_); return enabled_; } @@ -54,7 +54,7 @@ class RuntimeProfiler { void NotifyTick(); - void Setup(); + void SetUp(); void Reset(); void TearDown(); @@ -126,7 +126,7 @@ class RuntimeProfiler { static Semaphore* semaphore_; #ifdef DEBUG - static bool has_been_globally_setup_; + static bool has_been_globally_set_up_; #endif static bool enabled_; }; diff --git a/deps/v8/src/runtime.cc b/deps/v8/src/runtime.cc index 811d72d91d6..fb3621341ab 100644 --- a/deps/v8/src/runtime.cc +++ b/deps/v8/src/runtime.cc @@ -228,7 +228,7 @@ MUST_USE_RESULT static MaybeObject* DeepCopyBoilerplate(Isolate* isolate, break; } case DICTIONARY_ELEMENTS: { - NumberDictionary* element_dictionary = copy->element_dictionary(); + SeededNumberDictionary* element_dictionary = copy->element_dictionary(); int capacity = element_dictionary->Capacity(); for (int i = 0; i < capacity; i++) { Object* k = element_dictionary->KeyAt(i); @@ -355,7 +355,7 @@ static Handle<Object> CreateObjectLiteralBoilerplate( Handle<JSObject> boilerplate = isolate->factory()->NewJSObjectFromMap(map); // Normalize the elements of the boilerplate to save space if needed. - if (!should_have_fast_elements) NormalizeElements(boilerplate); + if (!should_have_fast_elements) JSObject::NormalizeElements(boilerplate); // Add the constant properties to the boilerplate. int length = constant_properties->length(); @@ -365,7 +365,8 @@ static Handle<Object> CreateObjectLiteralBoilerplate( // Normalize the properties of object to avoid n^2 behavior // when extending the object multiple properties. Indicate the number of // properties to be added. - NormalizeProperties(boilerplate, KEEP_INOBJECT_PROPERTIES, length / 2); + JSObject::NormalizeProperties( + boilerplate, KEEP_INOBJECT_PROPERTIES, length / 2); } for (int index = 0; index < length; index +=2) { @@ -383,22 +384,18 @@ static Handle<Object> CreateObjectLiteralBoilerplate( if (key->IsSymbol()) { if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) { // Array index as string (uint32). - result = SetOwnElement(boilerplate, - element_index, - value, - kNonStrictMode); + result = JSObject::SetOwnElement( + boilerplate, element_index, value, kNonStrictMode); } else { Handle<String> name(String::cast(*key)); ASSERT(!name->AsArrayIndex(&element_index)); - result = SetLocalPropertyIgnoreAttributes(boilerplate, name, - value, NONE); + result = JSObject::SetLocalPropertyIgnoreAttributes( + boilerplate, name, value, NONE); } } else if (key->ToArrayIndex(&element_index)) { // Array index (uint32). - result = SetOwnElement(boilerplate, - element_index, - value, - kNonStrictMode); + result = JSObject::SetOwnElement( + boilerplate, element_index, value, kNonStrictMode); } else { // Non-uint32 number. ASSERT(key->IsNumber()); @@ -408,8 +405,8 @@ static Handle<Object> CreateObjectLiteralBoilerplate( const char* str = DoubleToCString(num, buffer); Handle<String> name = isolate->factory()->NewStringFromAscii(CStrVector(str)); - result = SetLocalPropertyIgnoreAttributes(boilerplate, name, - value, NONE); + result = JSObject::SetLocalPropertyIgnoreAttributes( + boilerplate, name, value, NONE); } // If setting the property on the boilerplate throws an // exception, the exception is converted to an empty handle in @@ -423,8 +420,8 @@ static Handle<Object> CreateObjectLiteralBoilerplate( // computed properties have been assigned so that we can generate // constant function properties. if (should_transform && !has_function_literal) { - TransformToFastProperties(boilerplate, - boilerplate->map()->unused_property_fields()); + JSObject::TransformToFastProperties( + boilerplate, boilerplate->map()->unused_property_fields()); } return boilerplate; @@ -434,7 +431,6 @@ static Handle<Object> CreateObjectLiteralBoilerplate( static const int kSmiOnlyLiteralMinimumLength = 1024; -// static Handle<Object> Runtime::CreateArrayLiteralBoilerplate( Isolate* isolate, Handle<FixedArray> literals, @@ -1048,26 +1044,26 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOwnProperty) { holder = Handle<JSObject>(JSObject::cast(proto)); } FixedArray* elements = FixedArray::cast(holder->elements()); - NumberDictionary* dictionary = NULL; + SeededNumberDictionary* dictionary = NULL; if (elements->map() == heap->non_strict_arguments_elements_map()) { - dictionary = NumberDictionary::cast(elements->get(1)); + dictionary = SeededNumberDictionary::cast(elements->get(1)); } else { - dictionary = NumberDictionary::cast(elements); + dictionary = SeededNumberDictionary::cast(elements); } int entry = dictionary->FindEntry(index); - ASSERT(entry != NumberDictionary::kNotFound); + ASSERT(entry != SeededNumberDictionary::kNotFound); PropertyDetails details = dictionary->DetailsAt(entry); switch (details.type()) { case CALLBACKS: { // This is an accessor property with getter and/or setter. - FixedArray* callbacks = - FixedArray::cast(dictionary->ValueAt(entry)); + AccessorPair* accessors = + AccessorPair::cast(dictionary->ValueAt(entry)); elms->set(IS_ACCESSOR_INDEX, heap->true_value()); if (CheckElementAccess(*obj, index, v8::ACCESS_GET)) { - elms->set(GETTER_INDEX, callbacks->get(0)); + elms->set(GETTER_INDEX, accessors->getter()); } if (CheckElementAccess(*obj, index, v8::ACCESS_SET)) { - elms->set(SETTER_INDEX, callbacks->get(1)); + elms->set(SETTER_INDEX, accessors->setter()); } break; } @@ -1106,18 +1102,18 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOwnProperty) { elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!result.IsDontDelete())); bool is_js_accessor = (result.type() == CALLBACKS) && - (result.GetCallbackObject()->IsFixedArray()); + (result.GetCallbackObject()->IsAccessorPair()); if (is_js_accessor) { // __defineGetter__/__defineSetter__ callback. elms->set(IS_ACCESSOR_INDEX, heap->true_value()); - FixedArray* structure = FixedArray::cast(result.GetCallbackObject()); + AccessorPair* accessors = AccessorPair::cast(result.GetCallbackObject()); if (CheckAccess(*obj, *name, &result, v8::ACCESS_GET)) { - elms->set(GETTER_INDEX, structure->get(0)); + elms->set(GETTER_INDEX, accessors->getter()); } if (CheckAccess(*obj, *name, &result, v8::ACCESS_SET)) { - elms->set(SETTER_INDEX, structure->get(1)); + elms->set(SETTER_INDEX, accessors->setter()); } } else { elms->set(IS_ACCESSOR_INDEX, heap->false_value()); @@ -1335,21 +1331,19 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { } PropertyAttributes attributes = static_cast<PropertyAttributes>(attr); - RETURN_IF_EMPTY_HANDLE(isolate, - SetLocalPropertyIgnoreAttributes(global, - name, - value, - attributes)); + RETURN_IF_EMPTY_HANDLE( + isolate, + JSObject::SetLocalPropertyIgnoreAttributes(global, name, value, + attributes)); } else { LanguageMode language_mode = DeclareGlobalsLanguageMode::decode(flags); StrictModeFlag strict_mode_flag = (language_mode == CLASSIC_MODE) ? kNonStrictMode : kStrictMode; - RETURN_IF_EMPTY_HANDLE(isolate, - SetProperty(global, - name, - value, - static_cast<PropertyAttributes>(attr), - strict_mode_flag)); + RETURN_IF_EMPTY_HANDLE( + isolate, + JSReceiver::SetProperty(global, name, value, + static_cast<PropertyAttributes>(attr), + strict_mode_flag)); } } @@ -1403,7 +1397,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) { Handle<JSObject> object = Handle<JSObject>::cast(holder); RETURN_IF_EMPTY_HANDLE( isolate, - SetProperty(object, name, initial_value, mode, kNonStrictMode)); + JSReceiver::SetProperty(object, name, initial_value, mode, + kNonStrictMode)); } } @@ -1443,9 +1438,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) { return ThrowRedeclarationError(isolate, "const", name); } } - RETURN_IF_EMPTY_HANDLE(isolate, - SetProperty(object, name, value, mode, - kNonStrictMode)); + RETURN_IF_EMPTY_HANDLE( + isolate, + JSReceiver::SetProperty(object, name, value, mode, kNonStrictMode)); } return isolate->heap()->undefined_value(); @@ -1554,12 +1549,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) { // property through an interceptor and only do it if it's // uninitialized, e.g. the hole. Nirk... // Passing non-strict mode because the property is writable. - RETURN_IF_EMPTY_HANDLE(isolate, - SetProperty(global, - name, - value, - attributes, - kNonStrictMode)); + RETURN_IF_EMPTY_HANDLE( + isolate, + JSReceiver::SetProperty(global, name, value, attributes, + kNonStrictMode)); return *value; } @@ -1629,7 +1622,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) { // Strict mode not needed (const disallowed in strict mode). RETURN_IF_EMPTY_HANDLE( isolate, - SetProperty(global, name, value, NONE, kNonStrictMode)); + JSReceiver::SetProperty(global, name, value, NONE, kNonStrictMode)); return *value; } @@ -1681,7 +1674,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) { // Strict mode not needed (const disallowed in strict mode). RETURN_IF_EMPTY_HANDLE( isolate, - SetProperty(object, name, value, attributes, kNonStrictMode)); + JSReceiver::SetProperty(object, name, value, attributes, + kNonStrictMode)); } } @@ -1696,7 +1690,7 @@ RUNTIME_FUNCTION(MaybeObject*, CONVERT_ARG_CHECKED(JSObject, object, 0); CONVERT_SMI_ARG_CHECKED(properties, 1); if (object->HasFastProperties()) { - NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties); + JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties); } return *object; } @@ -1852,7 +1846,7 @@ static Handle<JSFunction> InstallBuiltin(Isolate* isolate, code, false); optimized->shared()->DontAdaptArguments(); - SetProperty(holder, key, optimized, NONE, kStrictMode); + JSReceiver::SetProperty(holder, key, optimized, NONE, kStrictMode); return optimized; } @@ -4066,8 +4060,7 @@ MaybeObject* Runtime::GetElementOrCharAt(Isolate* isolate, } if (object->IsString() || object->IsNumber() || object->IsBoolean()) { - Handle<Object> prototype = GetPrototype(object); - return prototype->GetElement(index); + return object->GetPrototype()->GetElement(index); } return object->GetElement(index); @@ -4134,8 +4127,8 @@ MaybeObject* TransitionElements(Handle<Object> object, ElementsKind from_kind = Handle<JSObject>::cast(object)->map()->elements_kind(); if (Map::IsValidElementsTransition(from_kind, to_kind)) { - Handle<Object> result = - TransitionElementsKind(Handle<JSObject>::cast(object), to_kind); + Handle<Object> result = JSObject::TransitionElementsKind( + Handle<JSObject>::cast(object), to_kind); if (result.is_null()) return isolate->ThrowIllegalOperation(); return *result; } @@ -4307,12 +4300,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) { return isolate->Throw(*error); } - Handle<NumberDictionary> dictionary = NormalizeElements(js_object); + Handle<SeededNumberDictionary> dictionary = + JSObject::NormalizeElements(js_object); // Make sure that we never go back to fast case. dictionary->set_requires_slow_elements(); PropertyDetails details = PropertyDetails(attr, NORMAL); - Handle<NumberDictionary> extended_dictionary = - NumberDictionarySet(dictionary, index, obj_value, details); + Handle<SeededNumberDictionary> extended_dictionary = + SeededNumberDictionary::Set(dictionary, index, obj_value, details); if (*extended_dictionary != *dictionary) { if (js_object->GetElementsKind() == NON_STRICT_ARGUMENTS_ELEMENTS) { FixedArray::cast(js_object->elements())->set(1, *extended_dictionary); @@ -4362,7 +4356,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) { // we don't have to check for null. js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype())); } - NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0); + JSObject::NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0); // Use IgnoreAttributes version since a readonly property may be // overridden and SetProperty does not allow this. return js_object->SetLocalPropertyIgnoreAttributes(*name, @@ -4387,12 +4381,13 @@ static MaybeObject* NormalizeObjectSetElement(Isolate* isolate, Handle<Object> value, PropertyAttributes attr) { // Normalize the elements to enable attributes on the property. - Handle<NumberDictionary> dictionary = NormalizeElements(js_object); + Handle<SeededNumberDictionary> dictionary = + JSObject::NormalizeElements(js_object); // Make sure that we never go back to fast case. dictionary->set_requires_slow_elements(); PropertyDetails details = PropertyDetails(attr, NORMAL); - Handle<NumberDictionary> extended_dictionary = - NumberDictionarySet(dictionary, index, value, details); + Handle<SeededNumberDictionary> extended_dictionary = + SeededNumberDictionary::Set(dictionary, index, value, details); if (*extended_dictionary != *dictionary) { js_object->set_elements(*extended_dictionary); } @@ -4447,7 +4442,8 @@ MaybeObject* Runtime::SetObjectProperty(Isolate* isolate, return NormalizeObjectSetElement(isolate, js_object, index, value, attr); } - Handle<Object> result = SetElement(js_object, index, value, strict_mode); + Handle<Object> result = + JSObject::SetElement(js_object, index, value, strict_mode); if (result.is_null()) return Failure::Exception(); return *value; } @@ -4462,11 +4458,13 @@ MaybeObject* Runtime::SetObjectProperty(Isolate* isolate, value, attr); } - result = SetElement(js_object, index, value, strict_mode); + result = + JSObject::SetElement(js_object, index, value, strict_mode); } else { Handle<String> key_string = Handle<String>::cast(key); key_string->TryFlatten(); - result = SetProperty(js_object, key_string, value, attr, strict_mode); + result = JSReceiver::SetProperty( + js_object, key_string, value, attr, strict_mode); } if (result.is_null()) return Failure::Exception(); return *value; @@ -4655,8 +4653,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreArrayLiteralElement) { if (value->IsNumber()) { ASSERT(elements_kind == FAST_SMI_ONLY_ELEMENTS); - TransitionElementsKind(object, FAST_DOUBLE_ELEMENTS); - TransitionElementsKind(boilerplate_object, FAST_DOUBLE_ELEMENTS); + JSObject::TransitionElementsKind(object, FAST_DOUBLE_ELEMENTS); + JSObject::TransitionElementsKind(boilerplate_object, FAST_DOUBLE_ELEMENTS); ASSERT(object->GetElementsKind() == FAST_DOUBLE_ELEMENTS); FixedDoubleArray* double_array = FixedDoubleArray::cast(object->elements()); @@ -4665,8 +4663,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreArrayLiteralElement) { } else { ASSERT(elements_kind == FAST_SMI_ONLY_ELEMENTS || elements_kind == FAST_DOUBLE_ELEMENTS); - TransitionElementsKind(object, FAST_ELEMENTS); - TransitionElementsKind(boilerplate_object, FAST_ELEMENTS); + JSObject::TransitionElementsKind(object, FAST_ELEMENTS); + JSObject::TransitionElementsKind(boilerplate_object, FAST_ELEMENTS); FixedArray* object_array = FixedArray::cast(object->elements()); object_array->set(store_index, *value); @@ -4818,15 +4816,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_IsPropertyEnumerable) { object = JSObject::cast(proto); } FixedArray* elements = FixedArray::cast(object->elements()); - NumberDictionary* dictionary = NULL; + SeededNumberDictionary* dictionary = NULL; if (elements->map() == isolate->heap()->non_strict_arguments_elements_map()) { - dictionary = NumberDictionary::cast(elements->get(1)); + dictionary = SeededNumberDictionary::cast(elements->get(1)); } else { - dictionary = NumberDictionary::cast(elements); + dictionary = SeededNumberDictionary::cast(elements); } int entry = dictionary->FindEntry(index); - ASSERT(entry != NumberDictionary::kNotFound); + ASSERT(entry != SeededNumberDictionary::kNotFound); PropertyDetails details = dictionary->DetailsAt(entry); return isolate->heap()->ToBoolean(!details.IsDontEnum()); } @@ -5144,31 +5142,20 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArgumentsProperty) { RUNTIME_FUNCTION(MaybeObject*, Runtime_ToFastProperties) { - HandleScope scope(isolate); - ASSERT(args.length() == 1); - Handle<Object> object = args.at<Object>(0); - if (object->IsJSObject()) { - Handle<JSObject> js_object = Handle<JSObject>::cast(object); - if (!js_object->HasFastProperties() && !js_object->IsGlobalObject()) { - MaybeObject* ok = js_object->TransformToFastProperties(0); - if (ok->IsRetryAfterGC()) return ok; - } - } - return *object; + Object* object = args[0]; + return (object->IsJSObject() && !object->IsGlobalObject()) + ? JSObject::cast(object)->TransformToFastProperties(0) + : object; } RUNTIME_FUNCTION(MaybeObject*, Runtime_ToSlowProperties) { - HandleScope scope(isolate); - ASSERT(args.length() == 1); - Handle<Object> object = args.at<Object>(0); - if (object->IsJSObject() && !object->IsJSGlobalProxy()) { - Handle<JSObject> js_object = Handle<JSObject>::cast(object); - NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0); - } - return *object; + Object* obj = args[0]; + return (obj->IsJSObject() && !obj->IsJSGlobalProxy()) + ? JSObject::cast(obj)->NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0) + : obj; } @@ -9133,7 +9120,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreContextSlot) { (object->GetLocalPropertyAttribute(*name) == ABSENT)) { RETURN_IF_EMPTY_HANDLE( isolate, - SetProperty(object, name, value, NONE, strict_mode)); + JSReceiver::SetProperty(object, name, value, NONE, strict_mode)); } else if (strict_mode == kStrictMode && (attributes & READ_ONLY) != 0) { // Setting read only property in strict mode. Handle<Object> error = @@ -9386,20 +9373,18 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ParseJson) { bool CodeGenerationFromStringsAllowed(Isolate* isolate, Handle<Context> context) { - if (context->allow_code_gen_from_strings()->IsFalse()) { - // Check with callback if set. - AllowCodeGenerationFromStringsCallback callback = - isolate->allow_code_gen_callback(); - if (callback == NULL) { - // No callback set and code generation disallowed. - return false; - } else { - // Callback set. Let it decide if code generation is allowed. - VMState state(isolate, EXTERNAL); - return callback(v8::Utils::ToLocal(context)); - } + ASSERT(context->allow_code_gen_from_strings()->IsFalse()); + // Check with callback if set. + AllowCodeGenerationFromStringsCallback callback = + isolate->allow_code_gen_callback(); + if (callback == NULL) { + // No callback set and code generation disallowed. + return false; + } else { + // Callback set. Let it decide if code generation is allowed. + VMState state(isolate, EXTERNAL); + return callback(v8::Utils::ToLocal(context)); } - return true; } @@ -9413,7 +9398,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) { // Check if global context allows code generation from // strings. Throw an exception if it doesn't. - if (!CodeGenerationFromStringsAllowed(isolate, context)) { + if (context->allow_code_gen_from_strings()->IsFalse() && + !CodeGenerationFromStringsAllowed(isolate, context)) { return isolate->Throw(*isolate->factory()->NewError( "code_gen_from_strings", HandleVector<Object>(NULL, 0))); } @@ -9440,7 +9426,8 @@ static ObjectPair CompileGlobalEval(Isolate* isolate, // Check if global context allows code generation from // strings. Throw an exception if it doesn't. - if (!CodeGenerationFromStringsAllowed(isolate, global_context)) { + if (global_context->allow_code_gen_from_strings()->IsFalse() && + !CodeGenerationFromStringsAllowed(isolate, global_context)) { isolate->Throw(*isolate->factory()->NewError( "code_gen_from_strings", HandleVector<Object>(NULL, 0))); return MakePair(Failure::Exception(), NULL); @@ -9596,8 +9583,9 @@ class ArrayConcatVisitor { // Fall-through to dictionary mode. } ASSERT(!fast_elements_); - Handle<NumberDictionary> dict(NumberDictionary::cast(*storage_)); - Handle<NumberDictionary> result = + Handle<SeededNumberDictionary> dict( + SeededNumberDictionary::cast(*storage_)); + Handle<SeededNumberDictionary> result = isolate_->factory()->DictionaryAtNumberPut(dict, index, elm); if (!result.is_identical_to(dict)) { // Dictionary needed to grow. @@ -9637,14 +9625,15 @@ class ArrayConcatVisitor { void SetDictionaryMode(uint32_t index) { ASSERT(fast_elements_); Handle<FixedArray> current_storage(*storage_); - Handle<NumberDictionary> slow_storage( - isolate_->factory()->NewNumberDictionary(current_storage->length())); + Handle<SeededNumberDictionary> slow_storage( + isolate_->factory()->NewSeededNumberDictionary( + current_storage->length())); uint32_t current_length = static_cast<uint32_t>(current_storage->length()); for (uint32_t i = 0; i < current_length; i++) { HandleScope loop_scope; Handle<Object> element(current_storage->get(i)); if (!element->IsTheHole()) { - Handle<NumberDictionary> new_storage = + Handle<SeededNumberDictionary> new_storage = isolate_->factory()->DictionaryAtNumberPut(slow_storage, i, element); if (!new_storage.is_identical_to(slow_storage)) { slow_storage = loop_scope.CloseAndEscape(new_storage); @@ -9696,8 +9685,8 @@ static uint32_t EstimateElementCount(Handle<JSArray> array) { UNREACHABLE(); break; case DICTIONARY_ELEMENTS: { - Handle<NumberDictionary> dictionary( - NumberDictionary::cast(array->elements())); + Handle<SeededNumberDictionary> dictionary( + SeededNumberDictionary::cast(array->elements())); int capacity = dictionary->Capacity(); for (int i = 0; i < capacity; i++) { Handle<Object> key(dictionary->KeyAt(i)); @@ -9800,7 +9789,8 @@ static void CollectElementIndices(Handle<JSObject> object, break; } case DICTIONARY_ELEMENTS: { - Handle<NumberDictionary> dict(NumberDictionary::cast(object->elements())); + Handle<SeededNumberDictionary> dict( + SeededNumberDictionary::cast(object->elements())); uint32_t capacity = dict->Capacity(); for (uint32_t j = 0; j < capacity; j++) { HandleScope loop_scope; @@ -9935,7 +9925,7 @@ static bool IterateElements(Isolate* isolate, break; } case DICTIONARY_ELEMENTS: { - Handle<NumberDictionary> dict(receiver->element_dictionary()); + Handle<SeededNumberDictionary> dict(receiver->element_dictionary()); List<uint32_t> indices(dict->Capacity() / 2); // Collect all indices in the object and the prototypes less // than length. This might introduce duplicates in the indices list. @@ -10049,7 +10039,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) { // FAST_ELEMENTS. if (array->HasFastDoubleElements()) { array = Handle<JSArray>::cast( - TransitionElementsKind(array, FAST_ELEMENTS)); + JSObject::TransitionElementsKind(array, FAST_ELEMENTS)); } length_estimate = static_cast<uint32_t>(array->length()->Number()); @@ -10091,7 +10081,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) { uint32_t at_least_space_for = estimate_nof_elements + (estimate_nof_elements >> 2); storage = Handle<FixedArray>::cast( - isolate->factory()->NewNumberDictionary(at_least_space_for)); + isolate->factory()->NewSeededNumberDictionary(at_least_space_for)); } ArrayConcatVisitor visitor(isolate, storage, fast_case); @@ -10179,7 +10169,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_EstimateNumberOfElements) { CONVERT_CHECKED(JSObject, object, args[0]); HeapObject* elements = object->elements(); if (elements->IsDictionary()) { - return Smi::FromInt(NumberDictionary::cast(elements)->NumberOfElements()); + int result = SeededNumberDictionary::cast(elements)->NumberOfElements(); + return Smi::FromInt(result); } else if (object->IsJSArray()) { return JSArray::cast(object)->length(); } else { @@ -10209,10 +10200,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SwapElements) { Handle<Object> tmp2 = Object::GetElement(jsobject, index2); RETURN_IF_EMPTY_HANDLE(isolate, tmp2); - RETURN_IF_EMPTY_HANDLE(isolate, - SetElement(jsobject, index1, tmp2, kStrictMode)); - RETURN_IF_EMPTY_HANDLE(isolate, - SetElement(jsobject, index2, tmp1, kStrictMode)); + RETURN_IF_EMPTY_HANDLE( + isolate, JSObject::SetElement(jsobject, index1, tmp2, kStrictMode)); + RETURN_IF_EMPTY_HANDLE( + isolate, JSObject::SetElement(jsobject, index2, tmp1, kStrictMode)); return isolate->heap()->undefined_value(); } @@ -10488,15 +10479,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPropertyDetails) { // If the callback object is a fixed array then it contains JavaScript // getter and/or setter. bool hasJavaScriptAccessors = result_type == CALLBACKS && - result_callback_obj->IsFixedArray(); + result_callback_obj->IsAccessorPair(); Handle<FixedArray> details = isolate->factory()->NewFixedArray(hasJavaScriptAccessors ? 5 : 2); details->set(0, *value); details->set(1, property_details); if (hasJavaScriptAccessors) { details->set(2, isolate->heap()->ToBoolean(caught_exception)); - details->set(3, FixedArray::cast(*result_callback_obj)->get(0)); - details->set(4, FixedArray::cast(*result_callback_obj)->get(1)); + details->set(3, AccessorPair::cast(*result_callback_obj)->getter()); + details->set(4, AccessorPair::cast(*result_callback_obj)->setter()); } return *isolate->factory()->NewJSArrayWithElements(details); diff --git a/deps/v8/src/scopes.cc b/deps/v8/src/scopes.cc index 4a6d0a7fae2..d0ee8ec7f21 100644 --- a/deps/v8/src/scopes.cc +++ b/deps/v8/src/scopes.cc @@ -808,7 +808,7 @@ void Scope::Print(int n) { PrintF(")"); } - PrintF(" {\n"); + PrintF(" { // (%d, %d)\n", start_position(), end_position()); // Function name, if any (named function literals, only). if (function_ != NULL) { diff --git a/deps/v8/src/spaces.cc b/deps/v8/src/spaces.cc index ebd3e651920..c8e94ddbe5a 100644 --- a/deps/v8/src/spaces.cc +++ b/deps/v8/src/spaces.cc @@ -132,7 +132,7 @@ CodeRange::CodeRange(Isolate* isolate) } -bool CodeRange::Setup(const size_t requested) { +bool CodeRange::SetUp(const size_t requested) { ASSERT(code_range_ == NULL); code_range_ = new VirtualMemory(requested); @@ -268,7 +268,7 @@ MemoryAllocator::MemoryAllocator(Isolate* isolate) } -bool MemoryAllocator::Setup(intptr_t capacity, intptr_t capacity_executable) { +bool MemoryAllocator::SetUp(intptr_t capacity, intptr_t capacity_executable) { capacity_ = RoundUp(capacity, Page::kPageSize); capacity_executable_ = RoundUp(capacity_executable, Page::kPageSize); ASSERT_GE(capacity_, capacity_executable_); @@ -658,7 +658,8 @@ PagedSpace::PagedSpace(Heap* heap, : Space(heap, id, executable), free_list_(this), was_swept_conservatively_(false), - first_unswept_page_(Page::FromAddress(NULL)) { + first_unswept_page_(Page::FromAddress(NULL)), + unswept_free_bytes_(0) { max_capacity_ = (RoundDown(max_capacity, Page::kPageSize) / Page::kPageSize) * Page::kObjectAreaSize; accounting_stats_.Clear(); @@ -670,12 +671,12 @@ PagedSpace::PagedSpace(Heap* heap, } -bool PagedSpace::Setup() { +bool PagedSpace::SetUp() { return true; } -bool PagedSpace::HasBeenSetup() { +bool PagedSpace::HasBeenSetUp() { return true; } @@ -873,9 +874,9 @@ void PagedSpace::Verify(ObjectVisitor* visitor) { // NewSpace implementation -bool NewSpace::Setup(int reserved_semispace_capacity, +bool NewSpace::SetUp(int reserved_semispace_capacity, int maximum_semispace_capacity) { - // Setup new space based on the preallocated memory block defined by + // Set up new space based on the preallocated memory block defined by // start and size. The provided space is divided into two semi-spaces. // To support fast containment testing in the new space, the size of // this chunk must be a power of two and it must be aligned to its size. @@ -894,7 +895,7 @@ bool NewSpace::Setup(int reserved_semispace_capacity, ASSERT(initial_semispace_capacity <= maximum_semispace_capacity); ASSERT(IsPowerOf2(maximum_semispace_capacity)); - // Allocate and setup the histogram arrays if necessary. + // Allocate and set up the histogram arrays if necessary. allocated_histogram_ = NewArray<HistogramInfo>(LAST_TYPE + 1); promoted_histogram_ = NewArray<HistogramInfo>(LAST_TYPE + 1); @@ -908,12 +909,12 @@ bool NewSpace::Setup(int reserved_semispace_capacity, 2 * heap()->ReservedSemiSpaceSize()); ASSERT(IsAddressAligned(chunk_base_, 2 * reserved_semispace_capacity, 0)); - if (!to_space_.Setup(chunk_base_, + if (!to_space_.SetUp(chunk_base_, initial_semispace_capacity, maximum_semispace_capacity)) { return false; } - if (!from_space_.Setup(chunk_base_ + reserved_semispace_capacity, + if (!from_space_.SetUp(chunk_base_ + reserved_semispace_capacity, initial_semispace_capacity, maximum_semispace_capacity)) { return false; @@ -1148,7 +1149,7 @@ void NewSpace::Verify() { // ----------------------------------------------------------------------------- // SemiSpace implementation -bool SemiSpace::Setup(Address start, +bool SemiSpace::SetUp(Address start, int initial_capacity, int maximum_capacity) { // Creates a space in the young generation. The constructor does not @@ -2062,6 +2063,7 @@ void PagedSpace::PrepareForMarkCompact() { } while (p != anchor()); } first_unswept_page_ = Page::FromAddress(NULL); + unswept_free_bytes_ = 0; // Clear the free list before a full GC---it will be rebuilt afterward. free_list_.Reset(); @@ -2110,6 +2112,7 @@ bool PagedSpace::AdvanceSweeper(intptr_t bytes_to_sweep) { PrintF("Sweeping 0x%" V8PRIxPTR " lazily advanced.\n", reinterpret_cast<intptr_t>(p)); } + unswept_free_bytes_ -= (Page::kObjectAreaSize - p->LiveBytes()); freed_bytes += MarkCompactCollector::SweepConservatively(this, p); } p = next_page; @@ -2408,7 +2411,7 @@ LargeObjectSpace::LargeObjectSpace(Heap* heap, objects_size_(0) {} -bool LargeObjectSpace::Setup() { +bool LargeObjectSpace::SetUp() { first_page_ = NULL; size_ = 0; page_count_ = 0; @@ -2428,7 +2431,7 @@ void LargeObjectSpace::TearDown() { space, kAllocationActionFree, page->size()); heap()->isolate()->memory_allocator()->Free(page); } - Setup(); + SetUp(); } diff --git a/deps/v8/src/spaces.h b/deps/v8/src/spaces.h index 41bfec90f14..41c3ef929f7 100644 --- a/deps/v8/src/spaces.h +++ b/deps/v8/src/spaces.h @@ -815,7 +815,7 @@ class CodeRange { // Reserves a range of virtual memory, but does not commit any of it. // Can only be called once, at heap initialization time. // Returns false on failure. - bool Setup(const size_t requested_size); + bool SetUp(const size_t requested_size); // Frees the range of virtual memory, and frees the data structures used to // manage it. @@ -943,7 +943,7 @@ class MemoryAllocator { // Initializes its internal bookkeeping structures. // Max capacity of the total space and executable memory limit. - bool Setup(intptr_t max_capacity, intptr_t capacity_executable); + bool SetUp(intptr_t max_capacity, intptr_t capacity_executable); void TearDown(); @@ -1419,11 +1419,11 @@ class PagedSpace : public Space { // the memory allocator's initial chunk) if possible. If the block of // addresses is not big enough to contain a single page-aligned page, a // fresh chunk will be allocated. - bool Setup(); + bool SetUp(); // Returns true if the space has been successfully set up and not // subsequently torn down. - bool HasBeenSetup(); + bool HasBeenSetUp(); // Cleans up the space, frees all pages in this space except those belonging // to the initial chunk, uncommits addresses in the initial chunk. @@ -1469,9 +1469,12 @@ class PagedSpace : public Space { // linear allocation area (between top and limit) are also counted here. virtual intptr_t Size() { return accounting_stats_.Size(); } - // As size, but the bytes in the current linear allocation area are not - // included. - virtual intptr_t SizeOfObjects() { return Size() - (limit() - top()); } + // As size, but the bytes in lazily swept pages are estimated and the bytes + // in the current linear allocation area are not included. + virtual intptr_t SizeOfObjects() { + ASSERT(!IsSweepingComplete() || (unswept_free_bytes_ == 0)); + return Size() - unswept_free_bytes_ - (limit() - top()); + } // Wasted bytes in this space. These are just the bytes that were thrown away // due to being too small to use for allocation. They do not include the @@ -1479,9 +1482,7 @@ class PagedSpace : public Space { virtual intptr_t Waste() { return accounting_stats_.Waste(); } // Returns the allocation pointer in this space. - Address top() { - return allocation_info_.top; - } + Address top() { return allocation_info_.top; } Address limit() { return allocation_info_.limit; } // Allocate the requested number of bytes in the space if possible, return a @@ -1557,10 +1558,15 @@ class PagedSpace : public Space { } void SetPagesToSweep(Page* first) { + ASSERT(unswept_free_bytes_ == 0); if (first == &anchor_) first = NULL; first_unswept_page_ = first; } + void MarkPageForLazySweeping(Page* p) { + unswept_free_bytes_ += (Page::kObjectAreaSize - p->LiveBytes()); + } + bool AdvanceSweeper(intptr_t bytes_to_sweep); bool IsSweepingComplete() { @@ -1647,8 +1653,15 @@ class PagedSpace : public Space { bool was_swept_conservatively_; + // The first page to be swept when the lazy sweeper advances. Is set + // to NULL when all pages have been swept. Page* first_unswept_page_; + // The number of free bytes which could be reclaimed by advancing the + // lazy sweeper. This is only an estimation because lazy sweeping is + // done conservatively. + intptr_t unswept_free_bytes_; + // Expands the space by allocating a fixed number of pages. Returns false if // it cannot allocate requested number of pages from OS, or if the hard heap // size limit has been hit. @@ -1808,14 +1821,14 @@ class SemiSpace : public Space { current_page_(NULL) { } // Sets up the semispace using the given chunk. - bool Setup(Address start, int initial_capacity, int maximum_capacity); + bool SetUp(Address start, int initial_capacity, int maximum_capacity); // Tear down the space. Heap memory was not allocated by the space, so it // is not deallocated here. void TearDown(); // True if the space has been set up but not torn down. - bool HasBeenSetup() { return start_ != NULL; } + bool HasBeenSetUp() { return start_ != NULL; } // Grow the semispace to the new capacity. The new capacity // requested must be larger than the current capacity and less than @@ -2054,15 +2067,15 @@ class NewSpace : public Space { inline_allocation_limit_step_(0) {} // Sets up the new space using the given chunk. - bool Setup(int reserved_semispace_size_, int max_semispace_size); + bool SetUp(int reserved_semispace_size_, int max_semispace_size); // Tears down the space. Heap memory was not allocated by the space, so it // is not deallocated here. void TearDown(); // True if the space has been set up but not torn down. - bool HasBeenSetup() { - return to_space_.HasBeenSetup() && from_space_.HasBeenSetup(); + bool HasBeenSetUp() { + return to_space_.HasBeenSetUp() && from_space_.HasBeenSetUp(); } // Flip the pair of spaces. @@ -2461,7 +2474,7 @@ class LargeObjectSpace : public Space { virtual ~LargeObjectSpace() {} // Initializes internal data structures. - bool Setup(); + bool SetUp(); // Releases internal resources, frees objects in this space. void TearDown(); diff --git a/deps/v8/src/store-buffer.cc b/deps/v8/src/store-buffer.cc index 0f1fed0286e..9022b3be837 100644 --- a/deps/v8/src/store-buffer.cc +++ b/deps/v8/src/store-buffer.cc @@ -55,7 +55,7 @@ StoreBuffer::StoreBuffer(Heap* heap) } -void StoreBuffer::Setup() { +void StoreBuffer::SetUp() { virtual_memory_ = new VirtualMemory(kStoreBufferSize * 3); uintptr_t start_as_int = reinterpret_cast<uintptr_t>(virtual_memory_->address()); diff --git a/deps/v8/src/store-buffer.h b/deps/v8/src/store-buffer.h index 204fa3ff4e0..951a9ca2bc3 100644 --- a/deps/v8/src/store-buffer.h +++ b/deps/v8/src/store-buffer.h @@ -54,7 +54,7 @@ class StoreBuffer { inline Address TopAddress(); - void Setup(); + void SetUp(); void TearDown(); // This is used by the mutator to enter addresses into the store buffer. diff --git a/deps/v8/src/stub-cache.cc b/deps/v8/src/stub-cache.cc index 787e833f4f7..ec8f6bdf25b 100644 --- a/deps/v8/src/stub-cache.cc +++ b/deps/v8/src/stub-cache.cc @@ -678,11 +678,10 @@ Handle<Code> StubCache::ComputeCallGlobal(int argc, static void FillCache(Isolate* isolate, Handle<Code> code) { - Handle<NumberDictionary> dictionary = - NumberDictionarySet(isolate->factory()->non_monomorphic_cache(), - code->flags(), - code, - PropertyDetails(NONE, NORMAL)); + Handle<UnseededNumberDictionary> dictionary = + UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(), + code->flags(), + code); isolate->heap()->public_set_non_monomorphic_cache(*dictionary); } @@ -697,7 +696,7 @@ Code* StubCache::FindCallInitialize(int argc, Code::ComputeFlags(kind, UNINITIALIZED, extra_state, NORMAL, argc); // Use raw_unchecked... so we don't get assert failures during GC. - NumberDictionary* dictionary = + UnseededNumberDictionary* dictionary = isolate()->heap()->raw_unchecked_non_monomorphic_cache(); int entry = dictionary->FindEntry(isolate(), flags); ASSERT(entry != -1); @@ -716,7 +715,8 @@ Handle<Code> StubCache::ComputeCallInitialize(int argc, CallICBase::Contextual::encode(mode == RelocInfo::CODE_TARGET_CONTEXT); Code::Flags flags = Code::ComputeFlags(kind, UNINITIALIZED, extra_state, NORMAL, argc); - Handle<NumberDictionary> cache = isolate_->factory()->non_monomorphic_cache(); + Handle<UnseededNumberDictionary> cache = + isolate_->factory()->non_monomorphic_cache(); int entry = cache->FindEntry(isolate_, flags); if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); @@ -744,7 +744,8 @@ Handle<Code> StubCache::ComputeCallPreMonomorphic( Code::ExtraICState extra_state) { Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, extra_state, NORMAL, argc); - Handle<NumberDictionary> cache = isolate_->factory()->non_monomorphic_cache(); + Handle<UnseededNumberDictionary> cache = + isolate_->factory()->non_monomorphic_cache(); int entry = cache->FindEntry(isolate_, flags); if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); @@ -760,7 +761,8 @@ Handle<Code> StubCache::ComputeCallNormal(int argc, Code::ExtraICState extra_state) { Code::Flags flags = Code::ComputeFlags(kind, MONOMORPHIC, extra_state, NORMAL, argc); - Handle<NumberDictionary> cache = isolate_->factory()->non_monomorphic_cache(); + Handle<UnseededNumberDictionary> cache = + isolate_->factory()->non_monomorphic_cache(); int entry = cache->FindEntry(isolate_, flags); if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); @@ -776,7 +778,8 @@ Handle<Code> StubCache::ComputeCallArguments(int argc, Code::Kind kind) { Code::Flags flags = Code::ComputeFlags(kind, MEGAMORPHIC, Code::kNoExtraICState, NORMAL, argc); - Handle<NumberDictionary> cache = isolate_->factory()->non_monomorphic_cache(); + Handle<UnseededNumberDictionary> cache = + isolate_->factory()->non_monomorphic_cache(); int entry = cache->FindEntry(isolate_, flags); if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); @@ -794,7 +797,8 @@ Handle<Code> StubCache::ComputeCallMegamorphic( Code::Flags flags = Code::ComputeFlags(kind, MEGAMORPHIC, extra_state, NORMAL, argc); - Handle<NumberDictionary> cache = isolate_->factory()->non_monomorphic_cache(); + Handle<UnseededNumberDictionary> cache = + isolate_->factory()->non_monomorphic_cache(); int entry = cache->FindEntry(isolate_, flags); if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); @@ -813,7 +817,8 @@ Handle<Code> StubCache::ComputeCallMiss(int argc, Code::Flags flags = Code::ComputeFlags(kind, MONOMORPHIC_PROTOTYPE_FAILURE, extra_state, NORMAL, argc, OWN_MAP); - Handle<NumberDictionary> cache = isolate_->factory()->non_monomorphic_cache(); + Handle<UnseededNumberDictionary> cache = + isolate_->factory()->non_monomorphic_cache(); int entry = cache->FindEntry(isolate_, flags); if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); @@ -832,7 +837,8 @@ Handle<Code> StubCache::ComputeCallDebugBreak(int argc, Code::Flags flags = Code::ComputeFlags(kind, DEBUG_BREAK, Code::kNoExtraICState, NORMAL, argc); - Handle<NumberDictionary> cache = isolate_->factory()->non_monomorphic_cache(); + Handle<UnseededNumberDictionary> cache = + isolate_->factory()->non_monomorphic_cache(); int entry = cache->FindEntry(isolate_, flags); if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); @@ -850,7 +856,8 @@ Handle<Code> StubCache::ComputeCallDebugPrepareStepIn(int argc, Code::Flags flags = Code::ComputeFlags(kind, DEBUG_PREPARE_STEP_IN, Code::kNoExtraICState, NORMAL, argc); - Handle<NumberDictionary> cache = isolate_->factory()->non_monomorphic_cache(); + Handle<UnseededNumberDictionary> cache = + isolate_->factory()->non_monomorphic_cache(); int entry = cache->FindEntry(isolate_, flags); if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); diff --git a/deps/v8/src/type-info.cc b/deps/v8/src/type-info.cc index 790d77cb19c..fcdc6108feb 100644 --- a/deps/v8/src/type-info.cc +++ b/deps/v8/src/type-info.cc @@ -71,7 +71,7 @@ TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code, Handle<Object> TypeFeedbackOracle::GetInfo(unsigned ast_id) { int entry = dictionary_->FindEntry(ast_id); - return entry != NumberDictionary::kNotFound + return entry != UnseededNumberDictionary::kNotFound ? Handle<Object>(dictionary_->ValueAt(entry)) : Handle<Object>::cast(isolate_->factory()->undefined_value()); } @@ -559,7 +559,7 @@ void TypeFeedbackOracle::CreateDictionary(Handle<Code> code, ZoneList<RelocInfo>* infos) { DisableAssertNoAllocation allocation_allowed; byte* old_start = code->instruction_start(); - dictionary_ = FACTORY->NewNumberDictionary(infos->length()); + dictionary_ = FACTORY->NewUnseededNumberDictionary(infos->length()); byte* new_start = code->instruction_start(); RelocateRelocInfos(infos, old_start, new_start); } @@ -639,7 +639,7 @@ void TypeFeedbackOracle::ProcessRelocInfos(ZoneList<RelocInfo>* infos) { void TypeFeedbackOracle::SetInfo(unsigned ast_id, Object* target) { - ASSERT(dictionary_->FindEntry(ast_id) == NumberDictionary::kNotFound); + ASSERT(dictionary_->FindEntry(ast_id) == UnseededNumberDictionary::kNotFound); MaybeObject* maybe_result = dictionary_->AtNumberPut(ast_id, target); USE(maybe_result); #ifdef DEBUG diff --git a/deps/v8/src/type-info.h b/deps/v8/src/type-info.h index 1519fcabb49..9d3080abbff 100644 --- a/deps/v8/src/type-info.h +++ b/deps/v8/src/type-info.h @@ -303,7 +303,7 @@ class TypeFeedbackOracle BASE_EMBEDDED { Handle<Context> global_context_; Isolate* isolate_; - Handle<NumberDictionary> dictionary_; + Handle<UnseededNumberDictionary> dictionary_; DISALLOW_COPY_AND_ASSIGN(TypeFeedbackOracle); }; diff --git a/deps/v8/src/utils.h b/deps/v8/src/utils.h index 68b1517de4b..17bf06ffa3c 100644 --- a/deps/v8/src/utils.h +++ b/deps/v8/src/utils.h @@ -252,10 +252,13 @@ class BitField { // ---------------------------------------------------------------------------- // Hash function. +static const uint32_t kZeroHashSeed = 0; + // Thomas Wang, Integer Hash Functions. // http://www.concentric.net/~Ttwang/tech/inthash.htm -inline uint32_t ComputeIntegerHash(uint32_t key) { +inline uint32_t ComputeIntegerHash(uint32_t key, uint32_t seed) { uint32_t hash = key; + hash = hash ^ seed; hash = ~hash + (hash << 15); // hash = (hash << 15) - hash - 1; hash = hash ^ (hash >> 12); hash = hash + (hash << 2); @@ -280,7 +283,8 @@ inline uint32_t ComputeLongHash(uint64_t key) { inline uint32_t ComputePointerHash(void* ptr) { return ComputeIntegerHash( - static_cast<uint32_t>(reinterpret_cast<intptr_t>(ptr))); + static_cast<uint32_t>(reinterpret_cast<intptr_t>(ptr)), + v8::internal::kZeroHashSeed); } diff --git a/deps/v8/src/v8.cc b/deps/v8/src/v8.cc index c882d86f8d9..36ee221948d 100644 --- a/deps/v8/src/v8.cc +++ b/deps/v8/src/v8.cc @@ -47,7 +47,7 @@ static Mutex* init_once_mutex = OS::CreateMutex(); static bool init_once_called = false; bool V8::is_running_ = false; -bool V8::has_been_setup_ = false; +bool V8::has_been_set_up_ = false; bool V8::has_been_disposed_ = false; bool V8::has_fatal_error_ = false; bool V8::use_crankshaft_ = true; @@ -82,7 +82,7 @@ bool V8::Initialize(Deserializer* des) { if (isolate->IsInitialized()) return true; is_running_ = true; - has_been_setup_ = true; + has_been_set_up_ = true; has_fatal_error_ = false; has_been_disposed_ = false; @@ -100,7 +100,7 @@ void V8::TearDown() { Isolate* isolate = Isolate::Current(); ASSERT(isolate->IsDefaultIsolate()); - if (!has_been_setup_ || has_been_disposed_) return; + if (!has_been_set_up_ || has_been_disposed_) return; isolate->TearDown(); is_running_ = false; @@ -239,8 +239,8 @@ void V8::InitializeOncePerProcess() { if (init_once_called) return; init_once_called = true; - // Setup the platform OS support. - OS::Setup(); + // Set up the platform OS support. + OS::SetUp(); use_crankshaft_ = FLAG_crankshaft; @@ -248,7 +248,7 @@ void V8::InitializeOncePerProcess() { use_crankshaft_ = false; } - CPU::Setup(); + CPU::SetUp(); if (!CPU::SupportsCrankshaft()) { use_crankshaft_ = false; } diff --git a/deps/v8/src/v8.h b/deps/v8/src/v8.h index b9a3e053861..adfdb3ea885 100644 --- a/deps/v8/src/v8.h +++ b/deps/v8/src/v8.h @@ -118,7 +118,7 @@ class V8 : public AllStatic { // True if engine is currently running static bool is_running_; // True if V8 has ever been run - static bool has_been_setup_; + static bool has_been_set_up_; // True if error has been signaled for current engine // (reset to false if engine is restarted) static bool has_fatal_error_; diff --git a/deps/v8/src/v8globals.h b/deps/v8/src/v8globals.h index 005cdbdaec5..bdb960e8fdc 100644 --- a/deps/v8/src/v8globals.h +++ b/deps/v8/src/v8globals.h @@ -130,7 +130,8 @@ class FixedArray; class FunctionLiteral; class FunctionTemplateInfo; class MemoryChunk; -class NumberDictionary; +class SeededNumberDictionary; +class UnseededNumberDictionary; class StringDictionary; template <typename T> class Handle; class Heap; diff --git a/deps/v8/src/version.cc b/deps/v8/src/version.cc index 617b7d1c502..95535851d1a 100644 --- a/deps/v8/src/version.cc +++ b/deps/v8/src/version.cc @@ -34,7 +34,7 @@ // cannot be changed without changing the SCons build script. #define MAJOR_VERSION 3 #define MINOR_VERSION 8 -#define BUILD_NUMBER 5 +#define BUILD_NUMBER 6 #define PATCH_LEVEL 0 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/deps/v8/src/win32-headers.h b/deps/v8/src/win32-headers.h index 0ee330668af..ca1b1d8b8e0 100644 --- a/deps/v8/src/win32-headers.h +++ b/deps/v8/src/win32-headers.h @@ -75,7 +75,9 @@ // makes it impossible to have them elsewhere. #include <winsock2.h> #include <ws2tcpip.h> +#ifndef __MINGW32__ #include <wspiapi.h> +#endif // __MINGW32__ #include <process.h> // for _beginthreadex() #include <stdlib.h> #endif // V8_WIN32_HEADERS_FULL diff --git a/deps/v8/src/x64/assembler-x64-inl.h b/deps/v8/src/x64/assembler-x64-inl.h index ab387d6d0a0..141d092d8e1 100644 --- a/deps/v8/src/x64/assembler-x64-inl.h +++ b/deps/v8/src/x64/assembler-x64-inl.h @@ -262,7 +262,7 @@ Object* RelocInfo::target_object() { } -Handle<Object> RelocInfo::target_object_handle(Assembler *origin) { +Handle<Object> RelocInfo::target_object_handle(Assembler* origin) { ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); if (rmode_ == EMBEDDED_OBJECT) { return Memory::Object_Handle_at(pc_); diff --git a/deps/v8/src/x64/assembler-x64.cc b/deps/v8/src/x64/assembler-x64.cc index ca3bece5f09..eb8d7d4d998 100644 --- a/deps/v8/src/x64/assembler-x64.cc +++ b/deps/v8/src/x64/assembler-x64.cc @@ -383,7 +383,7 @@ Assembler::Assembler(Isolate* arg_isolate, void* buffer, int buffer_size) } #endif - // Setup buffer pointers. + // Set up buffer pointers. ASSERT(buffer_ != NULL); pc_ = buffer_; reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); @@ -412,7 +412,7 @@ void Assembler::GetCode(CodeDesc* desc) { // Finalize code (at this point overflow() may be true, but the gap ensures // that we are still not overlapping instructions and relocation info). ASSERT(pc_ <= reloc_info_writer.pos()); // No overlap. - // Setup code descriptor. + // Set up code descriptor. desc->buffer = buffer_; desc->buffer_size = buffer_size_; desc->instr_size = pc_offset(); @@ -502,7 +502,7 @@ void Assembler::GrowBuffer() { V8::FatalProcessOutOfMemory("Assembler::GrowBuffer"); } - // Setup new buffer. + // Set up new buffer. desc.buffer = NewArray<byte>(desc.buffer_size); desc.instr_size = pc_offset(); desc.reloc_size = diff --git a/deps/v8/src/x64/builtins-x64.cc b/deps/v8/src/x64/builtins-x64.cc index ef63c7a27bb..4833e03c8e8 100644 --- a/deps/v8/src/x64/builtins-x64.cc +++ b/deps/v8/src/x64/builtins-x64.cc @@ -337,7 +337,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, __ push(rbx); __ push(rbx); - // Setup pointer to last argument. + // Set up pointer to last argument. __ lea(rbx, Operand(rbp, StandardFrameConstants::kCallerSPOffset)); // Copy arguments and receiver to the expression stack. @@ -1198,7 +1198,7 @@ static void AllocateJSArray(MacroAssembler* masm, // Both registers are preserved by this code so no need to differentiate between // a construct call and a normal call. static void ArrayNativeCode(MacroAssembler* masm, - Label *call_generic_code) { + Label* call_generic_code) { Label argc_one_or_more, argc_two_or_more, empty_array, not_empty_array, has_non_smi_element; diff --git a/deps/v8/src/x64/code-stubs-x64.cc b/deps/v8/src/x64/code-stubs-x64.cc index ea9c494e8a9..03a5170bae7 100644 --- a/deps/v8/src/x64/code-stubs-x64.cc +++ b/deps/v8/src/x64/code-stubs-x64.cc @@ -124,12 +124,12 @@ void FastNewContextStub::Generate(MacroAssembler* masm) { // Get the function from the stack. __ movq(rcx, Operand(rsp, 1 * kPointerSize)); - // Setup the object header. + // Set up the object header. __ LoadRoot(kScratchRegister, Heap::kFunctionContextMapRootIndex); __ movq(FieldOperand(rax, HeapObject::kMapOffset), kScratchRegister); __ Move(FieldOperand(rax, FixedArray::kLengthOffset), Smi::FromInt(length)); - // Setup the fixed slots. + // Set up the fixed slots. __ Set(rbx, 0); // Set to NULL. __ movq(Operand(rax, Context::SlotOffset(Context::CLOSURE_INDEX)), rcx); __ movq(Operand(rax, Context::SlotOffset(Context::PREVIOUS_INDEX)), rsi); @@ -173,7 +173,7 @@ void FastNewBlockContextStub::Generate(MacroAssembler* masm) { // Get the serialized scope info from the stack. __ movq(rbx, Operand(rsp, 2 * kPointerSize)); - // Setup the object header. + // Set up the object header. __ LoadRoot(kScratchRegister, Heap::kBlockContextMapRootIndex); __ movq(FieldOperand(rax, HeapObject::kMapOffset), kScratchRegister); __ Move(FieldOperand(rax, FixedArray::kLengthOffset), Smi::FromInt(length)); @@ -194,7 +194,7 @@ void FastNewBlockContextStub::Generate(MacroAssembler* masm) { __ movq(rcx, ContextOperand(rcx, Context::CLOSURE_INDEX)); __ bind(&after_sentinel); - // Setup the fixed slots. + // Set up the fixed slots. __ movq(ContextOperand(rax, Context::CLOSURE_INDEX), rcx); __ movq(ContextOperand(rax, Context::PREVIOUS_INDEX), rsi); __ movq(ContextOperand(rax, Context::EXTENSION_INDEX), rbx); @@ -2399,7 +2399,7 @@ void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) { __ movq(FieldOperand(rax, i), rdx); } - // Setup the callee in-object property. + // Set up the callee in-object property. STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); __ movq(rdx, Operand(rsp, 3 * kPointerSize)); __ movq(FieldOperand(rax, JSObject::kHeaderSize + @@ -2414,7 +2414,7 @@ void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) { Heap::kArgumentsLengthIndex * kPointerSize), rcx); - // Setup the elements pointer in the allocated arguments object. + // Set up the elements pointer in the allocated arguments object. // If we allocated a parameter map, edi will point there, otherwise to the // backing store. __ lea(rdi, Operand(rax, Heap::kArgumentsObjectSize)); @@ -2621,7 +2621,7 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { // Get the parameters pointer from the stack. __ movq(rdx, Operand(rsp, 2 * kPointerSize)); - // Setup the elements pointer in the allocated arguments object and + // Set up the elements pointer in the allocated arguments object and // initialize the header in the elements fixed array. __ lea(rdi, Operand(rax, Heap::kArgumentsObjectSizeStrict)); __ movq(FieldOperand(rax, JSObject::kElementsOffset), rdi); @@ -3942,7 +3942,7 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { Label not_outermost_js, not_outermost_js_2; { // NOLINT. Scope block confuses linter. MacroAssembler::NoRootArrayScope uninitialized_root_register(masm); - // Setup frame. + // Set up frame. __ push(rbp); __ movq(rbp, rsp); @@ -4156,12 +4156,14 @@ void InstanceofStub::Generate(MacroAssembler* masm) { // Get return address and delta to inlined map check. __ movq(kScratchRegister, Operand(rsp, 0 * kPointerSize)); __ subq(kScratchRegister, Operand(rsp, 1 * kPointerSize)); - __ movq(Operand(kScratchRegister, kOffsetToMapCheckValue), rax); if (FLAG_debug_code) { __ movl(rdi, Immediate(kWordBeforeMapCheckValue)); __ cmpl(Operand(kScratchRegister, kOffsetToMapCheckValue - 4), rdi); __ Assert(equal, "InstanceofStub unexpected call site cache (check)."); } + __ movq(kScratchRegister, + Operand(kScratchRegister, kOffsetToMapCheckValue)); + __ movq(Operand(kScratchRegister, 0), rax); } __ movq(rcx, FieldOperand(rax, Map::kPrototypeOffset)); @@ -4959,7 +4961,7 @@ void StringHelper::GenerateHashInit(MacroAssembler* masm, Register character, Register scratch) { // hash = (seed + character) + ((seed + character) << 10); - __ LoadRoot(scratch, Heap::kStringHashSeedRootIndex); + __ LoadRoot(scratch, Heap::kHashSeedRootIndex); __ SmiToInteger32(scratch, scratch); __ addl(scratch, character); __ movl(hash, scratch); @@ -5003,13 +5005,12 @@ void StringHelper::GenerateHashGetHash(MacroAssembler* masm, __ shll(scratch, Immediate(15)); __ addl(hash, scratch); - uint32_t kHashShiftCutOffMask = (1 << (32 - String::kHashShift)) - 1; - __ andl(hash, Immediate(kHashShiftCutOffMask)); + __ andl(hash, Immediate(String::kHashBitMask)); // if (hash == 0) hash = 27; Label hash_not_zero; __ j(not_zero, &hash_not_zero); - __ Set(hash, 27); + __ Set(hash, StringHasher::kZeroHash); __ bind(&hash_not_zero); } @@ -5080,7 +5081,7 @@ void SubStringStub::Generate(MacroAssembler* masm) { __ ret(3 * kPointerSize); __ bind(&make_two_character_string); - // Setup registers for allocating the two character string. + // Set up registers for allocating the two character string. __ movzxwq(rbx, FieldOperand(rax, rdx, times_1, SeqAsciiString::kHeaderSize)); __ AllocateAsciiString(rax, rcx, r11, r14, r15, &runtime); __ movw(FieldOperand(rax, SeqAsciiString::kHeaderSize), rbx); diff --git a/deps/v8/src/x64/cpu-x64.cc b/deps/v8/src/x64/cpu-x64.cc index ae5045f0df8..69e77eee9d0 100644 --- a/deps/v8/src/x64/cpu-x64.cc +++ b/deps/v8/src/x64/cpu-x64.cc @@ -41,7 +41,7 @@ namespace v8 { namespace internal { -void CPU::Setup() { +void CPU::SetUp() { CpuFeatures::Probe(); } diff --git a/deps/v8/src/x64/deoptimizer-x64.cc b/deps/v8/src/x64/deoptimizer-x64.cc index d684ad713f4..a5a171a2a88 100644 --- a/deps/v8/src/x64/deoptimizer-x64.cc +++ b/deps/v8/src/x64/deoptimizer-x64.cc @@ -314,7 +314,7 @@ void Deoptimizer::DoComputeOsrOutputFrame() { output_[0] = input_; output_[0]->SetPc(reinterpret_cast<intptr_t>(from_)); } else { - // Setup the frame pointer and the context pointer. + // Set up the frame pointer and the context pointer. output_[0]->SetRegister(rbp.code(), input_->GetRegister(rbp.code())); output_[0]->SetRegister(rsi.code(), input_->GetRegister(rsi.code())); diff --git a/deps/v8/src/x64/full-codegen-x64.cc b/deps/v8/src/x64/full-codegen-x64.cc index 24df20ba767..eeef0e94e84 100644 --- a/deps/v8/src/x64/full-codegen-x64.cc +++ b/deps/v8/src/x64/full-codegen-x64.cc @@ -967,7 +967,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { __ movq(rcx, FieldOperand(rcx, DescriptorArray::kEnumerationIndexOffset)); __ movq(rdx, FieldOperand(rcx, DescriptorArray::kEnumCacheBridgeCacheOffset)); - // Setup the four remaining stack slots. + // Set up the four remaining stack slots. __ push(rax); // Map. __ push(rdx); // Enumeration cache. __ movq(rax, FieldOperand(rdx, FixedArray::kLengthOffset)); diff --git a/deps/v8/src/x64/lithium-codegen-x64.cc b/deps/v8/src/x64/lithium-codegen-x64.cc index 6239acb5153..392c74dc23b 100644 --- a/deps/v8/src/x64/lithium-codegen-x64.cc +++ b/deps/v8/src/x64/lithium-codegen-x64.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -1755,13 +1755,17 @@ void LCodeGen::DoHasCachedArrayIndexAndBranch( // Branches to a label or falls through with the answer in the z flag. -// Trashes the temp register and possibly input (if it and temp are aliased). +// Trashes the temp register. void LCodeGen::EmitClassOfTest(Label* is_true, Label* is_false, Handle<String> class_name, Register input, Register temp, - Register scratch) { + Register temp2) { + ASSERT(!input.is(temp)); + ASSERT(!input.is(temp2)); + ASSERT(!temp.is(temp2)); + __ JumpIfSmi(input, is_false); if (class_name->IsEqualTo(CStrVector("Function"))) { @@ -1782,9 +1786,9 @@ void LCodeGen::EmitClassOfTest(Label* is_true, // Faster code path to avoid two compares: subtract lower bound from the // actual type and do a signed compare with the width of the type range. __ movq(temp, FieldOperand(input, HeapObject::kMapOffset)); - __ movq(scratch, FieldOperand(temp, Map::kInstanceTypeOffset)); - __ subb(scratch, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); - __ cmpb(scratch, + __ movq(temp2, FieldOperand(temp, Map::kInstanceTypeOffset)); + __ subb(temp2, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); + __ cmpb(temp2, Immediate(static_cast<int8_t>(LAST_NONCALLABLE_SPEC_OBJECT_TYPE - FIRST_NONCALLABLE_SPEC_OBJECT_TYPE))); __ j(above, is_false); @@ -1897,9 +1901,10 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { Register map = ToRegister(instr->TempAt(0)); __ movq(map, FieldOperand(object, HeapObject::kMapOffset)); __ bind(deferred->map_check()); // Label for calculating code patching. - __ movq(kScratchRegister, factory()->the_hole_value(), - RelocInfo::EMBEDDED_OBJECT); - __ cmpq(map, kScratchRegister); // Patched to cached map. + Handle<JSGlobalPropertyCell> cache_cell = + factory()->NewJSGlobalPropertyCell(factory()->the_hole_value()); + __ movq(kScratchRegister, cache_cell, RelocInfo::GLOBAL_PROPERTY_CELL); + __ cmpq(map, Operand(kScratchRegister, 0)); __ j(not_equal, &cache_miss, Label::kNear); // Patched to load either true or false. __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); @@ -2636,7 +2641,7 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function, __ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset)); } - // Setup deoptimization. + // Set up deoptimization. RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0); // Restore context. @@ -2926,6 +2931,38 @@ void LCodeGen::DoPower(LPower* instr) { } +void LCodeGen::DoRandom(LRandom* instr) { + // Having marked this instruction as a call we can use any + // registers. + ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); + + // Choose the right register for the first argument depending on + // calling convention. +#ifdef _WIN64 + ASSERT(ToRegister(instr->InputAt(0)).is(rcx)); + Register global_object = rcx; +#else + ASSERT(ToRegister(instr->InputAt(0)).is(rdi)); + Register global_object = rdi; +#endif + + __ PrepareCallCFunction(1); + __ movq(global_object, + FieldOperand(global_object, GlobalObject::kGlobalContextOffset)); + __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); + + // Convert 32 random bits in rax to 0.(32 random bits) in a double + // by computing: + // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). + __ movl(rcx, Immediate(0x49800000)); // 1.0 x 2^20 as single. + __ movd(xmm2, rcx); + __ movd(xmm1, rax); + __ cvtss2sd(xmm2, xmm2); + __ xorps(xmm1, xmm2); + __ subsd(xmm1, xmm2); +} + + void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); TranscendentalCacheStub stub(TranscendentalCache::LOG, @@ -3510,6 +3547,7 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) { void LCodeGen::EmitNumberUntagD(Register input_reg, XMMRegister result_reg, bool deoptimize_on_undefined, + bool deoptimize_on_minus_zero, LEnvironment* env) { Label load_smi, done; @@ -3537,6 +3575,15 @@ void LCodeGen::EmitNumberUntagD(Register input_reg, } // Heap number to XMM conversion. __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); + if (deoptimize_on_minus_zero) { + XMMRegister xmm_scratch = xmm0; + __ xorps(xmm_scratch, xmm_scratch); + __ ucomisd(xmm_scratch, result_reg); + __ j(not_equal, &done, Label::kNear); + __ movmskpd(kScratchRegister, result_reg); + __ testq(kScratchRegister, Immediate(1)); + DeoptimizeIf(not_zero, env); + } __ jmp(&done, Label::kNear); // Smi to XMM conversion @@ -3628,6 +3675,7 @@ void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { EmitNumberUntagD(input_reg, result_reg, instr->hydrogen()->deoptimize_on_undefined(), + instr->hydrogen()->deoptimize_on_minus_zero(), instr->environment()); } @@ -3747,13 +3795,23 @@ void LCodeGen::DoCheckFunction(LCheckFunction* instr) { } +void LCodeGen::DoCheckMapCommon(Register reg, + Handle<Map> map, + CompareMapMode mode, + LEnvironment* env) { + Label success; + __ CompareMap(reg, map, &success, mode); + DeoptimizeIf(not_equal, env); + __ bind(&success); +} + + void LCodeGen::DoCheckMap(LCheckMap* instr) { LOperand* input = instr->InputAt(0); ASSERT(input->IsRegister()); Register reg = ToRegister(input); - __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), - instr->hydrogen()->map()); - DeoptimizeIf(not_equal, instr->environment()); + Handle<Map> map = instr->hydrogen()->map(); + DoCheckMapCommon(reg, map, instr->hydrogen()->mode(), instr->environment()); } @@ -3819,9 +3877,8 @@ void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { // Check prototype maps up to the holder. while (!current_prototype.is_identical_to(holder)) { - __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), - Handle<Map>(current_prototype->map())); - DeoptimizeIf(not_equal, instr->environment()); + DoCheckMapCommon(reg, Handle<Map>(current_prototype->map()), + ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment()); current_prototype = Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype())); // Load next prototype object. @@ -3829,9 +3886,8 @@ void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { } // Check the holder map. - __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), - Handle<Map>(current_prototype->map())); - DeoptimizeIf(not_equal, instr->environment()); + DoCheckMapCommon(reg, Handle<Map>(current_prototype->map()), + ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment()); } @@ -3855,7 +3911,7 @@ void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { DeoptimizeIf(not_equal, instr->environment()); } - // Setup the parameters to the stub/runtime call. + // Set up the parameters to the stub/runtime call. __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); __ push(FieldOperand(rax, JSFunction::kLiteralsOffset)); __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); @@ -3956,7 +4012,7 @@ void LCodeGen::DoObjectLiteralGeneric(LObjectLiteralGeneric* instr) { Handle<FixedArray> constant_properties = instr->hydrogen()->constant_properties(); - // Setup the parameters to the stub/runtime call. + // Set up the parameters to the stub/runtime call. __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); __ push(FieldOperand(rax, JSFunction::kLiteralsOffset)); __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); diff --git a/deps/v8/src/x64/lithium-codegen-x64.h b/deps/v8/src/x64/lithium-codegen-x64.h index 832942f1efc..2890c530b74 100644 --- a/deps/v8/src/x64/lithium-codegen-x64.h +++ b/deps/v8/src/x64/lithium-codegen-x64.h @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -102,7 +102,10 @@ class LCodeGen BASE_EMBEDDED { void DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, Label* map_check); - // Parallel move support. + void DoCheckMapCommon(Register reg, Handle<Map> map, + CompareMapMode mode, LEnvironment* env); + +// Parallel move support. void DoParallelMove(LParallelMove* move); void DoGap(LGap* instr); @@ -252,6 +255,7 @@ class LCodeGen BASE_EMBEDDED { void EmitNumberUntagD(Register input, XMMRegister result, bool deoptimize_on_undefined, + bool deoptimize_on_minus_zero, LEnvironment* env); // Emits optimized code for typeof x == "y". Modifies input register. @@ -372,7 +376,7 @@ class LDeferredCode: public ZoneObject { virtual void Generate() = 0; virtual LInstruction* instr() = 0; - void SetExit(Label *exit) { external_exit_ = exit; } + void SetExit(Label* exit) { external_exit_ = exit; } Label* entry() { return &entry_; } Label* exit() { return external_exit_ != NULL ? external_exit_ : &exit_; } int instruction_index() const { return instruction_index_; } diff --git a/deps/v8/src/x64/lithium-x64.cc b/deps/v8/src/x64/lithium-x64.cc index 5bae14bfa9a..fee2f4f2ab9 100644 --- a/deps/v8/src/x64/lithium-x64.cc +++ b/deps/v8/src/x64/lithium-x64.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -1033,16 +1033,25 @@ LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { - HValue* v = instr->value(); - if (v->EmitAtUses()) { - ASSERT(v->IsConstant()); - ASSERT(!v->representation().IsDouble()); - HBasicBlock* successor = HConstant::cast(v)->ToBoolean() + HValue* value = instr->value(); + if (value->EmitAtUses()) { + ASSERT(value->IsConstant()); + ASSERT(!value->representation().IsDouble()); + HBasicBlock* successor = HConstant::cast(value)->ToBoolean() ? instr->FirstSuccessor() : instr->SecondSuccessor(); return new LGoto(successor->block_id()); } - return AssignEnvironment(new LBranch(UseRegister(v))); + + LBranch* result = new LBranch(UseRegister(value)); + // Tagged values that are not known smis or booleans require a + // deoptimization environment. + Representation rep = value->representation(); + HType type = value->type(); + if (rep.IsTagged() && !type.IsSmi() && !type.IsBoolean()) { + return AssignEnvironment(result); + } + return result; } @@ -1329,7 +1338,11 @@ LInstruction* LChunkBuilder::DoMul(HMul* instr) { LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); LOperand* right = UseOrConstant(instr->MostConstantOperand()); LMulI* mul = new LMulI(left, right); - return AssignEnvironment(DefineSameAsFirst(mul)); + if (instr->CheckFlag(HValue::kCanOverflow) || + instr->CheckFlag(HValue::kBailoutOnMinusZero)) { + AssignEnvironment(mul); + } + return DefineSameAsFirst(mul); } else if (instr->representation().IsDouble()) { return DoArithmeticD(Token::MUL, instr); } else { @@ -1402,6 +1415,19 @@ LInstruction* LChunkBuilder::DoPower(HPower* instr) { } +LInstruction* LChunkBuilder::DoRandom(HRandom* instr) { + ASSERT(instr->representation().IsDouble()); + ASSERT(instr->global_object()->representation().IsTagged()); +#ifdef _WIN64 + LOperand* global_object = UseFixed(instr->global_object(), rcx); +#else + LOperand* global_object = UseFixed(instr->global_object(), rdi); +#endif + LRandom* result = new LRandom(global_object); + return MarkAsCall(DefineFixedDouble(result, xmm1), instr); +} + + LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) { ASSERT(instr->left()->representation().IsTagged()); ASSERT(instr->right()->representation().IsTagged()); @@ -1525,7 +1551,7 @@ LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch( LInstruction* LChunkBuilder::DoClassOfTestAndBranch( HClassOfTestAndBranch* instr) { - return new LClassOfTestAndBranch(UseTempRegister(instr->value()), + return new LClassOfTestAndBranch(UseRegister(instr->value()), TempRegister(), TempRegister()); } @@ -1553,7 +1579,7 @@ LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) { LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) { LOperand* object = UseRegister(instr->value()); LValueOf* result = new LValueOf(object); - return AssignEnvironment(DefineSameAsFirst(result)); + return DefineSameAsFirst(result); } @@ -1866,7 +1892,8 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement( LOperand* obj = UseRegisterAtStart(instr->object()); LOperand* key = UseRegisterOrConstantAtStart(instr->key()); LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key); - return AssignEnvironment(DefineAsRegister(result)); + if (instr->RequiresHoleCheck()) AssignEnvironment(result); + return DefineAsRegister(result); } diff --git a/deps/v8/src/x64/lithium-x64.h b/deps/v8/src/x64/lithium-x64.h index c6fcfeb81ea..193f0389da3 100644 --- a/deps/v8/src/x64/lithium-x64.h +++ b/deps/v8/src/x64/lithium-x64.h @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -141,6 +141,7 @@ class LCodeGen; V(Parameter) \ V(Power) \ V(PushArgument) \ + V(Random) \ V(RegExpLiteral) \ V(Return) \ V(ShiftI) \ @@ -1024,6 +1025,17 @@ class LPower: public LTemplateInstruction<1, 2, 0> { }; +class LRandom: public LTemplateInstruction<1, 1, 0> { + public: + explicit LRandom(LOperand* global_object) { + inputs_[0] = global_object; + } + + DECLARE_CONCRETE_INSTRUCTION(Random, "random") + DECLARE_HYDROGEN_ACCESSOR(Random) +}; + + class LArithmeticD: public LTemplateInstruction<1, 2, 0> { public: LArithmeticD(Token::Value op, LOperand* left, LOperand* right) diff --git a/deps/v8/src/x64/macro-assembler-x64.cc b/deps/v8/src/x64/macro-assembler-x64.cc index 10e423b5b95..47553697aed 100644 --- a/deps/v8/src/x64/macro-assembler-x64.cc +++ b/deps/v8/src/x64/macro-assembler-x64.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -495,7 +495,7 @@ void MacroAssembler::Abort(const char* msg) { // from the real pointer as a smi. intptr_t p1 = reinterpret_cast<intptr_t>(msg); intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag; - // Note: p0 might not be a valid Smi *value*, but it has a valid Smi tag. + // Note: p0 might not be a valid Smi _value_, but it has a valid Smi tag. ASSERT(reinterpret_cast<Object*>(p0)->IsSmi()); #ifdef DEBUG if (msg != NULL) { @@ -2739,15 +2739,48 @@ void MacroAssembler::StoreNumberToDoubleElements( } +void MacroAssembler::CompareMap(Register obj, + Handle<Map> map, + Label* early_success, + CompareMapMode mode) { + Cmp(FieldOperand(obj, HeapObject::kMapOffset), map); + if (mode == ALLOW_ELEMENT_TRANSITION_MAPS) { + Map* transitioned_fast_element_map( + map->LookupElementsTransitionMap(FAST_ELEMENTS, NULL)); + ASSERT(transitioned_fast_element_map == NULL || + map->elements_kind() != FAST_ELEMENTS); + if (transitioned_fast_element_map != NULL) { + j(equal, early_success, Label::kNear); + Cmp(FieldOperand(obj, HeapObject::kMapOffset), + Handle<Map>(transitioned_fast_element_map)); + } + + Map* transitioned_double_map( + map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, NULL)); + ASSERT(transitioned_double_map == NULL || + map->elements_kind() == FAST_SMI_ONLY_ELEMENTS); + if (transitioned_double_map != NULL) { + j(equal, early_success, Label::kNear); + Cmp(FieldOperand(obj, HeapObject::kMapOffset), + Handle<Map>(transitioned_double_map)); + } + } +} + + void MacroAssembler::CheckMap(Register obj, Handle<Map> map, Label* fail, - SmiCheckType smi_check_type) { + SmiCheckType smi_check_type, + CompareMapMode mode) { if (smi_check_type == DO_SMI_CHECK) { JumpIfSmi(obj, fail); } - Cmp(FieldOperand(obj, HeapObject::kMapOffset), map); + + Label success; + CompareMap(obj, map, &success, mode); j(not_equal, fail); + bind(&success); } @@ -3198,7 +3231,7 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) { void MacroAssembler::EnterExitFramePrologue(bool save_rax) { - // Setup the frame structure on the stack. + // Set up the frame structure on the stack. // All constants are relative to the frame pointer of the exit frame. ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize); @@ -3258,7 +3291,7 @@ void MacroAssembler::EnterExitFrameEpilogue(int arg_stack_space, void MacroAssembler::EnterExitFrame(int arg_stack_space, bool save_doubles) { EnterExitFramePrologue(true); - // Setup argv in callee-saved register r15. It is reused in LeaveExitFrame, + // Set up argv in callee-saved register r15. It is reused in LeaveExitFrame, // so it must be retained across the C-call. int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; lea(r15, Operand(rbp, r14, times_pointer_size, offset)); @@ -3386,6 +3419,42 @@ void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, } +void MacroAssembler::GetNumberHash(Register r0, Register scratch) { + // First of all we assign the hash seed to scratch. + LoadRoot(scratch, Heap::kHashSeedRootIndex); + SmiToInteger32(scratch, scratch); + + // Xor original key with a seed. + xorl(r0, scratch); + + // Compute the hash code from the untagged key. This must be kept in sync + // with ComputeIntegerHash in utils.h. + // + // hash = ~hash + (hash << 15); + movl(scratch, r0); + notl(r0); + shll(scratch, Immediate(15)); + addl(r0, scratch); + // hash = hash ^ (hash >> 12); + movl(scratch, r0); + shrl(scratch, Immediate(12)); + xorl(r0, scratch); + // hash = hash + (hash << 2); + leal(r0, Operand(r0, r0, times_4, 0)); + // hash = hash ^ (hash >> 4); + movl(scratch, r0); + shrl(scratch, Immediate(4)); + xorl(r0, scratch); + // hash = hash * 2057; + imull(r0, r0, Immediate(2057)); + // hash = hash ^ (hash >> 16); + movl(scratch, r0); + shrl(scratch, Immediate(16)); + xorl(r0, scratch); +} + + + void MacroAssembler::LoadFromNumberDictionary(Label* miss, Register elements, Register key, @@ -3416,34 +3485,11 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, Label done; - // Compute the hash code from the untagged key. This must be kept in sync - // with ComputeIntegerHash in utils.h. - // - // hash = ~hash + (hash << 15); - movl(r1, r0); - notl(r0); - shll(r1, Immediate(15)); - addl(r0, r1); - // hash = hash ^ (hash >> 12); - movl(r1, r0); - shrl(r1, Immediate(12)); - xorl(r0, r1); - // hash = hash + (hash << 2); - leal(r0, Operand(r0, r0, times_4, 0)); - // hash = hash ^ (hash >> 4); - movl(r1, r0); - shrl(r1, Immediate(4)); - xorl(r0, r1); - // hash = hash * 2057; - imull(r0, r0, Immediate(2057)); - // hash = hash ^ (hash >> 16); - movl(r1, r0); - shrl(r1, Immediate(16)); - xorl(r0, r1); + GetNumberHash(r0, r1); // Compute capacity mask. - SmiToInteger32(r1, - FieldOperand(elements, NumberDictionary::kCapacityOffset)); + SmiToInteger32(r1, FieldOperand(elements, + SeededNumberDictionary::kCapacityOffset)); decl(r1); // Generate an unrolled loop that performs a few probes before giving up. @@ -3453,19 +3499,19 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, movq(r2, r0); // Compute the masked index: (hash + i + i * i) & mask. if (i > 0) { - addl(r2, Immediate(NumberDictionary::GetProbeOffset(i))); + addl(r2, Immediate(SeededNumberDictionary::GetProbeOffset(i))); } and_(r2, r1); // Scale the index by multiplying by the entry size. - ASSERT(NumberDictionary::kEntrySize == 3); + ASSERT(SeededNumberDictionary::kEntrySize == 3); lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 // Check if the key matches. cmpq(key, FieldOperand(elements, r2, times_pointer_size, - NumberDictionary::kElementsStartOffset)); + SeededNumberDictionary::kElementsStartOffset)); if (i != (kProbes - 1)) { j(equal, &done); } else { @@ -3476,7 +3522,7 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, bind(&done); // Check that the value is a normal propety. const int kDetailsOffset = - NumberDictionary::kElementsStartOffset + 2 * kPointerSize; + SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize; ASSERT_EQ(NORMAL, 0); Test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), Smi::FromInt(PropertyDetails::TypeField::kMask)); @@ -3484,7 +3530,7 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss, // Get the value at the masked, scaled index. const int kValueOffset = - NumberDictionary::kElementsStartOffset + kPointerSize; + SeededNumberDictionary::kElementsStartOffset + kPointerSize; movq(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); } diff --git a/deps/v8/src/x64/macro-assembler-x64.h b/deps/v8/src/x64/macro-assembler-x64.h index 97a98017c58..8596852db42 100644 --- a/deps/v8/src/x64/macro-assembler-x64.h +++ b/deps/v8/src/x64/macro-assembler-x64.h @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -328,7 +328,7 @@ class MacroAssembler: public Assembler { // --------------------------------------------------------------------------- // JavaScript invokes - // Setup call kind marking in rcx. The method takes rcx as an + // Set up call kind marking in rcx. The method takes rcx as an // explicit first parameter to make the code more readable at the // call sites. void SetCallKind(Register dst, CallKind kind); @@ -889,13 +889,24 @@ class MacroAssembler: public Assembler { XMMRegister xmm_scratch, Label* fail); - // Check if the map of an object is equal to a specified map and - // branch to label if not. Skip the smi check if not required - // (object is known to be a heap object) + // Compare an object's map with the specified map and its transitioned + // elements maps if mode is ALLOW_ELEMENT_TRANSITION_MAPS. FLAGS are set with + // result of map compare. If multiple map compares are required, the compare + // sequences branches to early_success. + void CompareMap(Register obj, + Handle<Map> map, + Label* early_success, + CompareMapMode mode = REQUIRE_EXACT_MAP); + + // Check if the map of an object is equal to a specified map and branch to + // label if not. Skip the smi check if not required (object is known to be a + // heap object). If mode is ALLOW_ELEMENT_TRANSITION_MAPS, then also match + // against maps that are ElementsKind transition maps of the specificed map. void CheckMap(Register obj, Handle<Map> map, Label* fail, - SmiCheckType smi_check_type); + SmiCheckType smi_check_type, + CompareMapMode mode = REQUIRE_EXACT_MAP); // Check if the map of an object is equal to a specified map and branch to a // specified target if equal. Skip the smi check if not required (object is @@ -975,6 +986,7 @@ class MacroAssembler: public Assembler { Register scratch, Label* miss); + void GetNumberHash(Register r0, Register scratch); void LoadFromNumberDictionary(Label* miss, Register elements, diff --git a/deps/v8/src/x64/stub-cache-x64.cc b/deps/v8/src/x64/stub-cache-x64.cc index a28dbbf0272..3633fbbceee 100644 --- a/deps/v8/src/x64/stub-cache-x64.cc +++ b/deps/v8/src/x64/stub-cache-x64.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -691,13 +691,9 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm, Register name_reg, Register scratch, Label* miss_label) { - // Check that the object isn't a smi. - __ JumpIfSmi(receiver_reg, miss_label); - // Check that the map of the object hasn't changed. - __ Cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset), - Handle<Map>(object->map())); - __ j(not_equal, miss_label); + __ CheckMap(receiver_reg, Handle<Map>(object->map()), + miss_label, DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); // Perform global security token check if needed. if (object->IsJSGlobalProxy()) { @@ -864,12 +860,10 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object, if (in_new_space) { // Save the map in scratch1 for later. __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); - __ Cmp(scratch1, current_map); - } else { - __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), current_map); } - // Branch on the result of the map check. - __ j(not_equal, miss); + __ CheckMap(reg, Handle<Map>(current_map), + miss, DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); + // 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. @@ -901,8 +895,8 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object, LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); // Check the holder map. - __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), Handle<Map>(holder->map())); - __ j(not_equal, miss); + __ CheckMap(reg, Handle<Map>(holder->map()), + miss, DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); // Perform security check for access to the global object. ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); @@ -2187,7 +2181,7 @@ Handle<Code> CallStubCompiler::CompileCallGlobal( __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); } - // Setup the context (function already in rdi). + // Set up the context (function already in rdi). __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); // Jump to the cached code (tail call). @@ -2251,13 +2245,9 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback( // ----------------------------------- Label miss; - // Check that the object isn't a smi. - __ JumpIfSmi(rdx, &miss); - // Check that the map of the object hasn't changed. - __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), - Handle<Map>(object->map())); - __ j(not_equal, &miss); + __ CheckMap(rdx, Handle<Map>(object->map()), &miss, + DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); // Perform global security token check if needed. if (object->IsJSGlobalProxy()) { @@ -2301,13 +2291,9 @@ Handle<Code> StoreStubCompiler::CompileStoreInterceptor( // ----------------------------------- Label miss; - // Check that the object isn't a smi. - __ JumpIfSmi(rdx, &miss); - // Check that the map of the object hasn't changed. - __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), - Handle<Map>(receiver->map())); - __ j(not_equal, &miss); + __ CheckMap(rdx, Handle<Map>(receiver->map()), &miss, + DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); // Perform global security token check if needed. if (receiver->IsJSGlobalProxy()) { diff --git a/deps/v8/test/cctest/SConscript b/deps/v8/test/cctest/SConscript index 5fc9188ee9d..edb859e9cbc 100644 --- a/deps/v8/test/cctest/SConscript +++ b/deps/v8/test/cctest/SConscript @@ -73,6 +73,7 @@ SOURCES = { 'test-fixed-dtoa.cc', 'test-flags.cc', 'test-func-name-inference.cc', + 'test-hashing.cc', 'test-hashmap.cc', 'test-heap-profiler.cc', 'test-heap.cc', diff --git a/deps/v8/test/cctest/cctest.h b/deps/v8/test/cctest/cctest.h index c04d893c107..0b935622163 100644 --- a/deps/v8/test/cctest/cctest.h +++ b/deps/v8/test/cctest/cctest.h @@ -104,7 +104,7 @@ class ApiTestFuzzer: public v8::internal::Thread { FOURTH_PART, LAST_PART = FOURTH_PART }; - static void Setup(PartOfTest part); + static void SetUp(PartOfTest part); static void RunAllTests(); static void TearDown(); // This method switches threads if we are running the Threading test. diff --git a/deps/v8/test/cctest/test-alloc.cc b/deps/v8/test/cctest/test-alloc.cc index 899c9021ff0..c654dfa8bbe 100644 --- a/deps/v8/test/cctest/test-alloc.cc +++ b/deps/v8/test/cctest/test-alloc.cc @@ -203,10 +203,10 @@ class Block { TEST(CodeRange) { const int code_range_size = 32*MB; - OS::Setup(); + OS::SetUp(); Isolate::Current()->InitializeLoggingAndCounters(); CodeRange* code_range = new CodeRange(Isolate::Current()); - code_range->Setup(code_range_size); + code_range->SetUp(code_range_size); int current_allocated = 0; int total_allocated = 0; List<Block> blocks(1000); diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc index fb8becda384..d001e65263e 100644 --- a/deps/v8/test/cctest/test-api.cc +++ b/deps/v8/test/cctest/test-api.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -2867,6 +2867,16 @@ THREADED_TEST(isNumberType) { obj = env->Global()->Get(v8_str("obj")); CHECK(!obj->IsInt32()); CHECK(!obj->IsUint32()); + // Positive zero + CompileRun("var obj = 0.0;"); + obj = env->Global()->Get(v8_str("obj")); + CHECK(obj->IsInt32()); + CHECK(obj->IsUint32()); + // Positive zero + CompileRun("var obj = -0.0;"); + obj = env->Global()->Get(v8_str("obj")); + CHECK(!obj->IsInt32()); + CHECK(!obj->IsUint32()); } @@ -7941,7 +7951,7 @@ THREADED_TEST(CrossEval) { other->SetSecurityToken(token); current->SetSecurityToken(token); - // Setup reference from current to other. + // Set up reference from current to other. current->Global()->Set(v8_str("other"), other->Global()); // Check that new variables are introduced in other context. @@ -8021,7 +8031,7 @@ THREADED_TEST(EvalInDetachedGlobal) { v8::Persistent<Context> context0 = Context::New(); v8::Persistent<Context> context1 = Context::New(); - // Setup function in context0 that uses eval from context0. + // Set up function in context0 that uses eval from context0. context0->Enter(); v8::Handle<v8::Value> fun = CompileRun("var x = 42;" @@ -8059,7 +8069,7 @@ THREADED_TEST(CrossLazyLoad) { other->SetSecurityToken(token); current->SetSecurityToken(token); - // Setup reference from current to other. + // Set up reference from current to other. current->Global()->Set(v8_str("other"), other->Global()); // Trigger lazy loading in other context. @@ -10170,7 +10180,7 @@ void ApiTestFuzzer::Run() { static unsigned linear_congruential_generator; -void ApiTestFuzzer::Setup(PartOfTest part) { +void ApiTestFuzzer::SetUp(PartOfTest part) { linear_congruential_generator = i::FLAG_testing_prng_seed; fuzzing_ = true; int count = RegisterThreadedTest::count(); @@ -10234,25 +10244,25 @@ void ApiTestFuzzer::TearDown() { // Lets not be needlessly self-referential. TEST(Threading) { - ApiTestFuzzer::Setup(ApiTestFuzzer::FIRST_PART); + ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART); ApiTestFuzzer::RunAllTests(); ApiTestFuzzer::TearDown(); } TEST(Threading2) { - ApiTestFuzzer::Setup(ApiTestFuzzer::SECOND_PART); + ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART); ApiTestFuzzer::RunAllTests(); ApiTestFuzzer::TearDown(); } TEST(Threading3) { - ApiTestFuzzer::Setup(ApiTestFuzzer::THIRD_PART); + ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART); ApiTestFuzzer::RunAllTests(); ApiTestFuzzer::TearDown(); } TEST(Threading4) { - ApiTestFuzzer::Setup(ApiTestFuzzer::FOURTH_PART); + ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART); ApiTestFuzzer::RunAllTests(); ApiTestFuzzer::TearDown(); } @@ -12111,7 +12121,7 @@ THREADED_TEST(GetCallingContext) { callback_templ->GetFunction()); calling_context0->Exit(); - // Expose context0 in context1 and setup a function that calls the + // Expose context0 in context1 and set up a function that calls the // callback function. calling_context1->Enter(); calling_context1->Global()->Set(v8_str("context0"), @@ -12269,18 +12279,18 @@ THREADED_TEST(PixelArray) { i::Handle<i::Smi> value(i::Smi::FromInt(2)); i::Handle<i::Object> no_failure; - no_failure = i::SetElement(jsobj, 1, value, i::kNonStrictMode); + no_failure = i::JSObject::SetElement(jsobj, 1, value, i::kNonStrictMode); ASSERT(!no_failure.is_null()); i::USE(no_failure); CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value()); *value.location() = i::Smi::FromInt(256); - no_failure = i::SetElement(jsobj, 1, value, i::kNonStrictMode); + no_failure = i::JSObject::SetElement(jsobj, 1, value, i::kNonStrictMode); ASSERT(!no_failure.is_null()); i::USE(no_failure); CHECK_EQ(255, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value()); *value.location() = i::Smi::FromInt(-1); - no_failure = i::SetElement(jsobj, 1, value, i::kNonStrictMode); + no_failure = i::JSObject::SetElement(jsobj, 1, value, i::kNonStrictMode); ASSERT(!no_failure.is_null()); i::USE(no_failure); CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value()); @@ -13549,21 +13559,24 @@ THREADED_TEST(IdleNotification) { // Test that idle notification can be handled and eventually returns true. // This just checks the contract of the IdleNotification() function, // and does not verify that it does reasonable work. -THREADED_TEST(IdleNotificationWithHint) { +TEST(IdleNotificationWithHint) { v8::HandleScope scope; LocalContext env; - CompileRun("function binom(n, m) {" - " var C = [[1]];" - " for (var i = 1; i <= n; ++i) {" - " C[i] = [1];" - " for (var j = 1; j < i; ++j) {" - " C[i][j] = C[i-1][j-1] + C[i-1][j];" - " }" - " C[i][i] = 1;" - " }" - " return C[n][m];" - "};" - "binom(1000, 500)"); + { + i::AlwaysAllocateScope always_allocate; + CompileRun("function binom(n, m) {" + " var C = [[1]];" + " for (var i = 1; i <= n; ++i) {" + " C[i] = [1];" + " for (var j = 1; j < i; ++j) {" + " C[i][j] = C[i-1][j-1] + C[i-1][j];" + " }" + " C[i][i] = 1;" + " }" + " return C[n][m];" + "};" + "binom(1000, 500)"); + } bool rv = false; intptr_t old_size = HEAP->SizeOfObjects(); bool no_idle_work = v8::V8::IdleNotification(10); @@ -13665,6 +13678,59 @@ THREADED_TEST(GetHeapStatistics) { } +class VisitorImpl : public v8::ExternalResourceVisitor { + public: + VisitorImpl(TestResource* r1, TestResource* r2) + : resource1_(r1), + resource2_(r2), + found_resource1_(false), + found_resource2_(false) {} + virtual ~VisitorImpl() {} + virtual void VisitExternalString(v8::Handle<v8::String> string) { + if (!string->IsExternal()) { + CHECK(string->IsExternalAscii()); + return; + } + v8::String::ExternalStringResource* resource = + string->GetExternalStringResource(); + CHECK(resource); + if (resource1_ == resource) { + CHECK(!found_resource1_); + found_resource1_ = true; + } + if (resource2_ == resource) { + CHECK(!found_resource2_); + found_resource2_ = true; + } + } + void CheckVisitedResources() { + CHECK(found_resource1_); + CHECK(found_resource2_); + } + + private: + v8::String::ExternalStringResource* resource1_; + v8::String::ExternalStringResource* resource2_; + bool found_resource1_; + bool found_resource2_; +}; + +TEST(VisitExternalStrings) { + v8::HandleScope scope; + LocalContext env; + const char* string = "Some string"; + uint16_t* two_byte_string = AsciiToTwoByteString(string); + TestResource* resource1 = new TestResource(two_byte_string); + v8::Local<v8::String> string1 = v8::String::NewExternal(resource1); + TestResource* resource2 = new TestResource(two_byte_string); + v8::Local<v8::String> string2 = v8::String::NewExternal(resource2); + + VisitorImpl visitor(resource1, resource2); + v8::V8::VisitExternalResources(&visitor); + visitor.CheckVisitedResources(); +} + + static double DoubleFromBits(uint64_t value) { double target; memcpy(&target, &value, sizeof(target)); diff --git a/deps/v8/test/cctest/test-assembler-x64.cc b/deps/v8/test/cctest/test-assembler-x64.cc index 959cf3fe52a..d81923fa5c2 100644 --- a/deps/v8/test/cctest/test-assembler-x64.cc +++ b/deps/v8/test/cctest/test-assembler-x64.cc @@ -99,7 +99,7 @@ static void InitializeVM() { TEST(AssemblerX64ReturnOperation) { - OS::Setup(); + OS::SetUp(); // Allocate an executable page of memory. size_t actual_size; byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, @@ -121,7 +121,7 @@ TEST(AssemblerX64ReturnOperation) { } TEST(AssemblerX64StackOperations) { - OS::Setup(); + OS::SetUp(); // Allocate an executable page of memory. size_t actual_size; byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, @@ -153,7 +153,7 @@ TEST(AssemblerX64StackOperations) { } TEST(AssemblerX64ArithmeticOperations) { - OS::Setup(); + OS::SetUp(); // Allocate an executable page of memory. size_t actual_size; byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, @@ -175,7 +175,7 @@ TEST(AssemblerX64ArithmeticOperations) { } TEST(AssemblerX64ImulOperation) { - OS::Setup(); + OS::SetUp(); // Allocate an executable page of memory. size_t actual_size; byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, @@ -203,7 +203,7 @@ TEST(AssemblerX64ImulOperation) { } TEST(AssemblerX64MemoryOperands) { - OS::Setup(); + OS::SetUp(); // Allocate an executable page of memory. size_t actual_size; byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, @@ -237,7 +237,7 @@ TEST(AssemblerX64MemoryOperands) { } TEST(AssemblerX64ControlFlow) { - OS::Setup(); + OS::SetUp(); // Allocate an executable page of memory. size_t actual_size; byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, @@ -266,7 +266,7 @@ TEST(AssemblerX64ControlFlow) { } TEST(AssemblerX64LoopImmediates) { - OS::Setup(); + OS::SetUp(); // Allocate an executable page of memory. size_t actual_size; byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize, diff --git a/deps/v8/test/cctest/test-cpu-profiler.cc b/deps/v8/test/cctest/test-cpu-profiler.cc index f567a0f7709..b10e6889ec8 100644 --- a/deps/v8/test/cctest/test-cpu-profiler.cc +++ b/deps/v8/test/cctest/test-cpu-profiler.cc @@ -216,7 +216,7 @@ TEST(TickEvents) { TEST(CrashIfStoppingLastNonExistentProfile) { InitializeVM(); TestSetup test_setup; - CpuProfiler::Setup(); + CpuProfiler::SetUp(); CpuProfiler::StartProfiling("1"); CpuProfiler::StopProfiling("2"); CpuProfiler::StartProfiling("1"); @@ -268,7 +268,7 @@ TEST(Issue1398) { TEST(DeleteAllCpuProfiles) { InitializeVM(); TestSetup test_setup; - CpuProfiler::Setup(); + CpuProfiler::SetUp(); CHECK_EQ(0, CpuProfiler::GetProfilesCount()); CpuProfiler::DeleteAllProfiles(); CHECK_EQ(0, CpuProfiler::GetProfilesCount()); diff --git a/deps/v8/test/cctest/test-debug.cc b/deps/v8/test/cctest/test-debug.cc index 8543a377202..4fa7afa0997 100644 --- a/deps/v8/test/cctest/test-debug.cc +++ b/deps/v8/test/cctest/test-debug.cc @@ -2743,7 +2743,7 @@ TEST(DebugStepKeyedLoadLoop) { v8::Handle<v8::Value> args[kArgc] = { a }; foo->Call(env->Global(), kArgc, args); - // Setup break point and step through the function. + // Set up break point and step through the function. SetBreakPoint(foo, 3); step_action = StepNext; break_point_hit_count = 0; @@ -2790,7 +2790,7 @@ TEST(DebugStepKeyedStoreLoop) { v8::Handle<v8::Value> args[kArgc] = { a }; foo->Call(env->Global(), kArgc, args); - // Setup break point and step through the function. + // Set up break point and step through the function. SetBreakPoint(foo, 3); step_action = StepNext; break_point_hit_count = 0; @@ -2834,7 +2834,7 @@ TEST(DebugStepNamedLoadLoop) { // Call function without any break points to ensure inlining is in place. foo->Call(env->Global(), 0, NULL); - // Setup break point and step through the function. + // Set up break point and step through the function. SetBreakPoint(foo, 4); step_action = StepNext; break_point_hit_count = 0; @@ -2869,7 +2869,7 @@ static void DoDebugStepNamedStoreLoop(int expected) { // Call function without any break points to ensure inlining is in place. foo->Call(env->Global(), 0, NULL); - // Setup break point and step through the function. + // Set up break point and step through the function. SetBreakPoint(foo, 3); step_action = StepNext; break_point_hit_count = 0; @@ -5709,7 +5709,7 @@ void HostDispatchV8Thread::Run() { v8::HandleScope scope; DebugLocalContext env; - // Setup message and host dispatch handlers. + // Set up message and host dispatch handlers. v8::Debug::SetMessageHandler2(HostDispatchMessageHandler); v8::Debug::SetHostDispatchHandler(HostDispatchDispatchHandler, 10 /* ms */); @@ -5797,7 +5797,7 @@ void DebugMessageDispatchV8Thread::Run() { v8::HandleScope scope; DebugLocalContext env; - // Setup debug message dispatch handler. + // Set up debug message dispatch handler. v8::Debug::SetDebugMessageDispatchHandler(DebugMessageHandler); CompileRun("var y = 1 + 2;\n"); @@ -5851,7 +5851,7 @@ TEST(DebuggerAgent) { bool ok; // Initialize the socket library. - i::Socket::Setup(); + i::Socket::SetUp(); // Test starting and stopping the agent without any client connection. debugger->StartAgent("test", kPort1); @@ -5949,7 +5949,7 @@ TEST(DebuggerAgentProtocolOverflowHeader) { OS::SNPrintF(i::Vector<char>(port_str, kPortBufferLen), "%d", kPort); // Initialize the socket library. - i::Socket::Setup(); + i::Socket::SetUp(); // Create a socket server to receive a debugger agent message. DebuggerAgentProtocolServerThread* server = diff --git a/deps/v8/test/cctest/test-disasm-arm.cc b/deps/v8/test/cctest/test-disasm-arm.cc index 032e6bc0fcf..0e9432d95df 100644 --- a/deps/v8/test/cctest/test-disasm-arm.cc +++ b/deps/v8/test/cctest/test-disasm-arm.cc @@ -69,10 +69,10 @@ bool DisassembleAndCompare(byte* pc, const char* compare_string) { } -// Setup V8 to a state where we can at least run the assembler and +// Set up V8 to a state where we can at least run the assembler and // disassembler. Declare the variables and allocate the data structures used // in the rest of the macros. -#define SETUP() \ +#define SET_UP() \ InitializeVM(); \ v8::HandleScope scope; \ byte *buffer = reinterpret_cast<byte*>(malloc(4*1024)); \ @@ -102,7 +102,7 @@ if (failure) { \ TEST(Type0) { - SETUP(); + SET_UP(); COMPARE(and_(r0, r1, Operand(r2)), "e0010002 and r0, r1, r2"); @@ -329,7 +329,7 @@ TEST(Type0) { TEST(Type1) { - SETUP(); + SET_UP(); COMPARE(and_(r0, r1, Operand(0x00000000)), "e2010000 and r0, r1, #0"); @@ -358,7 +358,7 @@ TEST(Type1) { TEST(Type3) { - SETUP(); + SET_UP(); if (CpuFeatures::IsSupported(ARMv7)) { COMPARE(ubfx(r0, r1, 5, 10), @@ -413,7 +413,7 @@ TEST(Type3) { TEST(Vfp) { - SETUP(); + SET_UP(); if (CpuFeatures::IsSupported(VFP3)) { CpuFeatures::Scope scope(VFP3); @@ -546,7 +546,7 @@ TEST(Vfp) { TEST(LoadStore) { - SETUP(); + SET_UP(); COMPARE(ldrb(r0, MemOperand(r1)), "e5d10000 ldrb r0, [r1, #+0]"); diff --git a/deps/v8/test/cctest/test-disasm-mips.cc b/deps/v8/test/cctest/test-disasm-mips.cc index 5ad99d7a397..8eadc6483b8 100644 --- a/deps/v8/test/cctest/test-disasm-mips.cc +++ b/deps/v8/test/cctest/test-disasm-mips.cc @@ -71,10 +71,10 @@ bool DisassembleAndCompare(byte* pc, const char* compare_string) { } -// Setup V8 to a state where we can at least run the assembler and +// Set up V8 to a state where we can at least run the assembler and // disassembler. Declare the variables and allocate the data structures used // in the rest of the macros. -#define SETUP() \ +#define SET_UP() \ InitializeVM(); \ v8::HandleScope scope; \ byte *buffer = reinterpret_cast<byte*>(malloc(4*1024)); \ @@ -104,7 +104,7 @@ if (failure) { \ TEST(Type0) { - SETUP(); + SET_UP(); COMPARE(addu(a0, a1, a2), "00a62021 addu a0, a1, a2"); diff --git a/deps/v8/test/cctest/test-hashing.cc b/deps/v8/test/cctest/test-hashing.cc index df1ab200131..a6265105eb7 100644 --- a/deps/v8/test/cctest/test-hashing.cc +++ b/deps/v8/test/cctest/test-hashing.cc @@ -46,65 +46,106 @@ typedef uint32_t (*HASH_FUNCTION)(); static v8::Persistent<v8::Context> env; -#define __ assm-> +#define __ masm-> -void generate(MacroAssembler* assm, i::Vector<const char> string) { +void generate(MacroAssembler* masm, i::Vector<const char> string) { + // GenerateHashInit takes the first character as an argument so it can't + // handle the zero length string. + ASSERT(string.length() > 0); #ifdef V8_TARGET_ARCH_IA32 __ push(ebx); __ push(ecx); __ mov(eax, Immediate(0)); - if (string.length() > 0) { - __ mov(ebx, Immediate(string.at(0))); - StringHelper::GenerateHashInit(assm, eax, ebx, ecx); - } + __ mov(ebx, Immediate(string.at(0))); + StringHelper::GenerateHashInit(masm, eax, ebx, ecx); for (int i = 1; i < string.length(); i++) { __ mov(ebx, Immediate(string.at(i))); - StringHelper::GenerateHashAddCharacter(assm, eax, ebx, ecx); + StringHelper::GenerateHashAddCharacter(masm, eax, ebx, ecx); } - StringHelper::GenerateHashGetHash(assm, eax, ecx); + StringHelper::GenerateHashGetHash(masm, eax, ecx); __ pop(ecx); __ pop(ebx); __ Ret(); #elif V8_TARGET_ARCH_X64 + __ push(kRootRegister); + __ InitializeRootRegister(); __ push(rbx); __ push(rcx); __ movq(rax, Immediate(0)); - if (string.length() > 0) { - __ movq(rbx, Immediate(string.at(0))); - StringHelper::GenerateHashInit(assm, rax, rbx, rcx); - } + __ movq(rbx, Immediate(string.at(0))); + StringHelper::GenerateHashInit(masm, rax, rbx, rcx); for (int i = 1; i < string.length(); i++) { __ movq(rbx, Immediate(string.at(i))); - StringHelper::GenerateHashAddCharacter(assm, rax, rbx, rcx); + StringHelper::GenerateHashAddCharacter(masm, rax, rbx, rcx); } - StringHelper::GenerateHashGetHash(assm, rax, rcx); + StringHelper::GenerateHashGetHash(masm, rax, rcx); __ pop(rcx); __ pop(rbx); + __ pop(kRootRegister); __ Ret(); #elif V8_TARGET_ARCH_ARM + __ push(kRootRegister); + __ InitializeRootRegister(); + __ mov(r0, Operand(0)); - if (string.length() > 0) { - __ mov(ip, Operand(string.at(0))); - StringHelper::GenerateHashInit(assm, r0, ip); - } + __ mov(ip, Operand(string.at(0))); + StringHelper::GenerateHashInit(masm, r0, ip); for (int i = 1; i < string.length(); i++) { __ mov(ip, Operand(string.at(i))); - StringHelper::GenerateHashAddCharacter(assm, r0, ip); + StringHelper::GenerateHashAddCharacter(masm, r0, ip); } - StringHelper::GenerateHashGetHash(assm, r0); + StringHelper::GenerateHashGetHash(masm, r0); + __ pop(kRootRegister); __ mov(pc, Operand(lr)); #elif V8_TARGET_ARCH_MIPS + __ push(kRootRegister); + __ InitializeRootRegister(); + __ li(v0, Operand(0)); - if (string.length() > 0) { - __ li(t1, Operand(string.at(0))); - StringHelper::GenerateHashInit(assm, v0, t1); - } + __ li(t1, Operand(string.at(0))); + StringHelper::GenerateHashInit(masm, v0, t1); for (int i = 1; i < string.length(); i++) { __ li(t1, Operand(string.at(i))); - StringHelper::GenerateHashAddCharacter(assm, v0, t1); + StringHelper::GenerateHashAddCharacter(masm, v0, t1); } - StringHelper::GenerateHashGetHash(assm, v0); + StringHelper::GenerateHashGetHash(masm, v0); + __ pop(kRootRegister); + __ jr(ra); + __ nop(); +#endif +} + + +void generate(MacroAssembler* masm, uint32_t key) { +#ifdef V8_TARGET_ARCH_IA32 + __ push(ebx); + __ mov(eax, Immediate(key)); + __ GetNumberHash(eax, ebx); + __ pop(ebx); + __ Ret(); +#elif V8_TARGET_ARCH_X64 + __ push(kRootRegister); + __ InitializeRootRegister(); + __ push(rbx); + __ movq(rax, Immediate(key)); + __ GetNumberHash(rax, rbx); + __ pop(rbx); + __ pop(kRootRegister); + __ Ret(); +#elif V8_TARGET_ARCH_ARM + __ push(kRootRegister); + __ InitializeRootRegister(); + __ mov(r0, Operand(key)); + __ GetNumberHash(r0, ip); + __ pop(kRootRegister); + __ mov(pc, Operand(lr)); +#elif V8_TARGET_ARCH_MIPS + __ push(kRootRegister); + __ InitializeRootRegister(); + __ li(v0, Operand(key)); + __ GetNumberHash(v0, t1); + __ pop(kRootRegister); __ jr(ra); __ nop(); #endif @@ -114,12 +155,12 @@ void generate(MacroAssembler* assm, i::Vector<const char> string) { void check(i::Vector<const char> string) { v8::HandleScope scope; v8::internal::byte buffer[2048]; - MacroAssembler assm(Isolate::Current(), buffer, sizeof buffer); + MacroAssembler masm(Isolate::Current(), buffer, sizeof buffer); - generate(&assm, string); + generate(&masm, string); CodeDesc desc; - assm.GetCode(&desc); + masm.GetCode(&desc); Code* code = Code::cast(HEAP->CreateCode( desc, Code::ComputeFlags(Code::STUB), @@ -140,12 +181,47 @@ void check(i::Vector<const char> string) { } +void check(uint32_t key) { + v8::HandleScope scope; + v8::internal::byte buffer[2048]; + MacroAssembler masm(Isolate::Current(), buffer, sizeof buffer); + + generate(&masm, key); + + CodeDesc desc; + masm.GetCode(&desc); + Code* code = Code::cast(HEAP->CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(HEAP->undefined_value()))->ToObjectChecked()); + CHECK(code->IsCode()); + + HASH_FUNCTION hash = FUNCTION_CAST<HASH_FUNCTION>(code->entry()); +#ifdef USE_SIMULATOR + uint32_t codegen_hash = + reinterpret_cast<uint32_t>(CALL_GENERATED_CODE(hash, 0, 0, 0, 0, 0)); +#else + uint32_t codegen_hash = hash(); +#endif + + uint32_t runtime_hash = ComputeIntegerHash( + key, + Isolate::Current()->heap()->HashSeed()); + CHECK(runtime_hash == codegen_hash); +} + + void check_twochars(char a, char b) { char ab[2] = {a, b}; check(i::Vector<const char>(ab, 2)); } +static uint32_t PseudoRandom(uint32_t i, uint32_t j) { + return ~(~((i * 781) ^ (j * 329))); +} + + TEST(StringHash) { if (env.IsEmpty()) env = v8::Context::New(); for (int a = 0; a < String::kMaxAsciiCharCode; a++) { @@ -156,7 +232,6 @@ TEST(StringHash) { check_twochars(static_cast<char>(a), static_cast<char>(b)); } } - check(i::Vector<const char>("", 0)); check(i::Vector<const char>("*", 1)); check(i::Vector<const char>(".zZ", 3)); check(i::Vector<const char>("muc", 3)); @@ -164,4 +239,22 @@ TEST(StringHash) { check(i::Vector<const char>("-=[ vee eight ftw ]=-", 21)); } + +TEST(NumberHash) { + if (env.IsEmpty()) env = v8::Context::New(); + + // Some specific numbers + for (uint32_t key = 0; key < 42; key += 7) { + check(key); + } + + // Some pseudo-random numbers + static const uint32_t kLimit = 1000; + for (uint32_t i = 0; i < 5; i++) { + for (uint32_t j = 0; j < 5; j++) { + check(PseudoRandom(i, j) % kLimit); + } + } +} + #undef __ diff --git a/deps/v8/test/cctest/test-heap.cc b/deps/v8/test/cctest/test-heap.cc index 42b5789d4d0..1e4e332b4ee 100644 --- a/deps/v8/test/cctest/test-heap.cc +++ b/deps/v8/test/cctest/test-heap.cc @@ -1187,6 +1187,44 @@ TEST(TestInternalWeakListsTraverseWithGC) { } +TEST(TestSizeOfObjects) { + v8::V8::Initialize(); + + // Get initial heap size after several full GCs, which will stabilize + // the heap size and return with sweeping finished completely. + HEAP->CollectAllGarbage(Heap::kNoGCFlags); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); + HEAP->CollectAllGarbage(Heap::kNoGCFlags); + CHECK(HEAP->old_pointer_space()->IsSweepingComplete()); + int initial_size = static_cast<int>(HEAP->SizeOfObjects()); + + { + // Allocate objects on several different old-space pages so that + // lazy sweeping kicks in for subsequent GC runs. + AlwaysAllocateScope always_allocate; + int filler_size = static_cast<int>(FixedArray::SizeFor(8192)); + for (int i = 1; i <= 100; i++) { + HEAP->AllocateFixedArray(8192, TENURED)->ToObjectChecked(); + CHECK_EQ(initial_size + i * filler_size, + static_cast<int>(HEAP->SizeOfObjects())); + } + } + + // The heap size should go back to initial size after a full GC, even + // though sweeping didn't finish yet. + HEAP->CollectAllGarbage(Heap::kNoGCFlags); + CHECK(!HEAP->old_pointer_space()->IsSweepingComplete()); + CHECK_EQ(initial_size, static_cast<int>(HEAP->SizeOfObjects())); + + // Advancing the sweeper step-wise should not change the heap size. + while (!HEAP->old_pointer_space()->IsSweepingComplete()) { + HEAP->old_pointer_space()->AdvanceSweeper(KB); + CHECK_EQ(initial_size, static_cast<int>(HEAP->SizeOfObjects())); + } +} + + TEST(TestSizeOfObjectsVsHeapIteratorPrecision) { InitializeVM(); HEAP->EnsureHeapIsIterable(); @@ -1476,3 +1514,61 @@ TEST(LeakGlobalContextViaMapProto) { HEAP->CollectAllAvailableGarbage(); CHECK_EQ(0, NumberOfGlobalObjects()); } + + +TEST(InstanceOfStubWriteBarrier) { + i::FLAG_allow_natives_syntax = true; +#ifdef DEBUG + i::FLAG_verify_heap = true; +#endif + InitializeVM(); + if (!i::V8::UseCrankshaft()) return; + v8::HandleScope outer_scope; + + { + v8::HandleScope scope; + CompileRun( + "function foo () { }" + "function mkbar () { return new (new Function(\"\")) (); }" + "function f (x) { return (x instanceof foo); }" + "function g () { f(mkbar()); }" + "f(new foo()); f(new foo());" + "%OptimizeFunctionOnNextCall(f);" + "f(new foo()); g();"); + } + + IncrementalMarking* marking = HEAP->incremental_marking(); + marking->Abort(); + marking->Start(); + + Handle<JSFunction> f = + v8::Utils::OpenHandle( + *v8::Handle<v8::Function>::Cast( + v8::Context::GetCurrent()->Global()->Get(v8_str("f")))); + + CHECK(f->IsOptimized()); + + while (!Marking::IsBlack(Marking::MarkBitFrom(f->code())) && + !marking->IsStopped()) { + marking->Step(MB); + } + + CHECK(marking->IsMarking()); + + // Discard any pending GC requests otherwise we will get GC when we enter + // code below. + if (ISOLATE->stack_guard()->IsGCRequest()) { + ISOLATE->stack_guard()->Continue(GC_REQUEST); + } + + { + v8::HandleScope scope; + v8::Handle<v8::Object> global = v8::Context::GetCurrent()->Global(); + v8::Handle<v8::Function> g = + v8::Handle<v8::Function>::Cast(global->Get(v8_str("g"))); + g->Call(global, 0, NULL); + } + + HEAP->incremental_marking()->set_should_hurry(true); + HEAP->CollectGarbage(OLD_POINTER_SPACE); +} diff --git a/deps/v8/test/cctest/test-platform-linux.cc b/deps/v8/test/cctest/test-platform-linux.cc index 756b9473c96..2a8d4978509 100644 --- a/deps/v8/test/cctest/test-platform-linux.cc +++ b/deps/v8/test/cctest/test-platform-linux.cc @@ -67,7 +67,7 @@ TEST(BusyLock) { TEST(VirtualMemory) { - OS::Setup(); + OS::SetUp(); VirtualMemory* vm = new VirtualMemory(1 * MB); CHECK(vm->IsReserved()); void* block_addr = vm->address(); diff --git a/deps/v8/test/cctest/test-platform-win32.cc b/deps/v8/test/cctest/test-platform-win32.cc index 9bd0014c6f7..36b30aaceb6 100644 --- a/deps/v8/test/cctest/test-platform-win32.cc +++ b/deps/v8/test/cctest/test-platform-win32.cc @@ -13,7 +13,7 @@ using namespace ::v8::internal; TEST(VirtualMemory) { - OS::Setup(); + OS::SetUp(); VirtualMemory* vm = new VirtualMemory(1 * MB); CHECK(vm->IsReserved()); void* block_addr = vm->address(); diff --git a/deps/v8/test/cctest/test-sockets.cc b/deps/v8/test/cctest/test-sockets.cc index 4af55dbe9b2..ad7354002ff 100644 --- a/deps/v8/test/cctest/test-sockets.cc +++ b/deps/v8/test/cctest/test-sockets.cc @@ -129,7 +129,7 @@ TEST(Socket) { bool ok; // Initialize socket support. - ok = Socket::Setup(); + ok = Socket::SetUp(); CHECK(ok); // Send and receive some data. diff --git a/deps/v8/test/cctest/test-spaces.cc b/deps/v8/test/cctest/test-spaces.cc index ee60086ed24..6e495bc169d 100644 --- a/deps/v8/test/cctest/test-spaces.cc +++ b/deps/v8/test/cctest/test-spaces.cc @@ -125,14 +125,14 @@ class TestMemoryAllocatorScope { TEST(MemoryAllocator) { - OS::Setup(); + OS::SetUp(); Isolate* isolate = Isolate::Current(); isolate->InitializeLoggingAndCounters(); Heap* heap = isolate->heap(); CHECK(isolate->heap()->ConfigureHeapDefault()); MemoryAllocator* memory_allocator = new MemoryAllocator(isolate); - CHECK(memory_allocator->Setup(heap->MaxReserved(), + CHECK(memory_allocator->SetUp(heap->MaxReserved(), heap->MaxExecutableSize())); int total_pages = 0; @@ -175,21 +175,21 @@ TEST(MemoryAllocator) { TEST(NewSpace) { - OS::Setup(); + OS::SetUp(); Isolate* isolate = Isolate::Current(); isolate->InitializeLoggingAndCounters(); Heap* heap = isolate->heap(); CHECK(heap->ConfigureHeapDefault()); MemoryAllocator* memory_allocator = new MemoryAllocator(isolate); - CHECK(memory_allocator->Setup(heap->MaxReserved(), + CHECK(memory_allocator->SetUp(heap->MaxReserved(), heap->MaxExecutableSize())); TestMemoryAllocatorScope test_scope(isolate, memory_allocator); NewSpace new_space(heap); - CHECK(new_space.Setup(HEAP->ReservedSemiSpaceSize(), + CHECK(new_space.SetUp(HEAP->ReservedSemiSpaceSize(), HEAP->ReservedSemiSpaceSize())); - CHECK(new_space.HasBeenSetup()); + CHECK(new_space.HasBeenSetUp()); while (new_space.Available() >= Page::kMaxHeapObjectSize) { Object* obj = @@ -204,13 +204,13 @@ TEST(NewSpace) { TEST(OldSpace) { - OS::Setup(); + OS::SetUp(); Isolate* isolate = Isolate::Current(); isolate->InitializeLoggingAndCounters(); Heap* heap = isolate->heap(); CHECK(heap->ConfigureHeapDefault()); MemoryAllocator* memory_allocator = new MemoryAllocator(isolate); - CHECK(memory_allocator->Setup(heap->MaxReserved(), + CHECK(memory_allocator->SetUp(heap->MaxReserved(), heap->MaxExecutableSize())); TestMemoryAllocatorScope test_scope(isolate, memory_allocator); @@ -220,7 +220,7 @@ TEST(OldSpace) { NOT_EXECUTABLE); CHECK(s != NULL); - CHECK(s->Setup()); + CHECK(s->SetUp()); while (s->Available() > 0) { s->AllocateRaw(Page::kMaxHeapObjectSize)->ToObjectUnchecked(); diff --git a/deps/v8/test/cctest/test-utils.cc b/deps/v8/test/cctest/test-utils.cc index e4f70df4093..df8ff72e4f3 100644 --- a/deps/v8/test/cctest/test-utils.cc +++ b/deps/v8/test/cctest/test-utils.cc @@ -105,7 +105,7 @@ void TestMemCopy(Vector<byte> src, TEST(MemCopy) { v8::V8::Initialize(); - OS::Setup(); + OS::SetUp(); const int N = OS::kMinComplexMemCopy + 128; Vector<byte> buffer1 = Vector<byte>::New(N); Vector<byte> buffer2 = Vector<byte>::New(N); diff --git a/deps/v8/test/mjsunit/external-array.js b/deps/v8/test/mjsunit/external-array.js index 81c6cfe8b44..72cfd859563 100644 --- a/deps/v8/test/mjsunit/external-array.js +++ b/deps/v8/test/mjsunit/external-array.js @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -43,6 +43,50 @@ f(a); assertEquals(0, a[0]); assertEquals(0, a[1]); +// No-parameter constructor should fail right now. +function abfunc1() { + return new ArrayBuffer(); +} +assertThrows(abfunc1); + +// Test derivation from an ArrayBuffer +var ab = new ArrayBuffer(12); +var derived_uint8 = new Uint8Array(ab); +assertEquals(12, derived_uint8.length); +var derived_uint32 = new Uint32Array(ab); +assertEquals(3, derived_uint32.length); +var derived_uint32_2 = new Uint32Array(ab,4); +assertEquals(2, derived_uint32_2.length); +var derived_uint32_3 = new Uint32Array(ab,4,1); +assertEquals(1, derived_uint32_3.length); + +// If a given byteOffset and length references an area beyond the end of the +// ArrayBuffer an exception is raised. +function abfunc3() { + new Uint32Array(ab,4,3); +} +assertThrows(abfunc3); +function abfunc4() { + new Uint32Array(ab,16); +} +assertThrows(abfunc4); + +// The given byteOffset must be a multiple of the element size of the specific +// type, otherwise an exception is raised. +function abfunc5() { + new Uint32Array(ab,5); +} +assertThrows(abfunc5); + +// If length is not explicitly specified, the length of the ArrayBuffer minus +// the byteOffset must be a multiple of the element size of the specific type, +// or an exception is raised. +var ab2 = new ArrayBuffer(13); +function abfunc6() { + new Uint32Array(ab2,4); +} +assertThrows(abfunc6); + // Test the correct behavior of the |BYTES_PER_ELEMENT| property (which is // "constant", but not read-only). a = new Int32Array(2); diff --git a/deps/v8/test/mjsunit/math-min-max.js b/deps/v8/test/mjsunit/math-min-max.js index 0833c5c8099..7717b3bff2d 100644 --- a/deps/v8/test/mjsunit/math-min-max.js +++ b/deps/v8/test/mjsunit/math-min-max.js @@ -115,3 +115,67 @@ assertEquals(NaN, Math.max(1, 'oxen')); assertEquals(Infinity, 1/Math.max(ZERO, -0)); assertEquals(Infinity, 1/Math.max(-0, ZERO)); + +function run(crankshaft_test) { + crankshaft_test(1); + crankshaft_test(1); + %OptimizeFunctionOnNextCall(crankshaft_test); + crankshaft_test(-0); +} + +function crankshaft_test_1(arg) { + var v1 = 1; + var v2 = 5; + var v3 = 1.5; + var v4 = 5.5; + var v5 = 2; + var v6 = 6; + var v7 = 0; + var v8 = -0; + + var v9 = 9.9; + var v0 = 10.1; + // Integer32 representation. + assertEquals(v2, Math.max(v1++, v2++)); + assertEquals(v1, Math.min(v1++, v2++)); + // Tagged representation. + assertEquals(v4, Math.max(v3, v4)); + assertEquals(v3, Math.min(v3, v4)); + assertEquals(v6, Math.max(v5, v6)); + assertEquals(v5, Math.min(v5, v6)); + // Double representation. + assertEquals(v0, Math.max(v0++, v9++)); + assertEquals(v9, Math.min(v0++, v9++)); + // Minus zero. + assertEquals(Infinity, 1/Math.max(v7, v8)); + assertEquals(-Infinity, 1/Math.min(v7, v8)); + // NaN. + assertEquals(NaN, Math.max(NaN, v8)); + assertEquals(NaN, Math.min(NaN, v9)); + assertEquals(NaN, Math.max(v8, NaN)); + assertEquals(NaN, Math.min(v9, NaN)); + // Minus zero as Integer32. + assertEquals((arg === -0) ? -Infinity : 1, 1/Math.min(arg, v2)); +} + +run(crankshaft_test_1); + +function crankshaft_test_2() { + var v9 = {}; + v9.valueOf = function() { return 6; } + // Deopt expected due to non-heapnumber objects. + assertEquals(6, Math.min(v9, 12)); +} + +run(crankshaft_test_2); + +// Test overriding Math.min and Math.max +Math.min = function(a, b) { return a + b; } +Math.max = function(a, b) { return a - b; } + +function crankshaft_test_3() { + assertEquals(8, Math.min(3, 5)); + assertEquals(3, Math.max(5, 2)); +} + +run(crankshaft_test_3); diff --git a/deps/v8/test/mjsunit/regress/regress-109195.js b/deps/v8/test/mjsunit/regress/regress-109195.js new file mode 100644 index 00000000000..97538aa1674 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-109195.js @@ -0,0 +1,65 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --expose-debug-as debug +var Debug = debug.Debug; + +function listener(event, exec_state, event_data, data) { + for (var i = 0, n = exec_state.frameCount(); i < n; i++) { + exec_state.frame().scopeCount(i); + } + exec_state.prepareStep(Debug.StepAction.Continue, 1); +} + +Debug.setListener(listener); + +var F = function () { + 1, function () { + var d = 0; + (function () { d; }); + debugger; + }(); +}; + +var src = "(" + F.toString() + ")()"; +eval(src); + +Function.prototype.__defineGetter__("f", function () { + debugger; + return 0; +}); + +var G = function () { + 1, function () { + var d = 0; + (function () { d; }); + debugger; + }['f']; +}; + +var src = "(" + G.toString() + ")()"; +eval(src); diff --git a/deps/v8/test/mjsunit/regress/regress-1898.js b/deps/v8/test/mjsunit/regress/regress-1898.js new file mode 100644 index 00000000000..5440446fbf7 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-1898.js @@ -0,0 +1,37 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --allow-natives-syntax + +function f(x) { + Math.log(Math.min(0.1, Math.abs(x))); +} + +f(0.1); +f(0.1); +%OptimizeFunctionOnNextCall(f); +f(0.1); diff --git a/deps/v8/tools/grokdump.py b/deps/v8/tools/grokdump.py index 44f9518f63f..9977289872b 100755 --- a/deps/v8/tools/grokdump.py +++ b/deps/v8/tools/grokdump.py @@ -506,10 +506,10 @@ class MinidumpReader(object): # List of V8 instance types. Obtained by adding the code below to any .cc file. # -# #define DUMP_TYPE(T) printf("%d: \"%s\",\n", T, #T); +# #define DUMP_TYPE(T) printf(" %d: \"%s\",\n", T, #T); # struct P { # P() { -# printf("{\n"); +# printf("INSTANCE_TYPES = {\n"); # INSTANCE_TYPE_LIST(DUMP_TYPE) # printf("}\n"); # } @@ -556,34 +556,35 @@ INSTANCE_TYPES = { 144: "EXTERNAL_PIXEL_ARRAY_TYPE", 146: "FILLER_TYPE", 147: "ACCESSOR_INFO_TYPE", - 148: "ACCESS_CHECK_INFO_TYPE", - 149: "INTERCEPTOR_INFO_TYPE", - 150: "CALL_HANDLER_INFO_TYPE", - 151: "FUNCTION_TEMPLATE_INFO_TYPE", - 152: "OBJECT_TEMPLATE_INFO_TYPE", - 153: "SIGNATURE_INFO_TYPE", - 154: "TYPE_SWITCH_INFO_TYPE", - 155: "SCRIPT_TYPE", - 156: "CODE_CACHE_TYPE", - 157: "POLYMORPHIC_CODE_CACHE_TYPE", - 160: "FIXED_ARRAY_TYPE", + 148: "ACCESSOR_PAIR_TYPE", + 149: "ACCESS_CHECK_INFO_TYPE", + 150: "INTERCEPTOR_INFO_TYPE", + 151: "CALL_HANDLER_INFO_TYPE", + 152: "FUNCTION_TEMPLATE_INFO_TYPE", + 153: "OBJECT_TEMPLATE_INFO_TYPE", + 154: "SIGNATURE_INFO_TYPE", + 155: "TYPE_SWITCH_INFO_TYPE", + 156: "SCRIPT_TYPE", + 157: "CODE_CACHE_TYPE", + 158: "POLYMORPHIC_CODE_CACHE_TYPE", + 161: "FIXED_ARRAY_TYPE", 145: "FIXED_DOUBLE_ARRAY_TYPE", - 161: "SHARED_FUNCTION_INFO_TYPE", - 162: "JS_MESSAGE_OBJECT_TYPE", - 165: "JS_VALUE_TYPE", - 166: "JS_OBJECT_TYPE", - 167: "JS_CONTEXT_EXTENSION_OBJECT_TYPE", - 168: "JS_GLOBAL_OBJECT_TYPE", - 169: "JS_BUILTINS_OBJECT_TYPE", - 170: "JS_GLOBAL_PROXY_TYPE", - 171: "JS_ARRAY_TYPE", - 164: "JS_PROXY_TYPE", - 174: "JS_WEAK_MAP_TYPE", - 175: "JS_REGEXP_TYPE", - 176: "JS_FUNCTION_TYPE", - 163: "JS_FUNCTION_PROXY_TYPE", - 158: "DEBUG_INFO_TYPE", - 159: "BREAK_POINT_INFO_TYPE", + 162: "SHARED_FUNCTION_INFO_TYPE", + 163: "JS_MESSAGE_OBJECT_TYPE", + 166: "JS_VALUE_TYPE", + 167: "JS_OBJECT_TYPE", + 168: "JS_CONTEXT_EXTENSION_OBJECT_TYPE", + 169: "JS_GLOBAL_OBJECT_TYPE", + 170: "JS_BUILTINS_OBJECT_TYPE", + 171: "JS_GLOBAL_PROXY_TYPE", + 172: "JS_ARRAY_TYPE", + 165: "JS_PROXY_TYPE", + 175: "JS_WEAK_MAP_TYPE", + 176: "JS_REGEXP_TYPE", + 177: "JS_FUNCTION_TYPE", + 164: "JS_FUNCTION_PROXY_TYPE", + 159: "DEBUG_INFO_TYPE", + 160: "BREAK_POINT_INFO_TYPE", } diff --git a/deps/v8/tools/ll_prof.py b/deps/v8/tools/ll_prof.py index 5c07d9165f9..51ba672acaa 100755 --- a/deps/v8/tools/ll_prof.py +++ b/deps/v8/tools/ll_prof.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright 2010 the V8 project authors. All rights reserved. +# Copyright 2012 the V8 project authors. All rights reserved. # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: @@ -673,7 +673,9 @@ OBJDUMP_SECTION_HEADER_RE = re.compile( OBJDUMP_SYMBOL_LINE_RE = re.compile( r"^([a-f0-9]+)\s(.{7})\s(\S+)\s+([a-f0-9]+)\s+(?:\.hidden\s+)?(.*)$") OBJDUMP_DYNAMIC_SYMBOLS_START_RE = re.compile( - r"^DYNAMIC SYMBOL TABLE") + r"^DYNAMIC SYMBOL TABLE") +OBJDUMP_SKIP_RE = re.compile( + r"^.*ld\.so\.cache$") KERNEL_ALLSYMS_FILE = "/proc/kallsyms" PERF_KERNEL_ALLSYMS_RE = re.compile( r".*kallsyms.*") @@ -692,6 +694,8 @@ class LibraryRepo(object): # is 0. if mmap_info.tid == 0 and not options.kernel: return True + if OBJDUMP_SKIP_RE.match(mmap_info.filename): + return True if PERF_KERNEL_ALLSYMS_RE.match(mmap_info.filename): return self._LoadKernelSymbols(code_map) self.infos.append(mmap_info) |