Revision: 19045
Author: [email protected]
Date: Tue Feb 4 07:54:22 2014 UTC
Log: Version 3.24.31 (based on bleeding_edge revision r19044)
Fix short-circuiting logical and/or in HOptimizedGraphBuilder (Chromium
issue 336148).
Elements field of newly allocated JSArray could be left uninitialized in
some cases (fast literal case) (Chromium issue 340124).
Re-enable escape analysis.
Performance and stability improvements on all platforms.
http://code.google.com/p/v8/source/detail?r=19045
Added:
/trunk/test/mjsunit/regress/regress-crbug-336148.js
/trunk/test/mjsunit/regress/regress-crbug-340064.js
Modified:
/trunk/ChangeLog
/trunk/src/arm/stub-cache-arm.cc
/trunk/src/flag-definitions.h
/trunk/src/hydrogen.cc
/trunk/src/hydrogen.h
/trunk/src/ia32/stub-cache-ia32.cc
/trunk/src/ic.cc
/trunk/src/mips/builtins-mips.cc
/trunk/src/mips/code-stubs-mips.cc
/trunk/src/mips/full-codegen-mips.cc
/trunk/src/mips/lithium-codegen-mips.cc
/trunk/src/mips/stub-cache-mips.cc
/trunk/src/stub-cache.cc
/trunk/src/stub-cache.h
/trunk/src/version.cc
/trunk/src/x64/disasm-x64.cc
/trunk/src/x64/stub-cache-x64.cc
/trunk/test/cctest/test-api.cc
/trunk/test/cctest/test-disasm-ia32.cc
/trunk/test/cctest/test-disasm-x64.cc
/trunk/test/cctest/test-strings.cc
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/regress/regress-crbug-336148.js Tue Feb 4 07:54:22
2014 UTC
@@ -0,0 +1,56 @@
+// Copyright 2014 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(o) {
+ var a = 1;
+ if (true) return o.v && a;
+}
+
+f({});
+f({});
+%OptimizeFunctionOnNextCall(f);
+assertEquals(1, f({ v: 1 }));
+
+
+function f1() { return 1 && 2; };
+function f2() { return 1 || 2; };
+function f3() { return 0 && 2; };
+function f4() { return 0 || 2; };
+
+function test() {
+ assertEquals(2, f1());
+ assertEquals(1, f2());
+ assertEquals(0, f3());
+ assertEquals(2, f4());
+}
+
+test();
+test();
+[f1, f2, f3, f4].forEach(function(f) { %OptimizeFunctionOnNextCall(f); });
+test();
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/regress/regress-crbug-340064.js Tue Feb 4 07:54:22
2014 UTC
@@ -0,0 +1,38 @@
+// Copyright 2014 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(v) {
+ return v.length;
+}
+
+assertEquals(4, f("test"));
+assertEquals(4, f("test"));
+assertEquals(undefined, f(true));
+%OptimizeFunctionOnNextCall(f);
+assertEquals(undefined, f(true));
=======================================
--- /trunk/ChangeLog Mon Feb 3 07:23:16 2014 UTC
+++ /trunk/ChangeLog Tue Feb 4 07:54:22 2014 UTC
@@ -1,3 +1,16 @@
+2014-02-04: Version 3.24.31
+
+ Fix short-circuiting logical and/or in HOptimizedGraphBuilder
(Chromium
+ issue 336148).
+
+ Elements field of newly allocated JSArray could be left
uninitialized in
+ some cases (fast literal case) (Chromium issue 340124).
+
+ Re-enable escape analysis.
+
+ Performance and stability improvements on all platforms.
+
+
2014-02-03: Version 3.24.30
Performance and stability improvements on all platforms.
=======================================
--- /trunk/src/arm/stub-cache-arm.cc Sat Feb 1 08:54:43 2014 UTC
+++ /trunk/src/arm/stub-cache-arm.cc Tue Feb 4 07:54:22 2014 UTC
@@ -782,11 +782,23 @@
}
-static void GenerateFastApiCallBody(MacroAssembler* masm,
- const CallOptimization& optimization,
- int argc,
- Register holder_in,
- bool restore_context) {
+// Generate call to api function.
+static void GenerateFastApiCall(MacroAssembler* masm,
+ const CallOptimization& optimization,
+ Handle<Map> receiver_map,
+ Register receiver,
+ Register scratch_in,
+ int argc,
+ Register* values) {
+ ASSERT(!receiver.is(scratch_in));
+ __ push(receiver);
+ // Write the arguments to stack frame.
+ for (int i = 0; i < argc; i++) {
+ Register arg = values[argc-1-i];
+ ASSERT(!receiver.is(arg));
+ ASSERT(!scratch_in.is(arg));
+ __ push(arg);
+ }
ASSERT(optimization.is_simple_api_call());
// Abi for CallApiFunctionStub.
@@ -796,7 +808,21 @@
Register api_function_address = r1;
// Put holder in place.
- __ Move(holder, holder_in);
+ CallOptimization::HolderLookup holder_lookup;
+ Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType(
+ receiver_map,
+ &holder_lookup);
+ switch (holder_lookup) {
+ case CallOptimization::kHolderIsReceiver:
+ __ Move(holder, receiver);
+ break;
+ case CallOptimization::kHolderFound:
+ __ Move(holder, api_holder);
+ break;
+ case CallOptimization::kHolderNotFound:
+ UNREACHABLE();
+ break;
+ }
Isolate* isolate = masm->isolate();
Handle<JSFunction> function = optimization.constant_function();
@@ -828,34 +854,9 @@
__ mov(api_function_address, Operand(ref));
// Jump to stub.
- CallApiFunctionStub stub(restore_context, call_data_undefined, argc);
+ CallApiFunctionStub stub(true, call_data_undefined, argc);
__ TailCallStub(&stub);
}
-
-
-// Generate call to api function.
-static void GenerateFastApiCall(MacroAssembler* masm,
- const CallOptimization& optimization,
- Register receiver,
- Register scratch,
- int argc,
- Register* values) {
- ASSERT(!receiver.is(scratch));
- __ push(receiver);
- // Write the arguments to stack frame.
- for (int i = 0; i < argc; i++) {
- Register arg = values[argc-1-i];
- ASSERT(!receiver.is(arg));
- ASSERT(!scratch.is(arg));
- __ push(arg);
- }
- // Stack now matches JSFunction abi.
- GenerateFastApiCallBody(masm,
- optimization,
- argc,
- receiver,
- true);
-}
void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code>
code) {
@@ -1075,9 +1076,11 @@
void LoadStubCompiler::GenerateLoadCallback(
- const CallOptimization& call_optimization) {
+ const CallOptimization& call_optimization,
+ Handle<Map> receiver_map) {
GenerateFastApiCall(
- masm(), call_optimization, receiver(), scratch3(), 0, NULL);
+ masm(), call_optimization, receiver_map,
+ receiver(), scratch3(), 0, NULL);
}
@@ -1267,7 +1270,8 @@
Register values[] = { value() };
GenerateFastApiCall(
- masm(), call_optimization, receiver(), scratch3(), 1, values);
+ masm(), call_optimization, handle(object->map()),
+ receiver(), scratch3(), 1, values);
// Return the generated code.
return GetCode(kind(), Code::FAST, name);
=======================================
--- /trunk/src/flag-definitions.h Sat Feb 1 08:54:43 2014 UTC
+++ /trunk/src/flag-definitions.h Tue Feb 4 07:54:22 2014 UTC
@@ -249,7 +249,7 @@
DEFINE_bool(use_gvn, true, "use hydrogen global value numbering")
DEFINE_bool(use_canonicalizing, true, "use hydrogen instruction
canonicalizing")
DEFINE_bool(use_inlining, true, "use function inlining")
-DEFINE_bool(use_escape_analysis, false, "use hydrogen escape analysis")
+DEFINE_bool(use_escape_analysis, true, "use hydrogen escape analysis")
DEFINE_bool(use_allocation_folding, true, "use allocation folding")
DEFINE_int(max_inlining_levels, 5, "maximum number of inlining levels")
DEFINE_int(max_inlined_source_size, 600,
=======================================
--- /trunk/src/hydrogen.cc Mon Feb 3 14:21:46 2014 UTC
+++ /trunk/src/hydrogen.cc Tue Feb 4 07:54:22 2014 UTC
@@ -9522,11 +9522,14 @@
ASSERT(current_block() != NULL);
HValue* left_value = Top();
- if (left_value->IsConstant()) {
- HConstant* left_constant = HConstant::cast(left_value);
- if ((is_logical_and && left_constant->BooleanValue()) ||
- (!is_logical_and && !left_constant->BooleanValue())) {
- Drop(1); // left_value.
+ // Short-circuit left values that always evaluate to the same boolean
value.
+ if (expr->left()->ToBooleanIsTrue() ||
expr->left()->ToBooleanIsFalse()) {
+ // l (evals true) && r -> r
+ // l (evals true) || r -> l
+ // l (evals false) && r -> l
+ // l (evals false) || r -> r
+ if (is_logical_and == expr->left()->ToBooleanIsTrue()) {
+ Drop(1);
CHECK_ALIVE(VisitForValue(expr->right()));
}
return ast_context()->ReturnValue(Pop());
=======================================
--- /trunk/src/hydrogen.h Sat Feb 1 08:54:43 2014 UTC
+++ /trunk/src/hydrogen.h Tue Feb 4 07:54:22 2014 UTC
@@ -2291,6 +2291,10 @@
Context* context = current_info()->closure()->context();
context = context->native_context();
return handle(context->number_function()->initial_map());
+ } else if (type_->Is(HeapType::Boolean())) {
+ Context* context = current_info()->closure()->context();
+ context = context->native_context();
+ return handle(context->boolean_function()->initial_map());
} else if (type_->Is(HeapType::String())) {
Context* context = current_info()->closure()->context();
context = context->native_context();
=======================================
--- /trunk/src/ia32/stub-cache-ia32.cc Sat Feb 1 08:54:43 2014 UTC
+++ /trunk/src/ia32/stub-cache-ia32.cc Tue Feb 4 07:54:22 2014 UTC
@@ -418,11 +418,30 @@
}
-static void GenerateFastApiCallBody(MacroAssembler* masm,
- const CallOptimization& optimization,
- int argc,
- Register holder_in,
- bool restore_context) {
+// Generate call to api function.
+// This function uses push() to generate smaller, faster code than
+// the version above. It is an optimization that should will be removed
+// when api call ICs are generated in hydrogen.
+static void GenerateFastApiCall(MacroAssembler* masm,
+ const CallOptimization& optimization,
+ Handle<Map> receiver_map,
+ Register receiver,
+ Register scratch_in,
+ int argc,
+ Register* values) {
+ // Copy return value.
+ __ pop(scratch_in);
+ // receiver
+ __ push(receiver);
+ // Write the arguments to stack frame.
+ for (int i = 0; i < argc; i++) {
+ Register arg = values[argc-1-i];
+ ASSERT(!receiver.is(arg));
+ ASSERT(!scratch_in.is(arg));
+ __ push(arg);
+ }
+ __ push(scratch_in);
+ // Stack now matches JSFunction abi.
ASSERT(optimization.is_simple_api_call());
// Abi for CallApiFunctionStub.
@@ -430,11 +449,24 @@
Register call_data = ebx;
Register holder = ecx;
Register api_function_address = edx;
+ Register scratch = edi; // scratch_in is no longer valid.
// Put holder in place.
- __ Move(holder, holder_in);
-
- Register scratch = edi;
+ CallOptimization::HolderLookup holder_lookup;
+ Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType(
+ receiver_map,
+ &holder_lookup);
+ switch (holder_lookup) {
+ case CallOptimization::kHolderIsReceiver:
+ __ Move(holder, receiver);
+ break;
+ case CallOptimization::kHolderFound:
+ __ LoadHeapObject(holder, api_holder);
+ break;
+ case CallOptimization::kHolderNotFound:
+ UNREACHABLE();
+ break;
+ }
Isolate* isolate = masm->isolate();
Handle<JSFunction> function = optimization.constant_function();
@@ -461,40 +493,9 @@
__ mov(api_function_address, Immediate(function_address));
// Jump to stub.
- CallApiFunctionStub stub(restore_context, call_data_undefined, argc);
+ CallApiFunctionStub stub(true, call_data_undefined, argc);
__ TailCallStub(&stub);
}
-
-
-// Generate call to api function.
-// This function uses push() to generate smaller, faster code than
-// the version above. It is an optimization that should will be removed
-// when api call ICs are generated in hydrogen.
-static void GenerateFastApiCall(MacroAssembler* masm,
- const CallOptimization& optimization,
- Register receiver,
- Register scratch1,
- int argc,
- Register* values) {
- // Copy return value.
- __ pop(scratch1);
- // receiver
- __ push(receiver);
- // Write the arguments to stack frame.
- for (int i = 0; i < argc; i++) {
- Register arg = values[argc-1-i];
- ASSERT(!receiver.is(arg));
- ASSERT(!scratch1.is(arg));
- __ push(arg);
- }
- __ push(scratch1);
- // Stack now matches JSFunction abi.
- GenerateFastApiCallBody(masm,
- optimization,
- argc,
- receiver,
- true);
-}
void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
@@ -1065,10 +1066,11 @@
void LoadStubCompiler::GenerateLoadCallback(
- const CallOptimization& call_optimization) {
+ const CallOptimization& call_optimization,
+ Handle<Map> receiver_map) {
GenerateFastApiCall(
- masm(), call_optimization, receiver(),
- scratch1(), 0, NULL);
+ masm(), call_optimization, receiver_map,
+ receiver(), scratch1(), 0, NULL);
}
@@ -1271,8 +1273,8 @@
Register values[] = { value() };
GenerateFastApiCall(
- masm(), call_optimization, receiver(),
- scratch1(), 1, values);
+ masm(), call_optimization, handle(object->map()),
+ receiver(), scratch1(), 1, values);
// Return the generated code.
return GetCode(kind(), Code::FAST, name);
=======================================
--- /trunk/src/ic.cc Sat Feb 1 08:54:43 2014 UTC
+++ /trunk/src/ic.cc Tue Feb 4 07:54:22 2014 UTC
@@ -938,7 +938,7 @@
}
CallOptimization call_optimization(function);
if (call_optimization.is_simple_api_call() &&
- call_optimization.IsCompatibleReceiver(*object)) {
+ call_optimization.IsCompatibleReceiver(object, holder)) {
return compiler.CompileLoadCallback(
type, holder, name, call_optimization);
}
@@ -1364,7 +1364,7 @@
Handle<JSFunction> function = Handle<JSFunction>::cast(setter);
CallOptimization call_optimization(function);
if (call_optimization.is_simple_api_call() &&
- call_optimization.IsCompatibleReceiver(*receiver)) {
+ call_optimization.IsCompatibleReceiver(receiver, holder)) {
return compiler.CompileStoreCallback(
receiver, holder, name, call_optimization);
}
=======================================
--- /trunk/src/mips/builtins-mips.cc Thu Jan 16 08:22:55 2014 UTC
+++ /trunk/src/mips/builtins-mips.cc Tue Feb 4 07:54:22 2014 UTC
@@ -585,8 +585,7 @@
// Receiver for constructor call allocated.
// t4: JSObject
__ bind(&allocated);
- __ push(t4);
- __ push(t4);
+ __ Push(t4, t4);
// Reload the number of arguments from the stack.
// sp[0]: receiver
@@ -1092,9 +1091,7 @@
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ sll(a0, a0, kSmiTagSize); // Smi tagged.
- __ push(a0);
-
- __ push(a2);
+ __ Push(a0, a2);
__ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
__ mov(a2, v0);
@@ -1244,9 +1241,8 @@
// Push current limit and index.
__ bind(&okay);
- __ push(v0); // Limit.
- __ mov(a1, zero_reg); // Initial index.
- __ push(a1);
+ __ mov(a1, zero_reg);
+ __ Push(v0, a1); // Limit and initial index.
// Get the receiver.
__ lw(a0, MemOperand(fp, kRecvOffset));
=======================================
--- /trunk/src/mips/code-stubs-mips.cc Mon Feb 3 07:23:16 2014 UTC
+++ /trunk/src/mips/code-stubs-mips.cc Tue Feb 4 07:54:22 2014 UTC
@@ -483,9 +483,12 @@
FrameScope scope(masm, StackFrame::INTERNAL);
ASSERT(descriptor->register_param_count_ == 0 ||
a0.is(descriptor->register_params_[param_count - 1]));
- // Push arguments
+ // Push arguments, adjust sp.
+ __ Subu(sp, sp, Operand(param_count * kPointerSize));
for (int i = 0; i < param_count; ++i) {
- __ push(descriptor->register_params_[i]);
+ // Store argument to stack.
+ __ sw(descriptor->register_params_[i],
+ MemOperand(sp, (param_count-1-i) * kPointerSize));
}
ExternalReference miss = descriptor->miss_handler();
__ CallExternalReference(miss, descriptor->register_param_count_);
=======================================
--- /trunk/src/mips/full-codegen-mips.cc Sat Feb 1 08:54:43 2014 UTC
+++ /trunk/src/mips/full-codegen-mips.cc Tue Feb 4 07:54:22 2014 UTC
@@ -1159,10 +1159,9 @@
__ lw(a2, FieldMemOperand(a2,
DescriptorArray::kEnumCacheBridgeCacheOffset));
// Set up the four remaining stack slots.
- __ push(v0); // Map.
__ li(a0, Operand(Smi::FromInt(0)));
- // Push enumeration cache, enumeration cache length (as smi) and zero.
- __ Push(a2, a1, a0);
+ // Push map, enumeration cache, enumeration cache length (as smi) and
zero.
+ __ Push(v0, a2, a1, a0);
__ jmp(&loop);
__ bind(&no_descriptors);
@@ -1227,8 +1226,7 @@
// Convert the entry to a string or (smi) 0 if it isn't a property
// any more. If the property has been removed while iterating, we
// just skip it.
- __ push(a1); // Enumerable.
- __ push(a3); // Current entry.
+ __ Push(a1, a3); // Enumerable and current entry.
__ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
__ mov(a3, result_register());
__ Branch(loop_statement.continue_label(), eq, a3, Operand(zero_reg));
@@ -2506,19 +2504,17 @@
// able to drill a hole to that function context, even from inside a
// 'with' context. We thus bypass the normal static scope lookup for
// var->IsContextSlot().
- __ push(v0);
__ li(a0, Operand(var->name()));
- __ Push(cp, a0); // Context and name.
+ __ Push(v0, cp, a0); // Context and name.
__ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
}
} else if (var->mode() == LET && op != Token::INIT_LET) {
// Non-initializing assignment to let variable needs a write barrier.
if (var->IsLookupSlot()) {
- __ push(v0); // Value.
__ li(a1, Operand(var->name()));
__ li(a0, Operand(Smi::FromInt(language_mode())));
- __ Push(cp, a1, a0); // Context, name, strict mode.
+ __ Push(v0, cp, a1, a0); // Value, context, name, strict mode.
__ CallRuntime(Runtime::kStoreContextSlot, 4);
} else {
ASSERT(var->IsStackAllocated() || var->IsContextSlot());
@@ -2563,10 +2559,9 @@
}
} else {
ASSERT(var->IsLookupSlot());
- __ push(v0); // Value.
__ li(a1, Operand(var->name()));
__ li(a0, Operand(Smi::FromInt(language_mode())));
- __ Push(cp, a1, a0); // Context, name, strict mode.
+ __ Push(v0, cp, a1, a0); // Value, context, name, strict mode.
__ CallRuntime(Runtime::kStoreContextSlot, 4);
}
}
=======================================
--- /trunk/src/mips/lithium-codegen-mips.cc Sat Feb 1 08:54:43 2014 UTC
+++ /trunk/src/mips/lithium-codegen-mips.cc Tue Feb 4 07:54:22 2014 UTC
@@ -179,8 +179,7 @@
if (slots > 0) {
if (FLAG_debug_code) {
__ Subu(sp, sp, Operand(slots * kPointerSize));
- __ push(a0);
- __ push(a1);
+ __ Push(a0, a1);
__ Addu(a0, sp, Operand(slots * kPointerSize));
__ li(a1, Operand(kSlotsZapValue));
Label loop;
@@ -188,8 +187,7 @@
__ Subu(a0, a0, Operand(kPointerSize));
__ sw(a1, MemOperand(a0, 2 * kPointerSize));
__ Branch(&loop, ne, a0, Operand(sp));
- __ pop(a1);
- __ pop(a0);
+ __ Pop(a0, a1);
} else {
__ Subu(sp, sp, Operand(slots * kPointerSize));
}
=======================================
--- /trunk/src/mips/stub-cache-mips.cc Sat Feb 1 08:54:43 2014 UTC
+++ /trunk/src/mips/stub-cache-mips.cc Tue Feb 4 07:54:22 2014 UTC
@@ -769,11 +769,25 @@
}
-static void GenerateFastApiCallBody(MacroAssembler* masm,
- const CallOptimization& optimization,
- int argc,
- Register holder_in,
- bool restore_context) {
+// Generate call to api function.
+static void GenerateFastApiCall(MacroAssembler* masm,
+ const CallOptimization& optimization,
+ Handle<Map> receiver_map,
+ Register receiver,
+ Register scratch_in,
+ int argc,
+ Register* values) {
+ ASSERT(!receiver.is(scratch_in));
+ // Preparing to push, adjust sp.
+ __ Subu(sp, sp, Operand((argc + 1) * kPointerSize));
+ __ sw(receiver, MemOperand(sp, argc * kPointerSize)); // Push receiver.
+ // Write the arguments to stack frame.
+ for (int i = 0; i < argc; i++) {
+ Register arg = values[argc-1-i];
+ ASSERT(!receiver.is(arg));
+ ASSERT(!scratch_in.is(arg));
+ __ sw(arg, MemOperand(sp, (argc-1-i) * kPointerSize)); // Push arg.
+ }
ASSERT(optimization.is_simple_api_call());
// Abi for CallApiFunctionStub.
@@ -783,7 +797,21 @@
Register api_function_address = a1;
// Put holder in place.
- __ mov(holder, holder_in);
+ CallOptimization::HolderLookup holder_lookup;
+ Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType(
+ receiver_map,
+ &holder_lookup);
+ switch (holder_lookup) {
+ case CallOptimization::kHolderIsReceiver:
+ __ Move(holder, receiver);
+ break;
+ case CallOptimization::kHolderFound:
+ __ li(holder, api_holder);
+ break;
+ case CallOptimization::kHolderNotFound:
+ UNREACHABLE();
+ break;
+ }
Isolate* isolate = masm->isolate();
Handle<JSFunction> function = optimization.constant_function();
@@ -815,35 +843,9 @@
__ li(api_function_address, Operand(ref));
// Jump to stub.
- CallApiFunctionStub stub(restore_context, call_data_undefined, argc);
+ CallApiFunctionStub stub(true, call_data_undefined, argc);
__ TailCallStub(&stub);
}
-
-
-// Generate call to api function.
-static void GenerateFastApiCall(MacroAssembler* masm,
- const CallOptimization& optimization,
- Register receiver,
- Register scratch,
- int argc,
- Register* values) {
- ASSERT(!receiver.is(scratch));
- __ push(receiver);
- // Write the arguments to stack frame.
- for (int i = 0; i < argc; i++) {
- Register arg = values[argc-1-i];
- ASSERT(!receiver.is(arg));
- ASSERT(!scratch.is(arg));
- __ push(arg);
- }
-
- // Stack now matches JSFunction abi.
- GenerateFastApiCallBody(masm,
- optimization,
- argc,
- receiver,
- true);
-}
void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code>
code) {
@@ -1062,9 +1064,11 @@
void LoadStubCompiler::GenerateLoadCallback(
- const CallOptimization& call_optimization) {
+ const CallOptimization& call_optimization,
+ Handle<Map> receiver_map) {
GenerateFastApiCall(
- masm(), call_optimization, receiver(), scratch3(), 0, NULL);
+ masm(), call_optimization, receiver_map,
+ receiver(), scratch3(), 0, NULL);
}
@@ -1226,8 +1230,7 @@
// checks.
ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
- __ push(receiver()); // Receiver.
- __ push(holder_reg);
+ __ Push(receiver(), holder_reg); // Receiver.
__ li(at, Operand(callback)); // Callback info.
__ push(at);
__ li(at, Operand(name));
@@ -1253,7 +1256,8 @@
Register values[] = { value() };
GenerateFastApiCall(
- masm(), call_optimization, receiver(), scratch3(), 1, values);
+ masm(), call_optimization, handle(object->map()),
+ receiver(), scratch3(), 1, values);
// Return the generated code.
return GetCode(kind(), Code::FAST, name);
@@ -1281,8 +1285,7 @@
if (!setter.is_null()) {
// Call the JavaScript setter with receiver and value on the stack.
- __ push(a1);
- __ push(a0);
+ __ Push(a1, a0);
ParameterCount actual(1);
ParameterCount expected(setter);
__ InvokeFunction(setter, expected, actual,
=======================================
--- /trunk/src/stub-cache.cc Sat Feb 1 08:54:43 2014 UTC
+++ /trunk/src/stub-cache.cc Tue Feb 4 07:54:22 2014 UTC
@@ -951,7 +951,7 @@
ASSERT(call_optimization.is_simple_api_call());
Handle<JSFunction> callback = call_optimization.constant_function();
CallbackHandlerFrontend(type, receiver(), holder, name, callback);
- GenerateLoadCallback(call_optimization);
+ GenerateLoadCallback(call_optimization, IC::TypeToMap(*type, isolate()));
// Return the generated code.
return GetCode(kind(), Code::FAST, name);
@@ -1357,7 +1357,6 @@
Handle<Map> object_map,
HolderLookup* holder_lookup) const {
ASSERT(is_simple_api_call());
- ASSERT_EQ(kHolderNotFound, *holder_lookup);
if (!object_map->IsJSObjectMap()) {
*holder_lookup = kHolderNotFound;
return Handle<JSObject>::null();
@@ -1380,6 +1379,38 @@
*holder_lookup = kHolderNotFound;
return Handle<JSObject>::null();
}
+
+
+bool CallOptimization::IsCompatibleReceiver(Handle<Object> receiver,
+ Handle<JSObject> holder) const
{
+ ASSERT(is_simple_api_call());
+ if (!receiver->IsJSObject()) return false;
+ Handle<Map> map(JSObject::cast(*receiver)->map());
+ HolderLookup holder_lookup;
+ Handle<JSObject> api_holder =
+ LookupHolderOfExpectedType(map, &holder_lookup);
+ switch (holder_lookup) {
+ case kHolderNotFound:
+ return false;
+ case kHolderIsReceiver:
+ return true;
+ case kHolderFound:
+ if (api_holder.is_identical_to(holder)) return true;
+ // Check if holder is in prototype chain of api_holder.
+ {
+ JSObject* object = *api_holder;
+ while (true) {
+ Object* prototype = object->map()->prototype();
+ if (!prototype->IsJSObject()) return false;
+ if (prototype == *holder) return true;
+ object = JSObject::cast(prototype);
+ }
+ }
+ break;
+ }
+ UNREACHABLE();
+ return false;
+}
void CallOptimization::Initialize(Handle<JSFunction> function) {
=======================================
--- /trunk/src/stub-cache.h Sat Feb 1 08:54:43 2014 UTC
+++ /trunk/src/stub-cache.h Tue Feb 4 07:54:22 2014 UTC
@@ -611,7 +611,8 @@
void GenerateLoadConstant(Handle<Object> value);
void GenerateLoadCallback(Register reg,
Handle<ExecutableAccessorInfo> callback);
- void GenerateLoadCallback(const CallOptimization& call_optimization);
+ void GenerateLoadCallback(const CallOptimization& call_optimization,
+ Handle<Map> receiver_map);
void GenerateLoadInterceptor(Register holder_reg,
Handle<Object> object,
Handle<JSObject> holder,
@@ -827,11 +828,9 @@
Handle<Map> receiver_map,
HolderLookup* holder_lookup) const;
- bool IsCompatibleReceiver(Object* receiver) {
- ASSERT(is_simple_api_call());
- if (expected_receiver_type_.is_null()) return true;
- return expected_receiver_type_->IsTemplateFor(receiver);
- }
+ // Check if the api holder is between the receiver and the holder.
+ bool IsCompatibleReceiver(Handle<Object> receiver,
+ Handle<JSObject> holder) const;
private:
void Initialize(Handle<JSFunction> function);
=======================================
--- /trunk/src/version.cc Mon Feb 3 14:21:46 2014 UTC
+++ /trunk/src/version.cc Tue Feb 4 07:54:22 2014 UTC
@@ -34,8 +34,8 @@
// system so their names cannot be changed without changing the scripts.
#define MAJOR_VERSION 3
#define MINOR_VERSION 24
-#define BUILD_NUMBER 30
-#define PATCH_LEVEL 1
+#define BUILD_NUMBER 31
+#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
#define IS_CANDIDATE_VERSION 0
=======================================
--- /trunk/src/x64/disasm-x64.cc Tue Nov 19 11:05:18 2013 UTC
+++ /trunk/src/x64/disasm-x64.cc Tue Feb 4 07:54:22 2014 UTC
@@ -934,6 +934,7 @@
case 0xF5: mnem = "fprem1"; break;
case 0xF7: mnem = "fincstp"; break;
case 0xF8: mnem = "fprem"; break;
+ case 0xFC: mnem = "frndint"; break;
case 0xFD: mnem = "fscale"; break;
case 0xFE: mnem = "fsin"; break;
case 0xFF: mnem = "fcos"; break;
@@ -956,6 +957,8 @@
has_register = true;
} else if (modrm_byte == 0xE2) {
mnem = "fclex";
+ } else if (modrm_byte == 0xE3) {
+ mnem = "fninit";
} else {
UnimplementedInstruction();
}
=======================================
--- /trunk/src/x64/stub-cache-x64.cc Sat Feb 1 08:54:43 2014 UTC
+++ /trunk/src/x64/stub-cache-x64.cc Tue Feb 4 07:54:22 2014 UTC
@@ -392,23 +392,52 @@
}
-static void GenerateFastApiCallBody(MacroAssembler* masm,
- const CallOptimization& optimization,
- int argc,
- Register holder_in,
- bool restore_context) {
+// Generate call to api function.
+static void GenerateFastApiCall(MacroAssembler* masm,
+ const CallOptimization& optimization,
+ Handle<Map> receiver_map,
+ Register receiver,
+ Register scratch_in,
+ int argc,
+ Register* values) {
ASSERT(optimization.is_simple_api_call());
+ __ PopReturnAddressTo(scratch_in);
+ // receiver
+ __ push(receiver);
+ // Write the arguments to stack frame.
+ for (int i = 0; i < argc; i++) {
+ Register arg = values[argc-1-i];
+ ASSERT(!receiver.is(arg));
+ ASSERT(!scratch_in.is(arg));
+ __ push(arg);
+ }
+ __ PushReturnAddressFrom(scratch_in);
+ // Stack now matches JSFunction abi.
+
// Abi for CallApiFunctionStub.
Register callee = rax;
Register call_data = rbx;
Register holder = rcx;
Register api_function_address = rdx;
+ Register scratch = rdi; // scratch_in is no longer valid.
// Put holder in place.
- __ Move(holder, holder_in);
-
- Register scratch = rdi;
+ CallOptimization::HolderLookup holder_lookup;
+ Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType(
+ receiver_map,
+ &holder_lookup);
+ switch (holder_lookup) {
+ case CallOptimization::kHolderIsReceiver:
+ __ Move(holder, receiver);
+ break;
+ case CallOptimization::kHolderFound:
+ __ Move(holder, api_holder);
+ break;
+ case CallOptimization::kHolderNotFound:
+ UNREACHABLE();
+ break;
+ }
Isolate* isolate = masm->isolate();
Handle<JSFunction> function = optimization.constant_function();
@@ -436,36 +465,9 @@
api_function_address, function_address,
RelocInfo::EXTERNAL_REFERENCE);
// Jump to stub.
- CallApiFunctionStub stub(restore_context, call_data_undefined, argc);
+ CallApiFunctionStub stub(true, call_data_undefined, argc);
__ TailCallStub(&stub);
}
-
-
-// Generate call to api function.
-static void GenerateFastApiCall(MacroAssembler* masm,
- const CallOptimization& optimization,
- Register receiver,
- Register scratch1,
- int argc,
- Register* values) {
- __ PopReturnAddressTo(scratch1);
- // receiver
- __ push(receiver);
- // Write the arguments to stack frame.
- for (int i = 0; i < argc; i++) {
- Register arg = values[argc-1-i];
- ASSERT(!receiver.is(arg));
- ASSERT(!scratch1.is(arg));
- __ push(arg);
- }
- __ PushReturnAddressFrom(scratch1);
- // Stack now matches JSFunction abi.
- GenerateFastApiCallBody(masm,
- optimization,
- argc,
- receiver,
- true);
-}
void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
@@ -968,10 +970,11 @@
void LoadStubCompiler::GenerateLoadCallback(
- const CallOptimization& call_optimization) {
+ const CallOptimization& call_optimization,
+ Handle<Map> receiver_map) {
GenerateFastApiCall(
- masm(), call_optimization, receiver(),
- scratch1(), 0, NULL);
+ masm(), call_optimization, receiver_map,
+ receiver(), scratch1(), 0, NULL);
}
@@ -1165,8 +1168,8 @@
Register values[] = { value() };
GenerateFastApiCall(
- masm(), call_optimization, receiver(),
- scratch1(), 1, values);
+ masm(), call_optimization, handle(object->map()),
+ receiver(), scratch1(), 1, values);
// Return the generated code.
return GetCode(kind(), Code::FAST, name);
=======================================
--- /trunk/test/cctest/test-api.cc Sat Feb 1 08:54:43 2014 UTC
+++ /trunk/test/cctest/test-api.cc Tue Feb 4 07:54:22 2014 UTC
@@ -15298,7 +15298,6 @@
timeout_thread.Join();
- delete regexp_interruption_data.string_resource;
regexp_interruption_data.string.Reset();
}
=======================================
--- /trunk/test/cctest/test-disasm-ia32.cc Wed Jan 8 10:55:36 2014 UTC
+++ /trunk/test/cctest/test-disasm-ia32.cc Tue Feb 4 07:54:22 2014 UTC
@@ -349,6 +349,8 @@
__ fdivp(3);
__ fcompp();
__ fwait();
+ __ frndint();
+ __ fninit();
__ nop();
// SSE instruction
=======================================
--- /trunk/test/cctest/test-disasm-x64.cc Tue Nov 19 11:05:18 2013 UTC
+++ /trunk/test/cctest/test-disasm-x64.cc Tue Feb 4 07:54:22 2014 UTC
@@ -330,6 +330,8 @@
__ fdivp(3);
__ fcompp();
__ fwait();
+ __ frndint();
+ __ fninit();
__ nop();
// SSE instruction
=======================================
--- /trunk/test/cctest/test-strings.cc Fri Jan 3 15:51:11 2014 UTC
+++ /trunk/test/cctest/test-strings.cc Tue Feb 4 07:54:22 2014 UTC
@@ -38,7 +38,6 @@
#include "factory.h"
#include "objects.h"
#include "cctest.h"
-#include "zone-inl.h"
// Adapted from http://en.wikipedia.org/wiki/Multiply-with-carry
class MyRandomNumberGenerator {
@@ -100,12 +99,10 @@
static const int SUPER_DEEP_DEPTH = 80 * 1024;
-class Resource: public v8::String::ExternalStringResource,
- public ZoneObject {
+class Resource: public v8::String::ExternalStringResource {
public:
- explicit Resource(Vector<const uc16> string): data_(string.start()) {
- length_ = string.length();
- }
+ Resource(const uc16* data, size_t length): data_(data), length_(length)
{}
+ ~Resource() { i::DeleteArray(data_); }
virtual const uint16_t* data() const { return data_; }
virtual size_t length() const { return length_; }
@@ -115,12 +112,11 @@
};
-class AsciiResource: public v8::String::ExternalAsciiStringResource,
- public ZoneObject {
+class AsciiResource: public v8::String::ExternalAsciiStringResource {
public:
- explicit AsciiResource(Vector<const char> string): data_(string.start())
{
- length_ = string.length();
- }
+ AsciiResource(const char* data, size_t length)
+ : data_(data), length_(length) {}
+ ~AsciiResource() { i::DeleteArray(data_); }
virtual const char* data() const { return data_; }
virtual size_t length() const { return length_; }
@@ -133,8 +129,7 @@
static void InitializeBuildingBlocks(Handle<String>* building_blocks,
int bb_length,
bool long_blocks,
- MyRandomNumberGenerator* rng,
- Zone* zone) {
+ MyRandomNumberGenerator* rng) {
// A list of pointers that we don't have any interest in cleaning up.
// If they are reachable from a root then leak detection won't complain.
Isolate* isolate = CcTest::i_isolate();
@@ -189,25 +184,28 @@
break;
}
case 2: {
- uc16* buf = zone->NewArray<uc16>(len);
+ uc16* buf = NewArray<uc16>(len);
for (int j = 0; j < len; j++) {
buf[j] = rng->next(0x10000);
}
- Resource* resource = new(zone) Resource(Vector<const uc16>(buf,
len));
- building_blocks[i] =
factory->NewExternalStringFromTwoByte(resource);
+ Resource* resource = new Resource(buf, len);
+ building_blocks[i] =
+ v8::Utils::OpenHandle(
+ *v8::String::NewExternal(CcTest::isolate(), resource));
for (int j = 0; j < len; j++) {
CHECK_EQ(buf[j], building_blocks[i]->Get(j));
}
break;
}
case 3: {
- char* buf = zone->NewArray<char>(len);
+ char* buf = NewArray<char>(len);
for (int j = 0; j < len; j++) {
buf[j] = rng->next(0x80);
}
- AsciiResource* resource =
- new(zone) AsciiResource(Vector<const char>(buf, len));
- building_blocks[i] = factory->NewExternalStringFromAscii(resource);
+ AsciiResource* resource = new AsciiResource(buf, len);
+ building_blocks[i] =
+ v8::Utils::OpenHandle(
+ *v8::String::NewExternal(CcTest::isolate(), resource));
for (int j = 0; j < len; j++) {
CHECK_EQ(buf[j], building_blocks[i]->Get(j));
}
@@ -263,7 +261,7 @@
class ConsStringGenerationData {
public:
static const int kNumberOfBuildingBlocks = 256;
- ConsStringGenerationData(bool long_blocks, Zone* zone);
+ explicit ConsStringGenerationData(bool long_blocks);
void Reset();
inline Handle<String> block(int offset);
inline Handle<String> block(uint32_t offset);
@@ -285,11 +283,10 @@
};
-ConsStringGenerationData::ConsStringGenerationData(bool long_blocks,
- Zone* zone) {
+ConsStringGenerationData::ConsStringGenerationData(bool long_blocks) {
rng_.init();
InitializeBuildingBlocks(
- building_blocks_, kNumberOfBuildingBlocks, long_blocks, &rng_, zone);
+ building_blocks_, kNumberOfBuildingBlocks, long_blocks, &rng_);
empty_string_ = CcTest::heap()->empty_string();
Reset();
}
@@ -571,8 +568,7 @@
printf("TestTraverse\n");
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
- Zone zone(CcTest::i_isolate());
- ConsStringGenerationData data(false, &zone);
+ ConsStringGenerationData data(false);
Handle<String> flat = ConstructBalanced(&data);
FlattenString(flat);
Handle<String> left_asymmetric = ConstructLeft(&data, DEEP_DEPTH);
@@ -661,8 +657,7 @@
CcTest::InitializeVM();
Isolate* isolate = CcTest::i_isolate();
HandleScope outer_scope(isolate);
- Zone zone(isolate);
- ConsStringGenerationData data(true, &zone);
+ ConsStringGenerationData data(true);
for (int i = 0; i < test_cases; i++) {
printf("%d\n", i);
HandleScope inner_scope(isolate);
@@ -931,9 +926,6 @@
TEST(ExternalShortStringAdd) {
- Isolate* isolate = CcTest::i_isolate();
- Zone zone(isolate);
-
LocalContext context;
v8::HandleScope handle_scope(CcTest::isolate());
@@ -949,26 +941,25 @@
// Generate short ascii and non-ascii external strings.
for (int i = 0; i <= kMaxLength; i++) {
- char* ascii = zone.NewArray<char>(i + 1);
+ char* ascii = NewArray<char>(i + 1);
for (int j = 0; j < i; j++) {
ascii[j] = 'a';
}
// Terminating '\0' is left out on purpose. It is not required for
external
// string data.
- AsciiResource* ascii_resource =
- new(&zone) AsciiResource(Vector<const char>(ascii, i));
+ AsciiResource* ascii_resource = new AsciiResource(ascii, i);
v8::Local<v8::String> ascii_external_string =
v8::String::NewExternal(CcTest::isolate(), ascii_resource);
ascii_external_strings->Set(v8::Integer::New(CcTest::isolate(), i),
ascii_external_string);
- uc16* non_ascii = zone.NewArray<uc16>(i + 1);
+ uc16* non_ascii = NewArray<uc16>(i + 1);
for (int j = 0; j < i; j++) {
non_ascii[j] = 0x1234;
}
// Terminating '\0' is left out on purpose. It is not required for
external
// string data.
- Resource* resource = new(&zone) Resource(Vector<const uc16>(non_ascii,
i));
+ Resource* resource = new Resource(non_ascii, i);
v8::Local<v8::String> non_ascii_external_string =
v8::String::NewExternal(CcTest::isolate(), resource);
non_ascii_external_strings->Set(v8::Integer::New(CcTest::isolate(), i),
@@ -1022,8 +1013,6 @@
TEST(JSONStringifySliceMadeExternal) {
CcTest::InitializeVM();
- Isolate* isolate = CcTest::i_isolate();
- Zone zone(isolate);
// Create a sliced string from a one-byte string. The latter is turned
// into a two-byte external string. Check that JSON.stringify works.
v8::HandleScope handle_scope(CcTest::isolate());
@@ -1037,10 +1026,9 @@
CHECK(v8::Utils::OpenHandle(*underlying)->IsSeqOneByteString());
int length = underlying->Length();
- uc16* two_byte = zone.NewArray<uc16>(length + 1);
+ uc16* two_byte = NewArray<uc16>(length + 1);
underlying->Write(two_byte);
- Resource* resource =
- new(&zone) Resource(Vector<const uc16>(two_byte, length));
+ Resource* resource = new Resource(two_byte, length);
CHECK(underlying->MakeExternal(resource));
CHECK(v8::Utils::OpenHandle(*slice)->IsSlicedString());
CHECK(v8::Utils::OpenHandle(*underlying)->IsExternalTwoByteString());
@@ -1056,7 +1044,6 @@
// values didn't fit in the hash field.
// See http://code.google.com/p/v8/issues/detail?id=728
Isolate* isolate = CcTest::i_isolate();
- Zone zone(isolate);
v8::HandleScope handle_scope(CcTest::isolate());
// Lines must be executed sequentially. Combining them into one script
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.