Browse Source

Update v8 to 3.8.9

v0.7.4-release
isaacs 13 years ago
parent
commit
05471f5c2a
  1. 18
      deps/v8/ChangeLog
  2. 2
      deps/v8/build/common.gypi
  3. 14
      deps/v8/include/v8.h
  4. 3
      deps/v8/include/v8stdint.h
  5. 23
      deps/v8/src/accessors.cc
  6. 3
      deps/v8/src/accessors.h
  7. 9
      deps/v8/src/allocation.cc
  8. 3
      deps/v8/src/allocation.h
  9. 24
      deps/v8/src/api.cc
  10. 10
      deps/v8/src/api.h
  11. 1
      deps/v8/src/arm/assembler-arm-inl.h
  12. 12
      deps/v8/src/arm/assembler-arm.h
  13. 1
      deps/v8/src/arm/builtins-arm.cc
  14. 125
      deps/v8/src/arm/deoptimizer-arm.cc
  15. 34
      deps/v8/src/arm/disasm-arm.cc
  16. 7
      deps/v8/src/arm/frames-arm.h
  17. 59
      deps/v8/src/arm/ic-arm.cc
  18. 24
      deps/v8/src/arm/lithium-arm.cc
  19. 12
      deps/v8/src/arm/lithium-codegen-arm.cc
  20. 41
      deps/v8/src/assembler.cc
  21. 10
      deps/v8/src/assembler.h
  22. 11
      deps/v8/src/ast.cc
  23. 41
      deps/v8/src/ast.h
  24. 7
      deps/v8/src/cpu-profiler.cc
  25. 29
      deps/v8/src/d8.cc
  26. 22
      deps/v8/src/d8.h
  27. 283
      deps/v8/src/debug.cc
  28. 313
      deps/v8/src/deoptimizer.cc
  29. 68
      deps/v8/src/deoptimizer.h
  30. 25
      deps/v8/src/frames.cc
  31. 14
      deps/v8/src/full-codegen.cc
  32. 1
      deps/v8/src/heap-inl.h
  33. 118
      deps/v8/src/heap.cc
  34. 42
      deps/v8/src/heap.h
  35. 17
      deps/v8/src/hydrogen-instructions.cc
  36. 7
      deps/v8/src/hydrogen-instructions.h
  37. 76
      deps/v8/src/hydrogen.cc
  38. 17
      deps/v8/src/hydrogen.h
  39. 4
      deps/v8/src/ia32/assembler-ia32-inl.h
  40. 3
      deps/v8/src/ia32/builtins-ia32.cc
  41. 126
      deps/v8/src/ia32/deoptimizer-ia32.cc
  42. 8
      deps/v8/src/ia32/frames-ia32.h
  43. 59
      deps/v8/src/ia32/ic-ia32.cc
  44. 12
      deps/v8/src/ia32/lithium-codegen-ia32.cc
  45. 24
      deps/v8/src/ia32/lithium-ia32.cc
  46. 8
      deps/v8/src/jsregexp.h
  47. 12
      deps/v8/src/lithium-allocator.cc
  48. 4
      deps/v8/src/lithium.cc
  49. 21
      deps/v8/src/lithium.h
  50. 13
      deps/v8/src/mark-compact-inl.h
  51. 213
      deps/v8/src/mark-compact.cc
  52. 6
      deps/v8/src/mark-compact.h
  53. 1
      deps/v8/src/mips/assembler-mips-inl.h
  54. 55
      deps/v8/src/mips/ic-mips.cc
  55. 3
      deps/v8/src/objects-inl.h
  56. 55
      deps/v8/src/objects.cc
  57. 11
      deps/v8/src/objects.h
  58. 15
      deps/v8/src/platform-freebsd.cc
  59. 15
      deps/v8/src/platform-linux.cc
  60. 17
      deps/v8/src/platform-macos.cc
  61. 15
      deps/v8/src/platform-openbsd.cc
  62. 54
      deps/v8/src/platform-solaris.cc
  63. 15
      deps/v8/src/platform-win32.cc
  64. 16
      deps/v8/src/platform.h
  65. 124
      deps/v8/src/runtime.cc
  66. 32
      deps/v8/src/serialize.cc
  67. 7
      deps/v8/src/serialize.h
  68. 22
      deps/v8/src/spaces.cc
  69. 2
      deps/v8/src/spaces.h
  70. 3
      deps/v8/src/type-info.h
  71. 19
      deps/v8/src/v8globals.h
  72. 2
      deps/v8/src/version.cc
  73. 4
      deps/v8/src/x64/assembler-x64-inl.h
  74. 1
      deps/v8/src/x64/builtins-x64.cc
  75. 131
      deps/v8/src/x64/deoptimizer-x64.cc
  76. 7
      deps/v8/src/x64/frames-x64.h
  77. 63
      deps/v8/src/x64/ic-x64.cc
  78. 12
      deps/v8/src/x64/lithium-codegen-x64.cc
  79. 24
      deps/v8/src/x64/lithium-x64.cc
  80. 123
      deps/v8/test/cctest/test-api.cc
  81. 5
      deps/v8/test/cctest/test-compiler.cc
  82. 30
      deps/v8/test/cctest/test-debug.cc
  83. 4
      deps/v8/test/cctest/test-deoptimization.cc
  84. 15
      deps/v8/test/cctest/test-mark-compact.cc
  85. 4
      deps/v8/test/cctest/test-parsing.cc
  86. 20
      deps/v8/test/mjsunit/compiler/regress-funarguments.js
  87. 174
      deps/v8/test/mjsunit/debug-evaluate-locals-optimized-double.js
  88. 160
      deps/v8/test/mjsunit/debug-evaluate-locals-optimized.js
  89. 103
      deps/v8/test/mjsunit/regress/regress-1229.js
  90. 5
      deps/v8/tools/js2c.py
  91. 4
      deps/v8/tools/test.py

18
deps/v8/ChangeLog

@ -1,3 +1,21 @@
2012-01-26: Version 3.8.9
Flush number string cache on GC (issue 1605).
Provide access to function inferred name with
v8::Function::GetInferredName in V8 public API.
Fix building with Clang (issue 1912).
Reduce the space used by the stack for the profiling thread.
Fix misleading documentation of v8::Locker (issue 542).
Introduce readbinary function in d8 to read binary files.
Performance and stability improvements on all platforms.
2012-01-23: Version 3.8.8 2012-01-23: Version 3.8.8
Limited number of loop iterations in Heap::ReserveSpace Limited number of loop iterations in Heap::ReserveSpace

2
deps/v8/build/common.gypi

@ -295,7 +295,7 @@
'-O3', '-O3',
], ],
'conditions': [ 'conditions': [
[ 'gcc_version==44', { [ 'gcc_version==44 and clang==0', {
'cflags': [ 'cflags': [
# Avoid crashes with gcc 4.4 in the v8 test suite. # Avoid crashes with gcc 4.4 in the v8 test suite.
'-fno-tree-vrp', '-fno-tree-vrp',

14
deps/v8/include/v8.h

@ -1731,6 +1731,14 @@ class Function : public Object {
V8EXPORT void SetName(Handle<String> name); V8EXPORT void SetName(Handle<String> name);
V8EXPORT Handle<Value> GetName() const; V8EXPORT Handle<Value> GetName() const;
/**
* Name inferred from variable or property assignment of this function.
* Used to facilitate debugging and profiling of JavaScript code written
* in an OO style, where many functions are anonymous but are assigned
* to object properties.
*/
V8EXPORT Handle<Value> GetInferredName() const;
/** /**
* Returns zero based line number of function body and * Returns zero based line number of function body and
* kLineOffsetNotFound if no information available. * kLineOffsetNotFound if no information available.
@ -2717,7 +2725,7 @@ class RetainedObjectInfo;
* default isolate is implicitly created and entered. The embedder * default isolate is implicitly created and entered. The embedder
* can create additional isolates and use them in parallel in multiple * can create additional isolates and use them in parallel in multiple
* threads. An isolate can be entered by at most one thread at any * threads. An isolate can be entered by at most one thread at any
* given time. The Locker/Unlocker API can be used to synchronize. * given time. The Locker/Unlocker API must be used to synchronize.
*/ */
class V8EXPORT Isolate { class V8EXPORT Isolate {
public: public:
@ -3559,7 +3567,9 @@ class V8EXPORT Context {
* accessing handles or holding onto object pointers obtained * accessing handles or holding onto object pointers obtained
* from V8 handles while in the particular V8 isolate. It is up * from V8 handles while in the particular V8 isolate. It is up
* to the user of V8 to ensure (perhaps with locking) that this * to the user of V8 to ensure (perhaps with locking) that this
* constraint is not violated. * constraint is not violated. In addition to any other synchronization
* mechanism that may be used, the v8::Locker and v8::Unlocker classes
* must be used to signal thead switches to V8.
* *
* v8::Locker is a scoped lock object. While it's * v8::Locker is a scoped lock object. While it's
* active (i.e. between its construction and destruction) the current thread is * active (i.e. between its construction and destruction) the current thread is

3
deps/v8/include/v8stdint.h

@ -1,4 +1,4 @@
// 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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -30,6 +30,7 @@
#ifndef V8STDINT_H_ #ifndef V8STDINT_H_
#define V8STDINT_H_ #define V8STDINT_H_
#include <stddef.h>
#include <stdio.h> #include <stdio.h>
#if defined(_WIN32) && !defined(__MINGW32__) #if defined(_WIN32) && !defined(__MINGW32__)

23
deps/v8/src/accessors.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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -26,15 +26,16 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "v8.h" #include "v8.h"
#include "accessors.h" #include "accessors.h"
#include "ast.h"
#include "contexts.h"
#include "deoptimizer.h" #include "deoptimizer.h"
#include "execution.h" #include "execution.h"
#include "factory.h" #include "factory.h"
#include "frames-inl.h"
#include "isolate.h"
#include "list-inl.h" #include "list-inl.h"
#include "safepoint-table.h" #include "property-details.h"
#include "scopeinfo.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
@ -574,11 +575,12 @@ static MaybeObject* ConstructArgumentsObjectForInlinedFunction(
Handle<JSFunction> inlined_function, Handle<JSFunction> inlined_function,
int inlined_frame_index) { int inlined_frame_index) {
Factory* factory = Isolate::Current()->factory(); Factory* factory = Isolate::Current()->factory();
int args_count = inlined_function->shared()->formal_parameter_count(); Vector<SlotRef> args_slots =
ScopedVector<SlotRef> args_slots(args_count); SlotRef::ComputeSlotMappingForArguments(
SlotRef::ComputeSlotMappingForArguments(frame, frame,
inlined_frame_index, inlined_frame_index,
&args_slots); inlined_function->shared()->formal_parameter_count());
int args_count = args_slots.length();
Handle<JSObject> arguments = Handle<JSObject> arguments =
factory->NewArgumentsObject(inlined_function, args_count); factory->NewArgumentsObject(inlined_function, args_count);
Handle<FixedArray> array = factory->NewFixedArray(args_count); Handle<FixedArray> array = factory->NewFixedArray(args_count);
@ -587,6 +589,7 @@ static MaybeObject* ConstructArgumentsObjectForInlinedFunction(
array->set(i, *value); array->set(i, *value);
} }
arguments->set_elements(*array); arguments->set_elements(*array);
args_slots.Dispose();
// Return the freshly allocated arguments object. // Return the freshly allocated arguments object.
return *arguments; return *arguments;

3
deps/v8/src/accessors.h

@ -1,4 +1,4 @@
// Copyright 2006-2008 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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -29,6 +29,7 @@
#define V8_ACCESSORS_H_ #define V8_ACCESSORS_H_
#include "allocation.h" #include "allocation.h"
#include "v8globals.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

9
deps/v8/src/allocation.cc

@ -1,4 +1,4 @@
// Copyright 2008 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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -25,10 +25,11 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../include/v8stdint.h"
#include "globals.h"
#include "checks.h"
#include "allocation.h" #include "allocation.h"
#include <stdlib.h> // For free, malloc.
#include <string.h> // For memcpy.
#include "checks.h"
#include "utils.h" #include "utils.h"
namespace v8 { namespace v8 {

3
deps/v8/src/allocation.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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -28,7 +28,6 @@
#ifndef V8_ALLOCATION_H_ #ifndef V8_ALLOCATION_H_
#define V8_ALLOCATION_H_ #define V8_ALLOCATION_H_
#include "checks.h"
#include "globals.h" #include "globals.h"
namespace v8 { namespace v8 {

24
deps/v8/src/api.cc

@ -25,34 +25,36 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "v8.h"
#include "api.h" #include "api.h"
#include "arguments.h" #include <math.h> // For isnan.
#include <string.h> // For memcpy, strlen.
#include "../include/v8-debug.h"
#include "../include/v8-profiler.h"
#include "../include/v8-testing.h"
#include "bootstrapper.h" #include "bootstrapper.h"
#include "compiler.h" #include "compiler.h"
#include "conversions-inl.h"
#include "counters.h"
#include "debug.h" #include "debug.h"
#include "deoptimizer.h" #include "deoptimizer.h"
#include "execution.h" #include "execution.h"
#include "flags.h"
#include "global-handles.h" #include "global-handles.h"
#include "heap-profiler.h" #include "heap-profiler.h"
#include "messages.h" #include "messages.h"
#include "natives.h"
#include "parser.h" #include "parser.h"
#include "platform.h" #include "platform.h"
#include "profile-generator-inl.h" #include "profile-generator-inl.h"
#include "property-details.h"
#include "property.h"
#include "runtime-profiler.h" #include "runtime-profiler.h"
#include "scanner-character-streams.h" #include "scanner-character-streams.h"
#include "serialize.h"
#include "snapshot.h" #include "snapshot.h"
#include "unicode-inl.h"
#include "v8threads.h" #include "v8threads.h"
#include "version.h" #include "version.h"
#include "vm-state-inl.h" #include "vm-state-inl.h"
#include "../include/v8-profiler.h"
#include "../include/v8-testing.h"
#define LOG_API(isolate, expr) LOG(isolate, ApiEntryCall(expr)) #define LOG_API(isolate, expr) LOG(isolate, ApiEntryCall(expr))
@ -3622,6 +3624,12 @@ Handle<Value> Function::GetName() const {
} }
Handle<Value> Function::GetInferredName() const {
i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
return Utils::ToLocal(i::Handle<i::Object>(func->shared()->inferred_name()));
}
ScriptOrigin Function::GetScriptOrigin() const { ScriptOrigin Function::GetScriptOrigin() const {
i::Handle<i::JSFunction> func = Utils::OpenHandle(this); i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
if (func->shared()->script()->IsScript()) { if (func->shared()->script()->IsScript()) {

10
deps/v8/src/api.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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -28,10 +28,14 @@
#ifndef V8_API_H_ #ifndef V8_API_H_
#define V8_API_H_ #define V8_API_H_
#include "apiutils.h" #include "v8.h"
#include "factory.h"
#include "../include/v8-testing.h" #include "../include/v8-testing.h"
#include "apiutils.h"
#include "contexts.h"
#include "factory.h"
#include "isolate.h"
#include "list-inl.h"
namespace v8 { namespace v8 {

1
deps/v8/src/arm/assembler-arm-inl.h

@ -38,6 +38,7 @@
#define V8_ARM_ASSEMBLER_ARM_INL_H_ #define V8_ARM_ASSEMBLER_ARM_INL_H_
#include "arm/assembler-arm.h" #include "arm/assembler-arm.h"
#include "cpu.h" #include "cpu.h"
#include "debug.h" #include "debug.h"

12
deps/v8/src/arm/assembler-arm.h

@ -300,11 +300,13 @@ const DwVfpRegister d13 = { 13 };
const DwVfpRegister d14 = { 14 }; const DwVfpRegister d14 = { 14 };
const DwVfpRegister d15 = { 15 }; const DwVfpRegister d15 = { 15 };
// Aliases for double registers. // Aliases for double registers. Defined using #define instead of
static const DwVfpRegister& kFirstCalleeSavedDoubleReg = d8; // "static const DwVfpRegister&" because Clang complains otherwise when a
static const DwVfpRegister& kLastCalleeSavedDoubleReg = d15; // compilation unit that includes this header doesn't use the variables.
static const DwVfpRegister& kDoubleRegZero = d14; #define kFirstCalleeSavedDoubleReg d8
static const DwVfpRegister& kScratchDoubleReg = d15; #define kLastCalleeSavedDoubleReg d15
#define kDoubleRegZero d14
#define kScratchDoubleReg d15
// Coprocessor register // Coprocessor register

1
deps/v8/src/arm/builtins-arm.cc

@ -1760,6 +1760,7 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
__ bind(&invoke); __ bind(&invoke);
__ Call(r3); __ Call(r3);
masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
// Exit frame and return. // Exit frame and return.
LeaveArgumentsAdaptorFrame(masm); LeaveArgumentsAdaptorFrame(masm);
__ Jump(lr); __ Jump(lr);

125
deps/v8/src/arm/deoptimizer-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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -211,12 +211,13 @@ void Deoptimizer::DoComputeOsrOutputFrame() {
ASSERT(Translation::BEGIN == opcode); ASSERT(Translation::BEGIN == opcode);
USE(opcode); USE(opcode);
int count = iterator.Next(); int count = iterator.Next();
iterator.Skip(1); // Drop JS frame count.
ASSERT(count == 1); ASSERT(count == 1);
USE(count); USE(count);
opcode = static_cast<Translation::Opcode>(iterator.Next()); opcode = static_cast<Translation::Opcode>(iterator.Next());
USE(opcode); USE(opcode);
ASSERT(Translation::FRAME == opcode); ASSERT(Translation::JS_FRAME == opcode);
unsigned node_id = iterator.Next(); unsigned node_id = iterator.Next();
USE(node_id); USE(node_id);
ASSERT(node_id == ast_id); ASSERT(node_id == ast_id);
@ -252,9 +253,7 @@ void Deoptimizer::DoComputeOsrOutputFrame() {
output_ = new FrameDescription*[1]; output_ = new FrameDescription*[1];
output_[0] = new(output_frame_size) FrameDescription( output_[0] = new(output_frame_size) FrameDescription(
output_frame_size, function_); output_frame_size, function_);
#ifdef DEBUG output_[0]->SetFrameType(StackFrame::JAVA_SCRIPT);
output_[0]->SetKind(Code::OPTIMIZED_FUNCTION);
#endif
// Clear the incoming parameters in the optimized frame to avoid // Clear the incoming parameters in the optimized frame to avoid
// confusing the garbage collector. // confusing the garbage collector.
@ -342,15 +341,115 @@ void Deoptimizer::DoComputeOsrOutputFrame() {
} }
void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator,
int frame_index) {
JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
unsigned height = iterator->Next();
unsigned height_in_bytes = height * kPointerSize;
if (FLAG_trace_deopt) {
PrintF(" translating arguments adaptor => height=%d\n", height_in_bytes);
}
unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize;
unsigned input_frame_size = input_->GetFrameSize();
unsigned output_frame_size = height_in_bytes + fixed_frame_size;
// Allocate and store the output frame description.
FrameDescription* output_frame =
new(output_frame_size) FrameDescription(output_frame_size, function);
output_frame->SetFrameType(StackFrame::ARGUMENTS_ADAPTOR);
// Arguments adaptor can not be topmost or bottommost.
ASSERT(frame_index > 0 && frame_index < output_count_ - 1);
ASSERT(output_[frame_index] == NULL);
output_[frame_index] = output_frame;
// The top address of the frame is computed from the previous
// frame's top and this frame's size.
uint32_t top_address;
top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
output_frame->SetTop(top_address);
// Compute the incoming parameter translation.
int parameter_count = height;
unsigned output_offset = output_frame_size;
unsigned input_offset = input_frame_size;
for (int i = 0; i < parameter_count; ++i) {
output_offset -= kPointerSize;
DoTranslateCommand(iterator, frame_index, output_offset);
}
input_offset -= (parameter_count * kPointerSize);
// Read caller's PC from the previous frame.
output_offset -= kPointerSize;
input_offset -= kPointerSize;
intptr_t callers_pc = output_[frame_index - 1]->GetPc();
output_frame->SetFrameSlot(output_offset, callers_pc);
if (FLAG_trace_deopt) {
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's pc\n",
top_address + output_offset, output_offset, callers_pc);
}
// Read caller's FP from the previous frame, and set this frame's FP.
output_offset -= kPointerSize;
input_offset -= kPointerSize;
intptr_t value = output_[frame_index - 1]->GetFp();
output_frame->SetFrameSlot(output_offset, value);
intptr_t fp_value = top_address + output_offset;
output_frame->SetFp(fp_value);
if (FLAG_trace_deopt) {
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's fp\n",
fp_value, output_offset, value);
}
// A marker value is used in place of the context.
output_offset -= kPointerSize;
input_offset -= kPointerSize;
intptr_t context = reinterpret_cast<intptr_t>(
Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
output_frame->SetFrameSlot(output_offset, context);
if (FLAG_trace_deopt) {
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; context (adaptor sentinel)\n",
top_address + output_offset, output_offset, context);
}
// The function was mentioned explicitly in the ARGUMENTS_ADAPTOR_FRAME.
output_offset -= kPointerSize;
input_offset -= kPointerSize;
value = reinterpret_cast<intptr_t>(function);
output_frame->SetFrameSlot(output_offset, value);
if (FLAG_trace_deopt) {
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; function\n",
top_address + output_offset, output_offset, value);
}
// Number of incoming arguments.
output_offset -= kPointerSize;
input_offset -= kPointerSize;
value = reinterpret_cast<uint32_t>(Smi::FromInt(height - 1));
output_frame->SetFrameSlot(output_offset, value);
if (FLAG_trace_deopt) {
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; argc (%d)\n",
top_address + output_offset, output_offset, value, height - 1);
}
ASSERT(0 == output_offset);
Builtins* builtins = isolate_->builtins();
Code* adaptor_trampoline =
builtins->builtin(Builtins::kArgumentsAdaptorTrampoline);
uint32_t pc = reinterpret_cast<uint32_t>(
adaptor_trampoline->instruction_start() +
isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value());
output_frame->SetPc(pc);
}
// This code is very similar to ia32 code, but relies on register names (fp, sp) // This code is very similar to ia32 code, but relies on register names (fp, sp)
// and how the frame is laid out. // and how the frame is laid out.
void Deoptimizer::DoComputeFrame(TranslationIterator* iterator, void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
int frame_index) { int frame_index) {
// Read the ast node id, function, and frame height for this output frame. // Read the ast node id, function, and frame height for this output frame.
Translation::Opcode opcode =
static_cast<Translation::Opcode>(iterator->Next());
USE(opcode);
ASSERT(Translation::FRAME == opcode);
int node_id = iterator->Next(); int node_id = iterator->Next();
JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
unsigned height = iterator->Next(); unsigned height = iterator->Next();
@ -370,9 +469,7 @@ void Deoptimizer::DoComputeFrame(TranslationIterator* iterator,
// Allocate and store the output frame description. // Allocate and store the output frame description.
FrameDescription* output_frame = FrameDescription* output_frame =
new(output_frame_size) FrameDescription(output_frame_size, function); new(output_frame_size) FrameDescription(output_frame_size, function);
#ifdef DEBUG output_frame->SetFrameType(StackFrame::JAVA_SCRIPT);
output_frame->SetKind(Code::FUNCTION);
#endif
bool is_bottommost = (0 == frame_index); bool is_bottommost = (0 == frame_index);
bool is_topmost = (output_count_ - 1 == frame_index); bool is_topmost = (output_count_ - 1 == frame_index);

34
deps/v8/src/arm/disasm-arm.cc

@ -662,6 +662,15 @@ void Decoder::Format(Instruction* instr, const char* format) {
} }
// The disassembler may end up decoding data inlined in the code. We do not want
// it to crash if the data does not ressemble any known instruction.
#define VERIFY(condition) \
if(!(condition)) { \
Unknown(instr); \
return; \
}
// For currently unimplemented decodings the disassembler calls Unknown(instr) // For currently unimplemented decodings the disassembler calls Unknown(instr)
// which will just print "unknown" of the instruction bits. // which will just print "unknown" of the instruction bits.
void Decoder::Unknown(Instruction* instr) { void Decoder::Unknown(Instruction* instr) {
@ -947,13 +956,13 @@ void Decoder::DecodeType2(Instruction* instr) {
void Decoder::DecodeType3(Instruction* instr) { void Decoder::DecodeType3(Instruction* instr) {
switch (instr->PUField()) { switch (instr->PUField()) {
case da_x: { case da_x: {
ASSERT(!instr->HasW()); VERIFY(!instr->HasW());
Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm"); Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
break; break;
} }
case ia_x: { case ia_x: {
if (instr->HasW()) { if (instr->HasW()) {
ASSERT(instr->Bits(5, 4) == 0x1); VERIFY(instr->Bits(5, 4) == 0x1);
if (instr->Bit(22) == 0x1) { if (instr->Bit(22) == 0x1) {
Format(instr, "usat 'rd, #'imm05@16, 'rm'shift_sat"); Format(instr, "usat 'rd, #'imm05@16, 'rm'shift_sat");
} else { } else {
@ -1074,8 +1083,8 @@ int Decoder::DecodeType7(Instruction* instr) {
// vmsr // vmsr
// Dd = vsqrt(Dm) // Dd = vsqrt(Dm)
void Decoder::DecodeTypeVFP(Instruction* instr) { void Decoder::DecodeTypeVFP(Instruction* instr) {
ASSERT((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) ); VERIFY((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) );
ASSERT(instr->Bits(11, 9) == 0x5); VERIFY(instr->Bits(11, 9) == 0x5);
if (instr->Bit(4) == 0) { if (instr->Bit(4) == 0) {
if (instr->Opc1Value() == 0x7) { if (instr->Opc1Value() == 0x7) {
@ -1166,7 +1175,7 @@ void Decoder::DecodeTypeVFP(Instruction* instr) {
void Decoder::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters( void Decoder::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(
Instruction* instr) { Instruction* instr) {
ASSERT((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) && VERIFY((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) &&
(instr->VAValue() == 0x0)); (instr->VAValue() == 0x0));
bool to_arm_register = (instr->VLValue() == 0x1); bool to_arm_register = (instr->VLValue() == 0x1);
@ -1180,8 +1189,8 @@ void Decoder::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(
void Decoder::DecodeVCMP(Instruction* instr) { void Decoder::DecodeVCMP(Instruction* instr) {
ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
ASSERT(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) && VERIFY(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
(instr->Opc3Value() & 0x1)); (instr->Opc3Value() & 0x1));
// Comparison. // Comparison.
@ -1203,8 +1212,8 @@ void Decoder::DecodeVCMP(Instruction* instr) {
void Decoder::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) { void Decoder::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) {
ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
ASSERT((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)); VERIFY((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3));
bool double_to_single = (instr->SzValue() == 1); bool double_to_single = (instr->SzValue() == 1);
@ -1217,8 +1226,8 @@ void Decoder::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) {
void Decoder::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) { void Decoder::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7)); VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
ASSERT(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) || VERIFY(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) ||
(((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1))); (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1)));
bool to_integer = (instr->Bit(18) == 1); bool to_integer = (instr->Bit(18) == 1);
@ -1265,7 +1274,7 @@ void Decoder::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
// Ddst = MEM(Rbase + 4*offset). // Ddst = MEM(Rbase + 4*offset).
// MEM(Rbase + 4*offset) = Dsrc. // MEM(Rbase + 4*offset) = Dsrc.
void Decoder::DecodeType6CoprocessorIns(Instruction* instr) { void Decoder::DecodeType6CoprocessorIns(Instruction* instr) {
ASSERT(instr->TypeValue() == 6); VERIFY(instr->TypeValue() == 6);
if (instr->CoprocessorValue() == 0xA) { if (instr->CoprocessorValue() == 0xA) {
switch (instr->OpcodeValue()) { switch (instr->OpcodeValue()) {
@ -1347,6 +1356,7 @@ void Decoder::DecodeType6CoprocessorIns(Instruction* instr) {
} }
} }
#undef VERIFIY
bool Decoder::IsConstantPoolAt(byte* instr_ptr) { bool Decoder::IsConstantPoolAt(byte* instr_ptr) {
int instruction_bits = *(reinterpret_cast<int*>(instr_ptr)); int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));

7
deps/v8/src/arm/frames-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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -136,6 +136,9 @@ class ExitFrameConstants : public AllStatic {
class StandardFrameConstants : public AllStatic { class StandardFrameConstants : public AllStatic {
public: public:
// Fixed part of the frame consists of return address, caller fp,
// context and function.
static const int kFixedFrameSize = 4 * kPointerSize;
static const int kExpressionsOffset = -3 * kPointerSize; static const int kExpressionsOffset = -3 * kPointerSize;
static const int kMarkerOffset = -2 * kPointerSize; static const int kMarkerOffset = -2 * kPointerSize;
static const int kContextOffset = -1 * kPointerSize; static const int kContextOffset = -1 * kPointerSize;
@ -161,6 +164,8 @@ class JavaScriptFrameConstants : public AllStatic {
class ArgumentsAdaptorFrameConstants : public AllStatic { class ArgumentsAdaptorFrameConstants : public AllStatic {
public: public:
static const int kLengthOffset = StandardFrameConstants::kExpressionsOffset; static const int kLengthOffset = StandardFrameConstants::kExpressionsOffset;
static const int kFrameSize =
StandardFrameConstants::kFixedFrameSize + kPointerSize;
}; };

59
deps/v8/src/arm/ic-arm.cc

@ -1036,21 +1036,29 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
// Load the key (consisting of map and symbol) from the cache and // Load the key (consisting of map and symbol) from the cache and
// check for match. // check for match.
Label try_second_entry, hit_on_first_entry, load_in_object_property; Label load_in_object_property;
static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket;
Label hit_on_nth_entry[kEntriesPerBucket];
ExternalReference cache_keys = ExternalReference cache_keys =
ExternalReference::keyed_lookup_cache_keys(isolate); ExternalReference::keyed_lookup_cache_keys(isolate);
__ mov(r4, Operand(cache_keys)); __ mov(r4, Operand(cache_keys));
__ add(r4, r4, Operand(r3, LSL, kPointerSizeLog2 + 1)); __ add(r4, r4, Operand(r3, LSL, kPointerSizeLog2 + 1));
// Move r4 to second entry.
__ ldr(r5, MemOperand(r4, kPointerSize * 2, PostIndex));
__ cmp(r2, r5);
__ b(ne, &try_second_entry);
__ ldr(r5, MemOperand(r4, -kPointerSize)); // Load symbol
__ cmp(r0, r5);
__ b(eq, &hit_on_first_entry);
__ bind(&try_second_entry); for (int i = 0; i < kEntriesPerBucket - 1; i++) {
__ ldr(r5, MemOperand(r4, kPointerSize, PostIndex)); // Move r4 to symbol. Label try_next_entry;
// Load map and move r4 to next entry.
__ ldr(r5, MemOperand(r4, kPointerSize * 2, PostIndex));
__ cmp(r2, r5);
__ b(ne, &try_next_entry);
__ ldr(r5, MemOperand(r4, -kPointerSize)); // Load symbol
__ cmp(r0, r5);
__ b(eq, &hit_on_nth_entry[i]);
__ bind(&try_next_entry);
}
// Last entry: Load map and move r4 to symbol.
__ ldr(r5, MemOperand(r4, kPointerSize, PostIndex));
__ cmp(r2, r5); __ cmp(r2, r5);
__ b(ne, &slow); __ b(ne, &slow);
__ ldr(r5, MemOperand(r4)); __ ldr(r5, MemOperand(r4));
@ -1065,22 +1073,21 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
ExternalReference cache_field_offsets = ExternalReference cache_field_offsets =
ExternalReference::keyed_lookup_cache_field_offsets(isolate); ExternalReference::keyed_lookup_cache_field_offsets(isolate);
// Hit on second entry. // Hit on nth entry.
__ mov(r4, Operand(cache_field_offsets)); for (int i = kEntriesPerBucket - 1; i >= 0; i--) {
__ add(r3, r3, Operand(1)); __ bind(&hit_on_nth_entry[i]);
__ ldr(r5, MemOperand(r4, r3, LSL, kPointerSizeLog2)); __ mov(r4, Operand(cache_field_offsets));
__ ldrb(r6, FieldMemOperand(r2, Map::kInObjectPropertiesOffset)); if (i != 0) {
__ sub(r5, r5, r6, SetCC); __ add(r3, r3, Operand(i));
__ b(ge, &property_array_property); }
__ jmp(&load_in_object_property); __ ldr(r5, MemOperand(r4, r3, LSL, kPointerSizeLog2));
__ ldrb(r6, FieldMemOperand(r2, Map::kInObjectPropertiesOffset));
// Hit on first entry. __ sub(r5, r5, r6, SetCC);
__ bind(&hit_on_first_entry); __ b(ge, &property_array_property);
__ mov(r4, Operand(cache_field_offsets)); if (i != 0) {
__ ldr(r5, MemOperand(r4, r3, LSL, kPointerSizeLog2)); __ jmp(&load_in_object_property);
__ ldrb(r6, FieldMemOperand(r2, Map::kInObjectPropertiesOffset)); }
__ sub(r5, r5, r6, SetCC); }
__ b(ge, &property_array_property);
// Load in-object property. // Load in-object property.
__ bind(&load_in_object_property); __ bind(&load_in_object_property);

24
deps/v8/src/arm/lithium-arm.cc

@ -1005,14 +1005,16 @@ LEnvironment* LChunkBuilder::CreateEnvironment(
LEnvironment* outer = LEnvironment* outer =
CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator); CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator);
int ast_id = hydrogen_env->ast_id(); int ast_id = hydrogen_env->ast_id();
ASSERT(ast_id != AstNode::kNoNumber); ASSERT(ast_id != AstNode::kNoNumber || hydrogen_env->is_arguments_adaptor());
int value_count = hydrogen_env->length(); int value_count = hydrogen_env->length();
LEnvironment* result = new LEnvironment(hydrogen_env->closure(), LEnvironment* result = new LEnvironment(hydrogen_env->closure(),
hydrogen_env->is_arguments_adaptor(),
ast_id, ast_id,
hydrogen_env->parameter_count(), hydrogen_env->parameter_count(),
argument_count_, argument_count_,
value_count, value_count,
outer); outer);
int argument_index = *argument_index_accumulator;
for (int i = 0; i < value_count; ++i) { for (int i = 0; i < value_count; ++i) {
if (hydrogen_env->is_special_index(i)) continue; if (hydrogen_env->is_special_index(i)) continue;
@ -1021,13 +1023,17 @@ LEnvironment* LChunkBuilder::CreateEnvironment(
if (value->IsArgumentsObject()) { if (value->IsArgumentsObject()) {
op = NULL; op = NULL;
} else if (value->IsPushArgument()) { } else if (value->IsPushArgument()) {
op = new LArgument((*argument_index_accumulator)++); op = new LArgument(argument_index++);
} else { } else {
op = UseAny(value); op = UseAny(value);
} }
result->AddValue(op, value->representation()); result->AddValue(op, value->representation());
} }
if (!hydrogen_env->is_arguments_adaptor()) {
*argument_index_accumulator = argument_index;
}
return result; return result;
} }
@ -1917,12 +1923,11 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement( LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
HLoadKeyedSpecializedArrayElement* instr) { HLoadKeyedSpecializedArrayElement* instr) {
ElementsKind elements_kind = instr->elements_kind(); ElementsKind elements_kind = instr->elements_kind();
Representation representation(instr->representation());
ASSERT( ASSERT(
(representation.IsInteger32() && (instr->representation().IsInteger32() &&
(elements_kind != EXTERNAL_FLOAT_ELEMENTS) && (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
(elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) || (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
(representation.IsDouble() && (instr->representation().IsDouble() &&
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) || ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS)))); (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
ASSERT(instr->key()->representation().IsInteger32()); ASSERT(instr->key()->representation().IsInteger32());
@ -1982,13 +1987,12 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement(
LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement( LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
HStoreKeyedSpecializedArrayElement* instr) { HStoreKeyedSpecializedArrayElement* instr) {
Representation representation(instr->value()->representation());
ElementsKind elements_kind = instr->elements_kind(); ElementsKind elements_kind = instr->elements_kind();
ASSERT( ASSERT(
(representation.IsInteger32() && (instr->value()->representation().IsInteger32() &&
(elements_kind != EXTERNAL_FLOAT_ELEMENTS) && (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
(elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) || (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
(representation.IsDouble() && (instr->value()->representation().IsDouble() &&
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) || ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS)))); (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
ASSERT(instr->external_pointer()->representation().IsExternal()); ASSERT(instr->external_pointer()->representation().IsExternal());
@ -2244,6 +2248,7 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
HEnvironment* outer = current_block_->last_environment(); HEnvironment* outer = current_block_->last_environment();
HConstant* undefined = graph()->GetConstantUndefined(); HConstant* undefined = graph()->GetConstantUndefined();
HEnvironment* inner = outer->CopyForInlining(instr->closure(), HEnvironment* inner = outer->CopyForInlining(instr->closure(),
instr->arguments_count(),
instr->function(), instr->function(),
undefined, undefined,
instr->call_kind()); instr->call_kind());
@ -2254,7 +2259,8 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
HEnvironment* outer = current_block_->last_environment()->outer(); HEnvironment* outer = current_block_->last_environment()->
DiscardInlined(false);
current_block_->UpdateEnvironment(outer); current_block_->UpdateEnvironment(outer);
return NULL; return NULL;
} }

12
deps/v8/src/arm/lithium-codegen-arm.cc

@ -479,7 +479,11 @@ void LCodeGen::WriteTranslation(LEnvironment* environment,
WriteTranslation(environment->outer(), translation); WriteTranslation(environment->outer(), translation);
int closure_id = DefineDeoptimizationLiteral(environment->closure()); int closure_id = DefineDeoptimizationLiteral(environment->closure());
translation->BeginFrame(environment->ast_id(), closure_id, height); if (environment->is_arguments_adaptor()) {
translation->BeginArgumentsAdaptorFrame(closure_id, translation_size);
} else {
translation->BeginJSFrame(environment->ast_id(), closure_id, height);
}
for (int i = 0; i < translation_size; ++i) { for (int i = 0; i < translation_size; ++i) {
LOperand* value = environment->values()->at(i); LOperand* value = environment->values()->at(i);
// spilled_registers_ and spilled_double_registers_ are either // spilled_registers_ and spilled_double_registers_ are either
@ -612,10 +616,14 @@ void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment,
// |>------------ translation_size ------------<| // |>------------ translation_size ------------<|
int frame_count = 0; int frame_count = 0;
int jsframe_count = 0;
for (LEnvironment* e = environment; e != NULL; e = e->outer()) { for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
++frame_count; ++frame_count;
if (!e->is_arguments_adaptor()) {
++jsframe_count;
}
} }
Translation translation(&translations_, frame_count); Translation translation(&translations_, frame_count, jsframe_count);
WriteTranslation(environment, &translation); WriteTranslation(environment, &translation);
int deoptimization_index = deoptimizations_.length(); int deoptimization_index = deoptimizations_.length();
int pc_offset = masm()->pc_offset(); int pc_offset = masm()->pc_offset();

41
deps/v8/src/assembler.cc

@ -30,25 +30,42 @@
// The original source code covered by the above license above has been // The original source code covered by the above license above has been
// modified significantly by Google Inc. // modified significantly by Google Inc.
// Copyright 2011 the V8 project authors. All rights reserved. // Copyright 2012 the V8 project authors. All rights reserved.
#include "v8.h" #include "assembler.h"
#include "arguments.h" #include <math.h> // For cos, log, pow, sin, tan, etc.
#include "api.h"
#include "builtins.h"
#include "counters.h"
#include "cpu.h"
#include "debug.h"
#include "deoptimizer.h" #include "deoptimizer.h"
#include "execution.h" #include "execution.h"
#include "ic-inl.h" #include "ic.h"
#include "incremental-marking.h" #include "isolate.h"
#include "factory.h" #include "jsregexp.h"
#include "platform.h"
#include "regexp-macro-assembler.h"
#include "regexp-stack.h"
#include "runtime.h" #include "runtime.h"
#include "runtime-profiler.h"
#include "serialize.h" #include "serialize.h"
#include "store-buffer-inl.h"
#include "stub-cache.h" #include "stub-cache.h"
#include "regexp-stack.h" #include "token.h"
#include "ast.h"
#include "regexp-macro-assembler.h" #if V8_TARGET_ARCH_IA32
#include "platform.h" #include "ia32/assembler-ia32-inl.h"
#include "store-buffer.h" #elif V8_TARGET_ARCH_X64
#include "x64/assembler-x64-inl.h"
#elif V8_TARGET_ARCH_ARM
#include "arm/assembler-arm-inl.h"
#elif V8_TARGET_ARCH_MIPS
#include "mips/assembler-mips-inl.h"
#else
#error "Unknown architecture."
#endif
// Include native regexp-macro-assembler. // Include native regexp-macro-assembler.
#ifndef V8_INTERPRETED_REGEXP #ifndef V8_INTERPRETED_REGEXP
#if V8_TARGET_ARCH_IA32 #if V8_TARGET_ARCH_IA32

10
deps/v8/src/assembler.h

@ -30,19 +30,27 @@
// The original source code covered by the above license above has been // The original source code covered by the above license above has been
// modified significantly by Google Inc. // modified significantly by Google Inc.
// Copyright 2011 the V8 project authors. All rights reserved. // Copyright 2012 the V8 project authors. All rights reserved.
#ifndef V8_ASSEMBLER_H_ #ifndef V8_ASSEMBLER_H_
#define V8_ASSEMBLER_H_ #define V8_ASSEMBLER_H_
#include "v8.h"
#include "allocation.h" #include "allocation.h"
#include "builtins.h"
#include "gdb-jit.h" #include "gdb-jit.h"
#include "isolate.h"
#include "runtime.h" #include "runtime.h"
#include "token.h" #include "token.h"
namespace v8 { namespace v8 {
class ApiFunction;
namespace internal { namespace internal {
struct StatsCounter;
const unsigned kNoASTId = -1; const unsigned kNoASTId = -1;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Platform independent assembler base class. // Platform independent assembler base class.

11
deps/v8/src/ast.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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -25,10 +25,15 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "v8.h"
#include "ast.h" #include "ast.h"
#include <math.h> // For isfinite.
#include "builtins.h"
#include "conversions.h"
#include "hashmap.h"
#include "parser.h" #include "parser.h"
#include "property-details.h"
#include "property.h"
#include "scopes.h" #include "scopes.h"
#include "string-stream.h" #include "string-stream.h"
#include "type-info.h" #include "type-info.h"

41
deps/v8/src/ast.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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -28,14 +28,19 @@
#ifndef V8_AST_H_ #ifndef V8_AST_H_
#define V8_AST_H_ #define V8_AST_H_
#include "allocation.h" #include "v8.h"
#include "execution.h"
#include "assembler.h"
#include "factory.h" #include "factory.h"
#include "isolate.h"
#include "jsregexp.h" #include "jsregexp.h"
#include "list-inl.h"
#include "runtime.h" #include "runtime.h"
#include "small-pointer-list.h" #include "small-pointer-list.h"
#include "smart-array-pointer.h"
#include "token.h" #include "token.h"
#include "variables.h" #include "variables.h"
#include "zone-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
@ -98,12 +103,28 @@ namespace internal {
EXPRESSION_NODE_LIST(V) EXPRESSION_NODE_LIST(V)
// Forward declarations // Forward declarations
class BitVector; class AstVisitor;
class DefinitionInfo; class BreakableStatement;
class Expression;
class IterationStatement;
class MaterializedLiteral; class MaterializedLiteral;
class Statement;
class TargetCollector; class TargetCollector;
class TypeFeedbackOracle; class TypeFeedbackOracle;
class RegExpAlternative;
class RegExpAssertion;
class RegExpAtom;
class RegExpBackReference;
class RegExpCapture;
class RegExpCharacterClass;
class RegExpCompiler;
class RegExpDisjunction;
class RegExpEmpty;
class RegExpLookahead;
class RegExpQuantifier;
class RegExpText;
#define DEF_FORWARD_DECLARATION(type) class type; #define DEF_FORWARD_DECLARATION(type) class type;
AST_NODE_LIST(DEF_FORWARD_DECLARATION) AST_NODE_LIST(DEF_FORWARD_DECLARATION)
#undef DEF_FORWARD_DECLARATION #undef DEF_FORWARD_DECLARATION
@ -115,11 +136,6 @@ typedef ZoneList<Handle<String> > ZoneStringList;
typedef ZoneList<Handle<Object> > ZoneObjectList; typedef ZoneList<Handle<Object> > ZoneObjectList;
#define DECLARE_NODE_TYPE(type) \
virtual void Accept(AstVisitor* v); \
virtual AstNode::Type node_type() const { return AstNode::k##type; } \
class AstNode: public ZoneObject { class AstNode: public ZoneObject {
public: public:
#define DECLARE_TYPE_ENUM(type) k##type, #define DECLARE_TYPE_ENUM(type) k##type,
@ -190,6 +206,11 @@ class AstNode: public ZoneObject {
}; };
#define DECLARE_NODE_TYPE(type) \
virtual void Accept(AstVisitor* v); \
virtual AstNode::Type node_type() const { return AstNode::k##type; } \
class Statement: public AstNode { class Statement: public AstNode {
public: public:
Statement() : statement_pos_(RelocInfo::kNoPosition) {} Statement() : statement_pos_(RelocInfo::kNoPosition) {}

7
deps/v8/src/cpu-profiler.cc

@ -39,13 +39,14 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
static const int kEventsBufferSize = 256*KB; static const int kEventsBufferSize = 256 * KB;
static const int kTickSamplesBufferChunkSize = 64*KB; static const int kTickSamplesBufferChunkSize = 64 * KB;
static const int kTickSamplesBufferChunksCount = 16; static const int kTickSamplesBufferChunksCount = 16;
static const int kProfilerStackSize = 32 * KB;
ProfilerEventsProcessor::ProfilerEventsProcessor(ProfileGenerator* generator) ProfilerEventsProcessor::ProfilerEventsProcessor(ProfileGenerator* generator)
: Thread("v8:ProfEvntProc"), : Thread(Thread::Options("v8:ProfEvntProc", kProfilerStackSize)),
generator_(generator), generator_(generator),
running_(true), running_(true),
ticks_buffer_(sizeof(TickSampleEventRecord), ticks_buffer_(sizeof(TickSampleEventRecord),

29
deps/v8/src/d8.cc

@ -120,6 +120,9 @@ ShellOptions Shell::options;
const char* Shell::kPrompt = "d8> "; const char* Shell::kPrompt = "d8> ";
const int MB = 1024 * 1024;
#ifndef V8_SHARED #ifndef V8_SHARED
bool CounterMap::Match(void* key1, void* key2) { bool CounterMap::Match(void* key1, void* key2) {
const char* name1 = reinterpret_cast<const char*>(key1); const char* name1 = reinterpret_cast<const char*>(key1);
@ -803,6 +806,8 @@ Handle<ObjectTemplate> Shell::CreateGlobalTemplate() {
global_template->Set(String::New("print"), FunctionTemplate::New(Print)); global_template->Set(String::New("print"), FunctionTemplate::New(Print));
global_template->Set(String::New("write"), FunctionTemplate::New(Write)); global_template->Set(String::New("write"), FunctionTemplate::New(Write));
global_template->Set(String::New("read"), FunctionTemplate::New(Read)); global_template->Set(String::New("read"), FunctionTemplate::New(Read));
global_template->Set(String::New("readbinary"),
FunctionTemplate::New(ReadBinary));
global_template->Set(String::New("readline"), global_template->Set(String::New("readline"),
FunctionTemplate::New(ReadLine)); FunctionTemplate::New(ReadLine));
global_template->Set(String::New("load"), FunctionTemplate::New(Load)); global_template->Set(String::New("load"), FunctionTemplate::New(Load));
@ -1021,6 +1026,23 @@ static char* ReadChars(const char* name, int* size_out) {
} }
Handle<Value> Shell::ReadBinary(const Arguments& args) {
String::Utf8Value filename(args[0]);
int size;
if (*filename == NULL) {
return ThrowException(String::New("Error loading file"));
}
char* chars = ReadChars(*filename, &size);
if (chars == NULL) {
return ThrowException(String::New("Error reading file"));
}
// We skip checking the string for UTF8 characters and use it raw as
// backing store for the external string with 8-bit characters.
BinaryResource* resource = new BinaryResource(chars, size);
return String::NewExternal(resource);
}
#ifndef V8_SHARED #ifndef V8_SHARED
static char* ReadToken(char* data, char token) { static char* ReadToken(char* data, char token) {
char* next = i::OS::StrChr(data, token); char* next = i::OS::StrChr(data, token);
@ -1191,14 +1213,11 @@ Handle<String> SourceGroup::ReadFile(const char* name) {
#ifndef V8_SHARED #ifndef V8_SHARED
i::Thread::Options SourceGroup::GetThreadOptions() { i::Thread::Options SourceGroup::GetThreadOptions() {
i::Thread::Options options;
options.name = "IsolateThread";
// On some systems (OSX 10.6) the stack size default is 0.5Mb or less // On some systems (OSX 10.6) the stack size default is 0.5Mb or less
// which is not enough to parse the big literal expressions used in tests. // which is not enough to parse the big literal expressions used in tests.
// The stack size should be at least StackGuard::kLimitSize + some // The stack size should be at least StackGuard::kLimitSize + some
// OS-specific padding for thread startup code. // OS-specific padding for thread startup code. 2Mbytes seems to be enough.
options.stack_size = 2 << 20; // 2 Mb seems to be enough return i::Thread::Options("IsolateThread", 2 * MB);
return options;
} }

22
deps/v8/src/d8.h

@ -195,6 +195,27 @@ class SourceGroup {
}; };
class BinaryResource : public v8::String::ExternalAsciiStringResource {
public:
BinaryResource(const char* string, int length)
: data_(string),
length_(length) { }
~BinaryResource() {
delete[] data_;
data_ = NULL;
length_ = 0;
}
virtual const char* data() const { return data_; }
virtual size_t length() const { return length_; }
private:
const char* data_;
size_t length_;
};
class ShellOptions { class ShellOptions {
public: public:
ShellOptions() : ShellOptions() :
@ -286,6 +307,7 @@ class Shell : public i::AllStatic {
static Handle<Value> EnableProfiler(const Arguments& args); static Handle<Value> EnableProfiler(const Arguments& args);
static Handle<Value> DisableProfiler(const Arguments& args); static Handle<Value> DisableProfiler(const Arguments& args);
static Handle<Value> Read(const Arguments& args); static Handle<Value> Read(const Arguments& args);
static Handle<Value> ReadBinary(const Arguments& args);
static Handle<String> ReadFromStdin(); static Handle<String> ReadFromStdin();
static Handle<Value> ReadLine(const Arguments& args) { static Handle<Value> ReadLine(const Arguments& args) {
return ReadFromStdin(); return ReadFromStdin();

283
deps/v8/src/debug.cc

@ -1758,6 +1758,135 @@ static bool CompileFullCodeForDebugging(Handle<SharedFunctionInfo> shared,
} }
static void CollectActiveFunctionsFromThread(
Isolate* isolate,
ThreadLocalTop* top,
List<Handle<JSFunction> >* active_functions,
Object* active_code_marker) {
// Find all non-optimized code functions with activation frames
// on the stack. This includes functions which have optimized
// activations (including inlined functions) on the stack as the
// non-optimized code is needed for the lazy deoptimization.
for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
JavaScriptFrame* frame = it.frame();
if (frame->is_optimized()) {
List<JSFunction*> functions(Compiler::kMaxInliningLevels + 1);
frame->GetFunctions(&functions);
for (int i = 0; i < functions.length(); i++) {
JSFunction* function = functions[i];
active_functions->Add(Handle<JSFunction>(function));
function->shared()->code()->set_gc_metadata(active_code_marker);
}
} else if (frame->function()->IsJSFunction()) {
JSFunction* function = JSFunction::cast(frame->function());
ASSERT(frame->LookupCode()->kind() == Code::FUNCTION);
active_functions->Add(Handle<JSFunction>(function));
function->shared()->code()->set_gc_metadata(active_code_marker);
}
}
}
static void RedirectActivationsToRecompiledCodeOnThread(
Isolate* isolate,
ThreadLocalTop* top) {
for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
JavaScriptFrame* frame = it.frame();
if (frame->is_optimized() || !frame->function()->IsJSFunction()) continue;
JSFunction* function = JSFunction::cast(frame->function());
ASSERT(frame->LookupCode()->kind() == Code::FUNCTION);
Handle<Code> frame_code(frame->LookupCode());
if (frame_code->has_debug_break_slots()) continue;
Handle<Code> new_code(function->shared()->code());
if (new_code->kind() != Code::FUNCTION ||
!new_code->has_debug_break_slots()) {
continue;
}
intptr_t delta = frame->pc() - frame_code->instruction_start();
int debug_break_slot_count = 0;
int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT);
for (RelocIterator it(*new_code, mask); !it.done(); it.next()) {
// Check if the pc in the new code with debug break
// slots is before this slot.
RelocInfo* info = it.rinfo();
int debug_break_slot_bytes =
debug_break_slot_count * Assembler::kDebugBreakSlotLength;
intptr_t new_delta =
info->pc() -
new_code->instruction_start() -
debug_break_slot_bytes;
if (new_delta > delta) {
break;
}
// Passed a debug break slot in the full code with debug
// break slots.
debug_break_slot_count++;
}
int debug_break_slot_bytes =
debug_break_slot_count * Assembler::kDebugBreakSlotLength;
if (FLAG_trace_deopt) {
PrintF("Replacing code %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
"with %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
"for debugging, "
"changing pc from %08" V8PRIxPTR " to %08" V8PRIxPTR "\n",
reinterpret_cast<intptr_t>(
frame_code->instruction_start()),
reinterpret_cast<intptr_t>(
frame_code->instruction_start()) +
frame_code->instruction_size(),
frame_code->instruction_size(),
reinterpret_cast<intptr_t>(new_code->instruction_start()),
reinterpret_cast<intptr_t>(new_code->instruction_start()) +
new_code->instruction_size(),
new_code->instruction_size(),
reinterpret_cast<intptr_t>(frame->pc()),
reinterpret_cast<intptr_t>(new_code->instruction_start()) +
delta + debug_break_slot_bytes);
}
// Patch the return address to return into the code with
// debug break slots.
frame->set_pc(
new_code->instruction_start() + delta + debug_break_slot_bytes);
}
}
class ActiveFunctionsCollector : public ThreadVisitor {
public:
explicit ActiveFunctionsCollector(List<Handle<JSFunction> >* active_functions,
Object* active_code_marker)
: active_functions_(active_functions),
active_code_marker_(active_code_marker) { }
void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
CollectActiveFunctionsFromThread(isolate,
top,
active_functions_,
active_code_marker_);
}
private:
List<Handle<JSFunction> >* active_functions_;
Object* active_code_marker_;
};
class ActiveFunctionsRedirector : public ThreadVisitor {
public:
void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
RedirectActivationsToRecompiledCodeOnThread(isolate, top);
}
};
void Debug::PrepareForBreakPoints() { void Debug::PrepareForBreakPoints() {
// If preparing for the first break point make sure to deoptimize all // If preparing for the first break point make sure to deoptimize all
// functions as debugging does not work with optimized code. // functions as debugging does not work with optimized code.
@ -1776,71 +1905,59 @@ void Debug::PrepareForBreakPoints() {
// debug break slots. // debug break slots.
isolate_->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask); isolate_->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask);
// Ensure no GC in this scope as we are comparing raw pointer // Ensure no GC in this scope as we are going to use gc_metadata
// values and performing a heap iteration. // field in the Code object to mark active functions.
AssertNoAllocation no_allocation; AssertNoAllocation no_allocation;
// Find all non-optimized code functions with activation frames Object* active_code_marker = isolate_->heap()->the_hole_value();
// on the stack. This includes functions which have optimized
// activations (including inlined functions) on the stack as the
// non-optimized code is needed for the lazy deoptimization.
for (JavaScriptFrameIterator it(isolate_); !it.done(); it.Advance()) {
JavaScriptFrame* frame = it.frame();
if (frame->is_optimized()) {
List<JSFunction*> functions(Compiler::kMaxInliningLevels + 1);
frame->GetFunctions(&functions);
for (int i = 0; i < functions.length(); i++) {
if (!functions[i]->shared()->code()->has_debug_break_slots()) {
active_functions.Add(Handle<JSFunction>(functions[i]));
}
}
} else if (frame->function()->IsJSFunction()) {
JSFunction* function = JSFunction::cast(frame->function());
ASSERT(frame->LookupCode()->kind() == Code::FUNCTION);
if (!frame->LookupCode()->has_debug_break_slots() ||
!function->shared()->code()->has_debug_break_slots()) {
active_functions.Add(Handle<JSFunction>(function));
}
}
}
// Sort the functions on the object pointer value to prepare for CollectActiveFunctionsFromThread(isolate_,
// the binary search below. isolate_->thread_local_top(),
active_functions.Sort(HandleObjectPointerCompare<JSFunction>); &active_functions,
active_code_marker);
ActiveFunctionsCollector active_functions_collector(&active_functions,
active_code_marker);
isolate_->thread_manager()->IterateArchivedThreads(
&active_functions_collector);
// Scan the heap for all non-optimized functions which has no // Scan the heap for all non-optimized functions which have no
// debug break slots. // debug break slots and are not active or inlined into an active
// function and mark them for lazy compilation.
HeapIterator iterator; HeapIterator iterator;
HeapObject* obj = NULL; HeapObject* obj = NULL;
while (((obj = iterator.next()) != NULL)) { while (((obj = iterator.next()) != NULL)) {
if (obj->IsJSFunction()) { if (obj->IsJSFunction()) {
JSFunction* function = JSFunction::cast(obj); JSFunction* function = JSFunction::cast(obj);
if (function->shared()->allows_lazy_compilation() && SharedFunctionInfo* shared = function->shared();
function->shared()->script()->IsScript() && if (shared->allows_lazy_compilation() &&
shared->script()->IsScript() &&
function->code()->kind() == Code::FUNCTION && function->code()->kind() == Code::FUNCTION &&
!function->code()->has_debug_break_slots()) { !function->code()->has_debug_break_slots() &&
bool has_activation = shared->code()->gc_metadata() != active_code_marker) {
SortedListBSearch<Handle<JSFunction> >( function->set_code(*lazy_compile);
active_functions, function->shared()->set_code(*lazy_compile);
Handle<JSFunction>(function),
HandleObjectPointerCompare<JSFunction>) != -1;
if (!has_activation) {
function->set_code(*lazy_compile);
function->shared()->set_code(*lazy_compile);
}
} }
} }
} }
}
// Now the non-GC scope is left, and the sorting of the functions // Clear gc_metadata field.
// in active_function is not ensured any more. The code below does for (int i = 0; i < active_functions.length(); i++) {
// not rely on it. Handle<JSFunction> function = active_functions[i];
function->shared()->code()->set_gc_metadata(Smi::FromInt(0));
}
}
// Now recompile all functions with activation frames and and // Now recompile all functions with activation frames and and
// patch the return address to run in the new compiled code. // patch the return address to run in the new compiled code.
for (int i = 0; i < active_functions.length(); i++) { for (int i = 0; i < active_functions.length(); i++) {
Handle<JSFunction> function = active_functions[i]; Handle<JSFunction> function = active_functions[i];
if (function->code()->kind() == Code::FUNCTION &&
function->code()->has_debug_break_slots()) {
// Nothing to do. Function code already had debug break slots.
continue;
}
Handle<SharedFunctionInfo> shared(function->shared()); Handle<SharedFunctionInfo> shared(function->shared());
// If recompilation is not possible just skip it. // If recompilation is not possible just skip it.
if (shared->is_toplevel() || if (shared->is_toplevel() ||
@ -1851,9 +1968,6 @@ void Debug::PrepareForBreakPoints() {
// Make sure that the shared full code is compiled with debug // Make sure that the shared full code is compiled with debug
// break slots. // break slots.
if (function->code() == *lazy_compile) {
function->set_code(shared->code());
}
if (!shared->code()->has_debug_break_slots()) { if (!shared->code()->has_debug_break_slots()) {
// Try to compile the full code with debug break slots. If it // Try to compile the full code with debug break slots. If it
// fails just keep the current code. // fails just keep the current code.
@ -1872,70 +1986,17 @@ void Debug::PrepareForBreakPoints() {
continue; continue;
} }
} }
Handle<Code> new_code(shared->code());
// Find the function and patch the return address.
for (JavaScriptFrameIterator it(isolate_); !it.done(); it.Advance()) {
JavaScriptFrame* frame = it.frame();
// If the current frame is for this function in its
// non-optimized form rewrite the return address to continue
// in the newly compiled full code with debug break slots.
if (!frame->is_optimized() &&
frame->function()->IsJSFunction() &&
frame->function() == *function) {
ASSERT(frame->LookupCode()->kind() == Code::FUNCTION);
Handle<Code> frame_code(frame->LookupCode());
if (frame_code->has_debug_break_slots()) continue;
intptr_t delta = frame->pc() - frame_code->instruction_start();
int debug_break_slot_count = 0;
int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT);
for (RelocIterator it(*new_code, mask); !it.done(); it.next()) {
// Check if the pc in the new code with debug break
// slots is before this slot.
RelocInfo* info = it.rinfo();
int debug_break_slot_bytes =
debug_break_slot_count * Assembler::kDebugBreakSlotLength;
intptr_t new_delta =
info->pc() -
new_code->instruction_start() -
debug_break_slot_bytes;
if (new_delta > delta) {
break;
}
// Passed a debug break slot in the full code with debug
// break slots.
debug_break_slot_count++;
}
int debug_break_slot_bytes =
debug_break_slot_count * Assembler::kDebugBreakSlotLength;
if (FLAG_trace_deopt) {
PrintF("Replacing code %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
"with %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
"for debugging, "
"changing pc from %08" V8PRIxPTR " to %08" V8PRIxPTR "\n",
reinterpret_cast<intptr_t>(
frame_code->instruction_start()),
reinterpret_cast<intptr_t>(
frame_code->instruction_start()) +
frame_code->instruction_size(),
frame_code->instruction_size(),
reinterpret_cast<intptr_t>(new_code->instruction_start()),
reinterpret_cast<intptr_t>(new_code->instruction_start()) +
new_code->instruction_size(),
new_code->instruction_size(),
reinterpret_cast<intptr_t>(frame->pc()),
reinterpret_cast<intptr_t>(new_code->instruction_start()) +
delta + debug_break_slot_bytes);
}
// Patch the return address to return into the code with // Keep function code in sync with shared function info.
// debug break slots. function->set_code(shared->code());
frame->set_pc(
new_code->instruction_start() + delta + debug_break_slot_bytes);
}
}
} }
RedirectActivationsToRecompiledCodeOnThread(isolate_,
isolate_->thread_local_top());
ActiveFunctionsRedirector active_functions_redirector;
isolate_->thread_manager()->IterateArchivedThreads(
&active_functions_redirector);
} }
} }

313
deps/v8/src/deoptimizer.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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -104,10 +104,27 @@ Deoptimizer* Deoptimizer::Grab(Isolate* isolate) {
return result; return result;
} }
int Deoptimizer::ConvertJSFrameIndexToFrameIndex(int jsframe_index) {
if (jsframe_index == 0) return 0;
int frame_index = 0;
while (jsframe_index >= 0) {
FrameDescription* frame = output_[frame_index];
if (frame->GetFrameType() == StackFrame::JAVA_SCRIPT) {
jsframe_index--;
}
frame_index++;
}
return frame_index - 1;
}
#ifdef ENABLE_DEBUGGER_SUPPORT #ifdef ENABLE_DEBUGGER_SUPPORT
DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame( DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame(
JavaScriptFrame* frame, JavaScriptFrame* frame,
int frame_index, int jsframe_index,
Isolate* isolate) { Isolate* isolate) {
ASSERT(isolate == Isolate::Current()); ASSERT(isolate == Isolate::Current());
ASSERT(frame->is_optimized()); ASSERT(frame->is_optimized());
@ -143,22 +160,40 @@ DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame(
// Create the GC safe output frame information and register it for GC // Create the GC safe output frame information and register it for GC
// handling. // handling.
ASSERT_LT(frame_index, deoptimizer->output_count()); ASSERT_LT(jsframe_index, deoptimizer->jsframe_count());
// Convert JS frame index into frame index.
int frame_index = deoptimizer->ConvertJSFrameIndexToFrameIndex(jsframe_index);
bool has_arguments_adaptor =
frame_index > 0 &&
deoptimizer->output_[frame_index - 1]->GetFrameType() ==
StackFrame::ARGUMENTS_ADAPTOR;
DeoptimizedFrameInfo* info = DeoptimizedFrameInfo* info =
new DeoptimizedFrameInfo(deoptimizer, frame_index); new DeoptimizedFrameInfo(deoptimizer, frame_index, has_arguments_adaptor);
isolate->deoptimizer_data()->deoptimized_frame_info_ = info; isolate->deoptimizer_data()->deoptimized_frame_info_ = info;
// Get the "simulated" top and size for the requested frame. // Get the "simulated" top and size for the requested frame.
Address top = FrameDescription* parameters_frame =
reinterpret_cast<Address>(deoptimizer->output_[frame_index]->GetTop()); deoptimizer->output_[
uint32_t size = deoptimizer->output_[frame_index]->GetFrameSize(); has_arguments_adaptor ? (frame_index - 1) : frame_index];
uint32_t parameters_size = (info->parameters_count() + 1) * kPointerSize;
Address parameters_top = reinterpret_cast<Address>(
parameters_frame->GetTop() + (parameters_frame->GetFrameSize() -
parameters_size));
uint32_t expressions_size = info->expression_count() * kPointerSize;
Address expressions_top = reinterpret_cast<Address>(
deoptimizer->output_[frame_index]->GetTop());
// Done with the GC-unsafe frame descriptions. This re-enables allocation. // Done with the GC-unsafe frame descriptions. This re-enables allocation.
deoptimizer->DeleteFrameDescriptions(); deoptimizer->DeleteFrameDescriptions();
// Allocate a heap number for the doubles belonging to this frame. // Allocate a heap number for the doubles belonging to this frame.
deoptimizer->MaterializeHeapNumbersForDebuggerInspectableFrame( deoptimizer->MaterializeHeapNumbersForDebuggerInspectableFrame(
top, size, info); parameters_top, parameters_size, expressions_top, expressions_size, info);
// Finished using the deoptimizer instance. // Finished using the deoptimizer instance.
delete deoptimizer; delete deoptimizer;
@ -313,6 +348,7 @@ Deoptimizer::Deoptimizer(Isolate* isolate,
fp_to_sp_delta_(fp_to_sp_delta), fp_to_sp_delta_(fp_to_sp_delta),
input_(NULL), input_(NULL),
output_count_(0), output_count_(0),
jsframe_count_(0),
output_(NULL), output_(NULL),
frame_alignment_marker_(isolate->heap()->frame_alignment_marker()), frame_alignment_marker_(isolate->heap()->frame_alignment_marker()),
has_alignment_padding_(0), has_alignment_padding_(0),
@ -377,9 +413,7 @@ Deoptimizer::Deoptimizer(Isolate* isolate,
ASSERT(HEAP->allow_allocation(false)); ASSERT(HEAP->allow_allocation(false));
unsigned size = ComputeInputFrameSize(); unsigned size = ComputeInputFrameSize();
input_ = new(size) FrameDescription(size, function); input_ = new(size) FrameDescription(size, function);
#ifdef DEBUG input_->SetFrameType(StackFrame::JAVA_SCRIPT);
input_->SetKind(Code::OPTIMIZED_FUNCTION);
#endif
} }
@ -515,6 +549,7 @@ void Deoptimizer::DoComputeOutputFrames() {
// Read the number of output frames and allocate an array for their // Read the number of output frames and allocate an array for their
// descriptions. // descriptions.
int count = iterator.Next(); int count = iterator.Next();
iterator.Next(); // Drop JS frames count.
ASSERT(output_ == NULL); ASSERT(output_ == NULL);
output_ = new FrameDescription*[count]; output_ = new FrameDescription*[count];
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
@ -524,7 +559,21 @@ void Deoptimizer::DoComputeOutputFrames() {
// Translate each output frame. // Translate each output frame.
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
DoComputeFrame(&iterator, i); // Read the ast node id, function, and frame height for this output frame.
Translation::Opcode opcode =
static_cast<Translation::Opcode>(iterator.Next());
switch (opcode) {
case Translation::JS_FRAME:
DoComputeJSFrame(&iterator, i);
jsframe_count_++;
break;
case Translation::ARGUMENTS_ADAPTOR_FRAME:
DoComputeArgumentsAdaptorFrame(&iterator, i);
break;
default:
UNREACHABLE();
break;
}
} }
// Print some helpful diagnostic information. // Print some helpful diagnostic information.
@ -565,39 +614,52 @@ void Deoptimizer::MaterializeHeapNumbers() {
#ifdef ENABLE_DEBUGGER_SUPPORT #ifdef ENABLE_DEBUGGER_SUPPORT
void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame( void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame(
Address top, uint32_t size, DeoptimizedFrameInfo* info) { Address parameters_top,
uint32_t parameters_size,
Address expressions_top,
uint32_t expressions_size,
DeoptimizedFrameInfo* info) {
ASSERT_EQ(DEBUGGER, bailout_type_); ASSERT_EQ(DEBUGGER, bailout_type_);
Address parameters_bottom = parameters_top + parameters_size;
Address expressions_bottom = expressions_top + expressions_size;
for (int i = 0; i < deferred_heap_numbers_.length(); i++) { for (int i = 0; i < deferred_heap_numbers_.length(); i++) {
HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i]; HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i];
// Check of the heap number to materialize actually belong to the frame // Check of the heap number to materialize actually belong to the frame
// being extracted. // being extracted.
Address slot = d.slot_address(); Address slot = d.slot_address();
if (top <= slot && slot < top + size) { if (parameters_top <= slot && slot < parameters_bottom) {
Handle<Object> num = isolate_->factory()->NewNumber(d.value()); Handle<Object> num = isolate_->factory()->NewNumber(d.value());
// Calculate the index with the botton of the expression stack
// at index 0, and the fixed part (including incoming arguments) int index = (info->parameters_count() - 1) -
// at negative indexes. static_cast<int>(slot - parameters_top) / kPointerSize;
int index = static_cast<int>(
info->expression_count_ - (slot - top) / kPointerSize - 1);
if (FLAG_trace_deopt) { if (FLAG_trace_deopt) {
PrintF("Materializing a new heap number %p [%e] in slot %p" PrintF("Materializing a new heap number %p [%e] in slot %p"
"for stack index %d\n", "for parameter slot #%d\n",
reinterpret_cast<void*>(*num), reinterpret_cast<void*>(*num),
d.value(), d.value(),
d.slot_address(), d.slot_address(),
index); index);
} }
if (index >=0) {
info->SetExpression(index, *num); info->SetParameter(index, *num);
} else { } else if (expressions_top <= slot && slot < expressions_bottom) {
// Calculate parameter index subtracting one for the receiver. Handle<Object> num = isolate_->factory()->NewNumber(d.value());
int parameter_index =
index + int index = info->expression_count() - 1 -
static_cast<int>(size) / kPointerSize - static_cast<int>(slot - expressions_top) / kPointerSize;
info->expression_count_ - 1;
info->SetParameter(parameter_index, *num); if (FLAG_trace_deopt) {
PrintF("Materializing a new heap number %p [%e] in slot %p"
"for expression slot #%d\n",
reinterpret_cast<void*>(*num),
d.value(),
d.slot_address(),
index);
} }
info->SetExpression(index, *num);
} }
} }
} }
@ -622,7 +684,8 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
switch (opcode) { switch (opcode) {
case Translation::BEGIN: case Translation::BEGIN:
case Translation::FRAME: case Translation::JS_FRAME:
case Translation::ARGUMENTS_ADAPTOR_FRAME:
case Translation::DUPLICATE: case Translation::DUPLICATE:
UNREACHABLE(); UNREACHABLE();
return; return;
@ -691,7 +754,7 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
case Translation::STACK_SLOT: { case Translation::STACK_SLOT: {
int input_slot_index = iterator->Next(); int input_slot_index = iterator->Next();
unsigned input_offset = unsigned input_offset =
input_->GetOffsetFromSlotIndex(this, input_slot_index); input_->GetOffsetFromSlotIndex(input_slot_index);
intptr_t input_value = input_->GetFrameSlot(input_offset); intptr_t input_value = input_->GetFrameSlot(input_offset);
if (FLAG_trace_deopt) { if (FLAG_trace_deopt) {
PrintF(" 0x%08" V8PRIxPTR ": ", PrintF(" 0x%08" V8PRIxPTR ": ",
@ -710,7 +773,7 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
case Translation::INT32_STACK_SLOT: { case Translation::INT32_STACK_SLOT: {
int input_slot_index = iterator->Next(); int input_slot_index = iterator->Next();
unsigned input_offset = unsigned input_offset =
input_->GetOffsetFromSlotIndex(this, input_slot_index); input_->GetOffsetFromSlotIndex(input_slot_index);
intptr_t value = input_->GetFrameSlot(input_offset); intptr_t value = input_->GetFrameSlot(input_offset);
bool is_smi = Smi::IsValid(value); bool is_smi = Smi::IsValid(value);
if (FLAG_trace_deopt) { if (FLAG_trace_deopt) {
@ -739,7 +802,7 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
case Translation::DOUBLE_STACK_SLOT: { case Translation::DOUBLE_STACK_SLOT: {
int input_slot_index = iterator->Next(); int input_slot_index = iterator->Next();
unsigned input_offset = unsigned input_offset =
input_->GetOffsetFromSlotIndex(this, input_slot_index); input_->GetOffsetFromSlotIndex(input_slot_index);
double value = input_->GetDoubleFrameSlot(input_offset); double value = input_->GetDoubleFrameSlot(input_offset);
if (FLAG_trace_deopt) { if (FLAG_trace_deopt) {
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- %e ; [esp + %d]\n", PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- %e ; [esp + %d]\n",
@ -808,7 +871,8 @@ bool Deoptimizer::DoOsrTranslateCommand(TranslationIterator* iterator,
switch (opcode) { switch (opcode) {
case Translation::BEGIN: case Translation::BEGIN:
case Translation::FRAME: case Translation::JS_FRAME:
case Translation::ARGUMENTS_ADAPTOR_FRAME:
case Translation::DUPLICATE: case Translation::DUPLICATE:
UNREACHABLE(); // Malformed input. UNREACHABLE(); // Malformed input.
return false; return false;
@ -871,7 +935,7 @@ bool Deoptimizer::DoOsrTranslateCommand(TranslationIterator* iterator,
case Translation::STACK_SLOT: { case Translation::STACK_SLOT: {
int output_index = iterator->Next(); int output_index = iterator->Next();
unsigned output_offset = unsigned output_offset =
output->GetOffsetFromSlotIndex(this, output_index); output->GetOffsetFromSlotIndex(output_index);
if (FLAG_trace_osr) { if (FLAG_trace_osr) {
PrintF(" [sp + %d] <- 0x%08" V8PRIxPTR " ; [sp + %d] ", PrintF(" [sp + %d] <- 0x%08" V8PRIxPTR " ; [sp + %d] ",
output_offset, output_offset,
@ -890,7 +954,7 @@ bool Deoptimizer::DoOsrTranslateCommand(TranslationIterator* iterator,
int output_index = iterator->Next(); int output_index = iterator->Next();
unsigned output_offset = unsigned output_offset =
output->GetOffsetFromSlotIndex(this, output_index); output->GetOffsetFromSlotIndex(output_index);
int int32_value = input_object->IsSmi() int int32_value = input_object->IsSmi()
? Smi::cast(input_object)->value() ? Smi::cast(input_object)->value()
: DoubleToInt32(input_object->Number()); : DoubleToInt32(input_object->Number());
@ -922,7 +986,7 @@ bool Deoptimizer::DoOsrTranslateCommand(TranslationIterator* iterator,
int output_index = iterator->Next(); int output_index = iterator->Next();
unsigned output_offset = unsigned output_offset =
output->GetOffsetFromSlotIndex(this, output_index); output->GetOffsetFromSlotIndex(output_index);
double double_value = input_object->Number(); double double_value = input_object->Number();
uint64_t int_value = BitCast<uint64_t, double>(double_value); uint64_t int_value = BitCast<uint64_t, double>(double_value);
int32_t lower = static_cast<int32_t>(int_value); int32_t lower = static_cast<int32_t>(int_value);
@ -1033,8 +1097,8 @@ unsigned Deoptimizer::ComputeInputFrameSize() const {
unsigned Deoptimizer::ComputeFixedSize(JSFunction* function) const { unsigned Deoptimizer::ComputeFixedSize(JSFunction* function) const {
// The fixed part of the frame consists of the return address, frame // The fixed part of the frame consists of the return address, frame
// pointer, function, context, and all the incoming arguments. // pointer, function, context, and all the incoming arguments.
static const unsigned kFixedSlotSize = 4 * kPointerSize; return ComputeIncomingArgumentSize(function) +
return ComputeIncomingArgumentSize(function) + kFixedSlotSize; StandardFrameConstants::kFixedFrameSize;
} }
@ -1154,49 +1218,62 @@ FrameDescription::FrameDescription(uint32_t frame_size,
} }
unsigned FrameDescription::GetOffsetFromSlotIndex(Deoptimizer* deoptimizer, int FrameDescription::ComputeFixedSize() {
int slot_index) { return StandardFrameConstants::kFixedFrameSize +
(ComputeParametersCount() + 1) * kPointerSize;
}
unsigned FrameDescription::GetOffsetFromSlotIndex(int slot_index) {
if (slot_index >= 0) { if (slot_index >= 0) {
// Local or spill slots. Skip the fixed part of the frame // Local or spill slots. Skip the fixed part of the frame
// including all arguments. // including all arguments.
unsigned base = unsigned base = GetFrameSize() - ComputeFixedSize();
GetFrameSize() - deoptimizer->ComputeFixedSize(GetFunction());
return base - ((slot_index + 1) * kPointerSize); return base - ((slot_index + 1) * kPointerSize);
} else { } else {
// Incoming parameter. // Incoming parameter.
unsigned base = GetFrameSize() - int arg_size = (ComputeParametersCount() + 1) * kPointerSize;
deoptimizer->ComputeIncomingArgumentSize(GetFunction()); unsigned base = GetFrameSize() - arg_size;
return base - ((slot_index + 1) * kPointerSize); return base - ((slot_index + 1) * kPointerSize);
} }
} }
int FrameDescription::ComputeParametersCount() { int FrameDescription::ComputeParametersCount() {
return function_->shared()->formal_parameter_count(); switch (type_) {
case StackFrame::JAVA_SCRIPT:
return function_->shared()->formal_parameter_count();
case StackFrame::ARGUMENTS_ADAPTOR: {
// Last slot contains number of incomming arguments as a smi.
// Can't use GetExpression(0) because it would cause infinite recursion.
return reinterpret_cast<Smi*>(*GetFrameSlotPointer(0))->value();
}
default:
UNREACHABLE();
return 0;
}
} }
Object* FrameDescription::GetParameter(Deoptimizer* deoptimizer, int index) { Object* FrameDescription::GetParameter(int index) {
ASSERT_EQ(Code::FUNCTION, kind_);
ASSERT(index >= 0); ASSERT(index >= 0);
ASSERT(index < ComputeParametersCount()); ASSERT(index < ComputeParametersCount());
// The slot indexes for incoming arguments are negative. // The slot indexes for incoming arguments are negative.
unsigned offset = GetOffsetFromSlotIndex(deoptimizer, unsigned offset = GetOffsetFromSlotIndex(index - ComputeParametersCount());
index - ComputeParametersCount());
return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset)); return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset));
} }
unsigned FrameDescription::GetExpressionCount(Deoptimizer* deoptimizer) { unsigned FrameDescription::GetExpressionCount() {
ASSERT_EQ(Code::FUNCTION, kind_); ASSERT_EQ(StackFrame::JAVA_SCRIPT, type_);
unsigned size = GetFrameSize() - deoptimizer->ComputeFixedSize(GetFunction()); unsigned size = GetFrameSize() - ComputeFixedSize();
return size / kPointerSize; return size / kPointerSize;
} }
Object* FrameDescription::GetExpression(Deoptimizer* deoptimizer, int index) { Object* FrameDescription::GetExpression(int index) {
ASSERT_EQ(Code::FUNCTION, kind_); ASSERT_EQ(StackFrame::JAVA_SCRIPT, type_);
unsigned offset = GetOffsetFromSlotIndex(deoptimizer, index); unsigned offset = GetOffsetFromSlotIndex(index);
return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset)); return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset));
} }
@ -1242,8 +1319,15 @@ Handle<ByteArray> TranslationBuffer::CreateByteArray() {
} }
void Translation::BeginFrame(int node_id, int literal_id, unsigned height) { void Translation::BeginArgumentsAdaptorFrame(int literal_id, unsigned height) {
buffer_->Add(FRAME); buffer_->Add(ARGUMENTS_ADAPTOR_FRAME);
buffer_->Add(literal_id);
buffer_->Add(height);
}
void Translation::BeginJSFrame(int node_id, int literal_id, unsigned height) {
buffer_->Add(JS_FRAME);
buffer_->Add(node_id); buffer_->Add(node_id);
buffer_->Add(literal_id); buffer_->Add(literal_id);
buffer_->Add(height); buffer_->Add(height);
@ -1307,7 +1391,6 @@ int Translation::NumberOfOperandsFor(Opcode opcode) {
case ARGUMENTS_OBJECT: case ARGUMENTS_OBJECT:
case DUPLICATE: case DUPLICATE:
return 0; return 0;
case BEGIN:
case REGISTER: case REGISTER:
case INT32_REGISTER: case INT32_REGISTER:
case DOUBLE_REGISTER: case DOUBLE_REGISTER:
@ -1316,7 +1399,10 @@ int Translation::NumberOfOperandsFor(Opcode opcode) {
case DOUBLE_STACK_SLOT: case DOUBLE_STACK_SLOT:
case LITERAL: case LITERAL:
return 1; return 1;
case FRAME: case BEGIN:
case ARGUMENTS_ADAPTOR_FRAME:
return 2;
case JS_FRAME:
return 3; return 3;
} }
UNREACHABLE(); UNREACHABLE();
@ -1330,8 +1416,10 @@ const char* Translation::StringFor(Opcode opcode) {
switch (opcode) { switch (opcode) {
case BEGIN: case BEGIN:
return "BEGIN"; return "BEGIN";
case FRAME: case JS_FRAME:
return "FRAME"; return "JS_FRAME";
case ARGUMENTS_ADAPTOR_FRAME:
return "ARGUMENTS_ADAPTOR_FRAME";
case REGISTER: case REGISTER:
return "REGISTER"; return "REGISTER";
case INT32_REGISTER: case INT32_REGISTER:
@ -1385,7 +1473,8 @@ SlotRef SlotRef::ComputeSlotForNextArgument(TranslationIterator* iterator,
switch (opcode) { switch (opcode) {
case Translation::BEGIN: case Translation::BEGIN:
case Translation::FRAME: case Translation::JS_FRAME:
case Translation::ARGUMENTS_ADAPTOR_FRAME:
// Peeled off before getting here. // Peeled off before getting here.
break; break;
@ -1431,9 +1520,27 @@ SlotRef SlotRef::ComputeSlotForNextArgument(TranslationIterator* iterator,
} }
void SlotRef::ComputeSlotMappingForArguments(JavaScriptFrame* frame, void SlotRef::ComputeSlotsForArguments(Vector<SlotRef>* args_slots,
int inlined_frame_index, TranslationIterator* it,
Vector<SlotRef>* args_slots) { DeoptimizationInputData* data,
JavaScriptFrame* frame) {
// Process the translation commands for the arguments.
// Skip the translation command for the receiver.
it->Skip(Translation::NumberOfOperandsFor(
static_cast<Translation::Opcode>(it->Next())));
// Compute slots for arguments.
for (int i = 0; i < args_slots->length(); ++i) {
(*args_slots)[i] = ComputeSlotForNextArgument(it, data, frame);
}
}
Vector<SlotRef> SlotRef::ComputeSlotMappingForArguments(
JavaScriptFrame* frame,
int inlined_jsframe_index,
int formal_parameter_count) {
AssertNoAllocation no_gc; AssertNoAllocation no_gc;
int deopt_index = AstNode::kNoNumber; int deopt_index = AstNode::kNoNumber;
DeoptimizationInputData* data = DeoptimizationInputData* data =
@ -1442,51 +1549,73 @@ void SlotRef::ComputeSlotMappingForArguments(JavaScriptFrame* frame,
data->TranslationIndex(deopt_index)->value()); data->TranslationIndex(deopt_index)->value());
Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
ASSERT(opcode == Translation::BEGIN); ASSERT(opcode == Translation::BEGIN);
int frame_count = it.Next(); it.Next(); // Drop frame count.
USE(frame_count); int jsframe_count = it.Next();
ASSERT(frame_count > inlined_frame_index); USE(jsframe_count);
int frames_to_skip = inlined_frame_index; ASSERT(jsframe_count > inlined_jsframe_index);
int jsframes_to_skip = inlined_jsframe_index;
while (true) { while (true) {
opcode = static_cast<Translation::Opcode>(it.Next()); opcode = static_cast<Translation::Opcode>(it.Next());
// Skip over operands to advance to the next opcode. if (opcode == Translation::ARGUMENTS_ADAPTOR_FRAME) {
it.Skip(Translation::NumberOfOperandsFor(opcode)); if (jsframes_to_skip == 0) {
if (opcode == Translation::FRAME) { ASSERT(Translation::NumberOfOperandsFor(opcode) == 2);
if (frames_to_skip == 0) {
it.Skip(1); // literal id
int height = it.Next();
// We reached the arguments adaptor frame corresponding to the
// inlined function in question. Number of arguments is height - 1.
Vector<SlotRef> args_slots =
Vector<SlotRef>::New(height - 1); // Minus receiver.
ComputeSlotsForArguments(&args_slots, &it, data, frame);
return args_slots;
}
} else if (opcode == Translation::JS_FRAME) {
if (jsframes_to_skip == 0) {
// Skip over operands to advance to the next opcode.
it.Skip(Translation::NumberOfOperandsFor(opcode));
// We reached the frame corresponding to the inlined function // We reached the frame corresponding to the inlined function
// in question. Process the translation commands for the // in question. Process the translation commands for the
// arguments. // arguments. Number of arguments is equal to the number of
// // format parameter count.
// Skip the translation command for the receiver. Vector<SlotRef> args_slots =
it.Skip(Translation::NumberOfOperandsFor( Vector<SlotRef>::New(formal_parameter_count);
static_cast<Translation::Opcode>(it.Next()))); ComputeSlotsForArguments(&args_slots, &it, data, frame);
// Compute slots for arguments. return args_slots;
for (int i = 0; i < args_slots->length(); ++i) {
(*args_slots)[i] = ComputeSlotForNextArgument(&it, data, frame);
}
return;
} }
frames_to_skip--; jsframes_to_skip--;
} }
// Skip over operands to advance to the next opcode.
it.Skip(Translation::NumberOfOperandsFor(opcode));
} }
UNREACHABLE(); UNREACHABLE();
return Vector<SlotRef>();
} }
#ifdef ENABLE_DEBUGGER_SUPPORT #ifdef ENABLE_DEBUGGER_SUPPORT
DeoptimizedFrameInfo::DeoptimizedFrameInfo( DeoptimizedFrameInfo::DeoptimizedFrameInfo(
Deoptimizer* deoptimizer, int frame_index) { Deoptimizer* deoptimizer, int frame_index, bool has_arguments_adaptor) {
FrameDescription* output_frame = deoptimizer->output_[frame_index]; FrameDescription* output_frame = deoptimizer->output_[frame_index];
SetFunction(output_frame->GetFunction()); SetFunction(output_frame->GetFunction());
expression_count_ = output_frame->GetExpressionCount(deoptimizer); expression_count_ = output_frame->GetExpressionCount();
expression_stack_ = new Object*[expression_count_];
for (int i = 0; i < expression_count_; i++) {
SetExpression(i, output_frame->GetExpression(i));
}
if (has_arguments_adaptor) {
output_frame = deoptimizer->output_[frame_index - 1];
ASSERT(output_frame->GetFrameType() == StackFrame::ARGUMENTS_ADAPTOR);
}
parameters_count_ = output_frame->ComputeParametersCount(); parameters_count_ = output_frame->ComputeParametersCount();
parameters_ = new Object*[parameters_count_]; parameters_ = new Object*[parameters_count_];
for (int i = 0; i < parameters_count_; i++) { for (int i = 0; i < parameters_count_; i++) {
SetParameter(i, output_frame->GetParameter(deoptimizer, i)); SetParameter(i, output_frame->GetParameter(i));
}
expression_stack_ = new Object*[expression_count_];
for (int i = 0; i < expression_count_; i++) {
SetExpression(i, output_frame->GetExpression(deoptimizer, i));
} }
} }

68
deps/v8/src/deoptimizer.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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -119,6 +119,9 @@ class Deoptimizer : public Malloced {
int output_count() const { return output_count_; } int output_count() const { return output_count_; }
// Number of created JS frames. Not all created frames are necessarily JS.
int jsframe_count() const { return jsframe_count_; }
static Deoptimizer* New(JSFunction* function, static Deoptimizer* New(JSFunction* function,
BailoutType type, BailoutType type,
unsigned bailout_id, unsigned bailout_id,
@ -131,7 +134,7 @@ class Deoptimizer : public Malloced {
// The returned object with information on the optimized frame needs to be // The returned object with information on the optimized frame needs to be
// freed before another one can be generated. // freed before another one can be generated.
static DeoptimizedFrameInfo* DebuggerInspectableFrame(JavaScriptFrame* frame, static DeoptimizedFrameInfo* DebuggerInspectableFrame(JavaScriptFrame* frame,
int frame_index, int jsframe_index,
Isolate* isolate); Isolate* isolate);
static void DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info, static void DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info,
Isolate* isolate); Isolate* isolate);
@ -196,7 +199,11 @@ class Deoptimizer : public Malloced {
void MaterializeHeapNumbers(); void MaterializeHeapNumbers();
#ifdef ENABLE_DEBUGGER_SUPPORT #ifdef ENABLE_DEBUGGER_SUPPORT
void MaterializeHeapNumbersForDebuggerInspectableFrame( void MaterializeHeapNumbersForDebuggerInspectableFrame(
Address top, uint32_t size, DeoptimizedFrameInfo* info); Address parameters_top,
uint32_t parameters_size,
Address expressions_top,
uint32_t expressions_size,
DeoptimizedFrameInfo* info);
#endif #endif
static void ComputeOutputFrames(Deoptimizer* deoptimizer); static void ComputeOutputFrames(Deoptimizer* deoptimizer);
@ -257,8 +264,10 @@ class Deoptimizer : public Malloced {
int count_; int count_;
}; };
int ConvertJSFrameIndexToFrameIndex(int jsframe_index);
private: private:
static const int kNumberOfEntries = 4096; static const int kNumberOfEntries = 8192;
Deoptimizer(Isolate* isolate, Deoptimizer(Isolate* isolate,
JSFunction* function, JSFunction* function,
@ -271,7 +280,9 @@ class Deoptimizer : public Malloced {
void DoComputeOutputFrames(); void DoComputeOutputFrames();
void DoComputeOsrOutputFrame(); void DoComputeOsrOutputFrame();
void DoComputeFrame(TranslationIterator* iterator, int frame_index); void DoComputeJSFrame(TranslationIterator* iterator, int frame_index);
void DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator,
int frame_index);
void DoTranslateCommand(TranslationIterator* iterator, void DoTranslateCommand(TranslationIterator* iterator,
int frame_index, int frame_index,
unsigned output_offset); unsigned output_offset);
@ -319,6 +330,8 @@ class Deoptimizer : public Malloced {
FrameDescription* input_; FrameDescription* input_;
// Number of output frames. // Number of output frames.
int output_count_; int output_count_;
// Number of output js frames.
int jsframe_count_;
// Array of output frame descriptions. // Array of output frame descriptions.
FrameDescription** output_; FrameDescription** output_;
@ -362,7 +375,7 @@ class FrameDescription {
JSFunction* GetFunction() const { return function_; } JSFunction* GetFunction() const { return function_; }
unsigned GetOffsetFromSlotIndex(Deoptimizer* deoptimizer, int slot_index); unsigned GetOffsetFromSlotIndex(int slot_index);
intptr_t GetFrameSlot(unsigned offset) { intptr_t GetFrameSlot(unsigned offset) {
return *GetFrameSlotPointer(offset); return *GetFrameSlotPointer(offset);
@ -423,22 +436,20 @@ class FrameDescription {
void SetContinuation(intptr_t pc) { continuation_ = pc; } void SetContinuation(intptr_t pc) { continuation_ = pc; }
#ifdef DEBUG StackFrame::Type GetFrameType() const { return type_; }
Code::Kind GetKind() const { return kind_; } void SetFrameType(StackFrame::Type type) { type_ = type; }
void SetKind(Code::Kind kind) { kind_ = kind; }
#endif
// Get the incoming arguments count. // Get the incoming arguments count.
int ComputeParametersCount(); int ComputeParametersCount();
// Get a parameter value for an unoptimized frame. // Get a parameter value for an unoptimized frame.
Object* GetParameter(Deoptimizer* deoptimizer, int index); Object* GetParameter(int index);
// Get the expression stack height for a unoptimized frame. // Get the expression stack height for a unoptimized frame.
unsigned GetExpressionCount(Deoptimizer* deoptimizer); unsigned GetExpressionCount();
// Get the expression stack value for an unoptimized frame. // Get the expression stack value for an unoptimized frame.
Object* GetExpression(Deoptimizer* deoptimizer, int index); Object* GetExpression(int index);
static int registers_offset() { static int registers_offset() {
return OFFSET_OF(FrameDescription, registers_); return OFFSET_OF(FrameDescription, registers_);
@ -481,6 +492,7 @@ class FrameDescription {
intptr_t top_; intptr_t top_;
intptr_t pc_; intptr_t pc_;
intptr_t fp_; intptr_t fp_;
StackFrame::Type type_;
Smi* state_; Smi* state_;
#ifdef DEBUG #ifdef DEBUG
Code::Kind kind_; Code::Kind kind_;
@ -499,6 +511,8 @@ class FrameDescription {
return reinterpret_cast<intptr_t*>( return reinterpret_cast<intptr_t*>(
reinterpret_cast<Address>(this) + frame_content_offset() + offset); reinterpret_cast<Address>(this) + frame_content_offset() + offset);
} }
int ComputeFixedSize();
}; };
@ -541,7 +555,8 @@ class Translation BASE_EMBEDDED {
public: public:
enum Opcode { enum Opcode {
BEGIN, BEGIN,
FRAME, JS_FRAME,
ARGUMENTS_ADAPTOR_FRAME,
REGISTER, REGISTER,
INT32_REGISTER, INT32_REGISTER,
DOUBLE_REGISTER, DOUBLE_REGISTER,
@ -556,17 +571,19 @@ class Translation BASE_EMBEDDED {
DUPLICATE DUPLICATE
}; };
Translation(TranslationBuffer* buffer, int frame_count) Translation(TranslationBuffer* buffer, int frame_count, int jsframe_count)
: buffer_(buffer), : buffer_(buffer),
index_(buffer->CurrentIndex()) { index_(buffer->CurrentIndex()) {
buffer_->Add(BEGIN); buffer_->Add(BEGIN);
buffer_->Add(frame_count); buffer_->Add(frame_count);
buffer_->Add(jsframe_count);
} }
int index() const { return index_; } int index() const { return index_; }
// Commands. // Commands.
void BeginFrame(int node_id, int literal_id, unsigned height); void BeginJSFrame(int node_id, int literal_id, unsigned height);
void BeginArgumentsAdaptorFrame(int literal_id, unsigned height);
void StoreRegister(Register reg); void StoreRegister(Register reg);
void StoreInt32Register(Register reg); void StoreInt32Register(Register reg);
void StoreDoubleRegister(DoubleRegister reg); void StoreDoubleRegister(DoubleRegister reg);
@ -656,9 +673,10 @@ class SlotRef BASE_EMBEDDED {
} }
} }
static void ComputeSlotMappingForArguments(JavaScriptFrame* frame, static Vector<SlotRef> ComputeSlotMappingForArguments(
int inlined_frame_index, JavaScriptFrame* frame,
Vector<SlotRef>* args_slots); int inlined_frame_index,
int formal_parameter_count);
private: private:
Address addr_; Address addr_;
@ -678,6 +696,12 @@ class SlotRef BASE_EMBEDDED {
static SlotRef ComputeSlotForNextArgument(TranslationIterator* iterator, static SlotRef ComputeSlotForNextArgument(TranslationIterator* iterator,
DeoptimizationInputData* data, DeoptimizationInputData* data,
JavaScriptFrame* frame); JavaScriptFrame* frame);
static void ComputeSlotsForArguments(
Vector<SlotRef>* args_slots,
TranslationIterator* iterator,
DeoptimizationInputData* data,
JavaScriptFrame* frame);
}; };
@ -686,9 +710,13 @@ class SlotRef BASE_EMBEDDED {
// needs to inspect a frame that is part of an optimized frame. The // needs to inspect a frame that is part of an optimized frame. The
// internally used FrameDescription objects are not GC safe so for use // internally used FrameDescription objects are not GC safe so for use
// by the debugger frame information is copied to an object of this type. // by the debugger frame information is copied to an object of this type.
// Represents parameters in unadapted form so their number might mismatch
// formal parameter count.
class DeoptimizedFrameInfo : public Malloced { class DeoptimizedFrameInfo : public Malloced {
public: public:
DeoptimizedFrameInfo(Deoptimizer* deoptimizer, int frame_index); DeoptimizedFrameInfo(Deoptimizer* deoptimizer,
int frame_index,
bool has_arguments_adaptor);
virtual ~DeoptimizedFrameInfo(); virtual ~DeoptimizedFrameInfo();
// GC support. // GC support.

25
deps/v8/src/frames.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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -813,17 +813,18 @@ void OptimizedFrame::Summarize(List<FrameSummary>* frames) {
data->TranslationIndex(deopt_index)->value()); data->TranslationIndex(deopt_index)->value());
Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
ASSERT(opcode == Translation::BEGIN); ASSERT(opcode == Translation::BEGIN);
int frame_count = it.Next(); it.Next(); // Drop frame count.
int jsframe_count = it.Next();
// We create the summary in reverse order because the frames // We create the summary in reverse order because the frames
// in the deoptimization translation are ordered bottom-to-top. // in the deoptimization translation are ordered bottom-to-top.
int i = frame_count; int i = jsframe_count;
while (i > 0) { while (i > 0) {
opcode = static_cast<Translation::Opcode>(it.Next()); opcode = static_cast<Translation::Opcode>(it.Next());
if (opcode == Translation::FRAME) { if (opcode == Translation::JS_FRAME) {
// We don't inline constructor calls, so only the first, outermost // We don't inline constructor calls, so only the first, outermost
// frame can be a constructor frame in case of inlining. // frame can be a constructor frame in case of inlining.
bool is_constructor = (i == frame_count) && IsConstructor(); bool is_constructor = (i == jsframe_count) && IsConstructor();
i--; i--;
int ast_id = it.Next(); int ast_id = it.Next();
@ -918,8 +919,9 @@ int OptimizedFrame::GetInlineCount() {
Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
ASSERT(opcode == Translation::BEGIN); ASSERT(opcode == Translation::BEGIN);
USE(opcode); USE(opcode);
int frame_count = it.Next(); it.Next(); // Drop frame count.
return frame_count; int jsframe_count = it.Next();
return jsframe_count;
} }
@ -934,14 +936,15 @@ void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) {
data->TranslationIndex(deopt_index)->value()); data->TranslationIndex(deopt_index)->value());
Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
ASSERT(opcode == Translation::BEGIN); ASSERT(opcode == Translation::BEGIN);
int frame_count = it.Next(); it.Next(); // Drop frame count.
int jsframe_count = it.Next();
// We insert the frames in reverse order because the frames // We insert the frames in reverse order because the frames
// in the deoptimization translation are ordered bottom-to-top. // in the deoptimization translation are ordered bottom-to-top.
while (frame_count > 0) { while (jsframe_count > 0) {
opcode = static_cast<Translation::Opcode>(it.Next()); opcode = static_cast<Translation::Opcode>(it.Next());
if (opcode == Translation::FRAME) { if (opcode == Translation::JS_FRAME) {
frame_count--; jsframe_count--;
it.Next(); // Skip ast id. it.Next(); // Skip ast id.
int function_id = it.Next(); int function_id = it.Next();
it.Next(); // Skip height. it.Next(); // Skip height.

14
deps/v8/src/full-codegen.cc

@ -370,12 +370,14 @@ void FullCodeGenerator::PrepareForBailoutForId(unsigned id, State state) {
StateField::encode(state) | PcField::encode(masm_->pc_offset()); StateField::encode(state) | PcField::encode(masm_->pc_offset());
BailoutEntry entry = { id, pc_and_state }; BailoutEntry entry = { id, pc_and_state };
#ifdef DEBUG #ifdef DEBUG
// Assert that we don't have multiple bailout entries for the same node. if (FLAG_enable_slow_asserts) {
for (int i = 0; i < bailout_entries_.length(); i++) { // Assert that we don't have multiple bailout entries for the same node.
if (bailout_entries_.at(i).id == entry.id) { for (int i = 0; i < bailout_entries_.length(); i++) {
AstPrinter printer; if (bailout_entries_.at(i).id == entry.id) {
PrintF("%s", printer.PrintProgram(info_->function())); AstPrinter printer;
UNREACHABLE(); PrintF("%s", printer.PrintProgram(info_->function()));
UNREACHABLE();
}
} }
} }
#endif // DEBUG #endif // DEBUG

1
deps/v8/src/heap-inl.h

@ -505,7 +505,6 @@ Isolate* Heap::isolate() {
#define GC_GREEDY_CHECK() { } #define GC_GREEDY_CHECK() { }
#endif #endif
// Calls the FUNCTION_CALL function and retries it up to three times // Calls the FUNCTION_CALL function and retries it up to three times
// to guarantee that any allocations performed during the call will // to guarantee that any allocations performed during the call will
// succeed if there's enough memory. // succeed if there's enough memory.

118
deps/v8/src/heap.cc

@ -695,12 +695,18 @@ void Heap::UpdateSurvivalRateTrend(int start_new_space_size) {
(static_cast<double>(young_survivors_after_last_gc_) * 100) / (static_cast<double>(young_survivors_after_last_gc_) * 100) /
start_new_space_size; start_new_space_size;
if (survival_rate > kYoungSurvivalRateThreshold) { if (survival_rate > kYoungSurvivalRateHighThreshold) {
high_survival_rate_period_length_++; high_survival_rate_period_length_++;
} else { } else {
high_survival_rate_period_length_ = 0; high_survival_rate_period_length_ = 0;
} }
if (survival_rate < kYoungSurvivalRateLowThreshold) {
low_survival_rate_period_length_++;
} else {
low_survival_rate_period_length_ = 0;
}
double survival_rate_diff = survival_rate_ - survival_rate; double survival_rate_diff = survival_rate_ - survival_rate;
if (survival_rate_diff > kYoungSurvivalRateAllowedDeviation) { if (survival_rate_diff > kYoungSurvivalRateAllowedDeviation) {
@ -760,32 +766,6 @@ bool Heap::PerformGarbageCollection(GarbageCollector collector,
UpdateSurvivalRateTrend(start_new_space_size); UpdateSurvivalRateTrend(start_new_space_size);
if (!new_space_high_promotion_mode_active_ &&
new_space_.Capacity() == new_space_.MaximumCapacity() &&
IsStableOrIncreasingSurvivalTrend() &&
IsHighSurvivalRate()) {
// Stable high survival rates even though young generation is at
// maximum capacity indicates that most objects will be promoted.
// To decrease scavenger pauses and final mark-sweep pauses, we
// have to limit maximal capacity of the young generation.
new_space_high_promotion_mode_active_ = true;
if (FLAG_trace_gc) {
PrintF("Limited new space size due to high promotion rate: %d MB\n",
new_space_.InitialCapacity() / MB);
}
} else if (new_space_high_promotion_mode_active_ &&
IsDecreasingSurvivalTrend() &&
!IsHighSurvivalRate()) {
// Decreasing low survival rates might indicate that the above high
// promotion mode is over and we should allow the young generation
// to grow again.
new_space_high_promotion_mode_active_ = false;
if (FLAG_trace_gc) {
PrintF("Unlimited new space size due to low promotion rate: %d MB\n",
new_space_.MaximumCapacity() / MB);
}
}
size_of_old_gen_at_last_old_space_gc_ = PromotedSpaceSize(); size_of_old_gen_at_last_old_space_gc_ = PromotedSpaceSize();
if (high_survival_rate_during_scavenges && if (high_survival_rate_during_scavenges &&
@ -815,6 +795,32 @@ bool Heap::PerformGarbageCollection(GarbageCollector collector,
UpdateSurvivalRateTrend(start_new_space_size); UpdateSurvivalRateTrend(start_new_space_size);
} }
if (!new_space_high_promotion_mode_active_ &&
new_space_.Capacity() == new_space_.MaximumCapacity() &&
IsStableOrIncreasingSurvivalTrend() &&
IsHighSurvivalRate()) {
// Stable high survival rates even though young generation is at
// maximum capacity indicates that most objects will be promoted.
// To decrease scavenger pauses and final mark-sweep pauses, we
// have to limit maximal capacity of the young generation.
new_space_high_promotion_mode_active_ = true;
if (FLAG_trace_gc) {
PrintF("Limited new space size due to high promotion rate: %d MB\n",
new_space_.InitialCapacity() / MB);
}
} else if (new_space_high_promotion_mode_active_ &&
IsStableOrDecreasingSurvivalTrend() &&
IsLowSurvivalRate()) {
// Decreasing low survival rates might indicate that the above high
// promotion mode is over and we should allow the young generation
// to grow again.
new_space_high_promotion_mode_active_ = false;
if (FLAG_trace_gc) {
PrintF("Unlimited new space size due to low promotion rate: %d MB\n",
new_space_.MaximumCapacity() / MB);
}
}
if (new_space_high_promotion_mode_active_ && if (new_space_high_promotion_mode_active_ &&
new_space_.Capacity() > new_space_.InitialCapacity()) { new_space_.Capacity() > new_space_.InitialCapacity()) {
new_space_.Shrink(); new_space_.Shrink();
@ -1099,7 +1105,7 @@ void Heap::Scavenge() {
isolate_->descriptor_lookup_cache()->Clear(); isolate_->descriptor_lookup_cache()->Clear();
// Used for updating survived_since_last_expansion_ at function end. // Used for updating survived_since_last_expansion_ at function end.
intptr_t survived_watermark = PromotedSpaceSize(); intptr_t survived_watermark = PromotedSpaceSizeOfObjects();
CheckNewSpaceExpansionCriteria(); CheckNewSpaceExpansionCriteria();
@ -1191,7 +1197,7 @@ void Heap::Scavenge() {
// Update how much has survived scavenge. // Update how much has survived scavenge.
IncrementYoungSurvivorsCounter(static_cast<int>( IncrementYoungSurvivorsCounter(static_cast<int>(
(PromotedSpaceSize() - survived_watermark) + new_space_.Size())); (PromotedSpaceSizeOfObjects() - survived_watermark) + new_space_.Size()));
LOG(isolate_, ResourceEvent("scavenge", "end")); LOG(isolate_, ResourceEvent("scavenge", "end"));
@ -3302,7 +3308,7 @@ MaybeObject* Heap::CreateCode(const CodeDesc& desc,
} }
code->set_deoptimization_data(empty_fixed_array(), SKIP_WRITE_BARRIER); code->set_deoptimization_data(empty_fixed_array(), SKIP_WRITE_BARRIER);
code->set_handler_table(empty_fixed_array(), SKIP_WRITE_BARRIER); code->set_handler_table(empty_fixed_array(), SKIP_WRITE_BARRIER);
code->set_next_code_flushing_candidate(undefined_value()); code->set_gc_metadata(Smi::FromInt(0));
// Allow self references to created code object by patching the handle to // Allow self references to created code object by patching the handle to
// point to the newly allocated Code object. // point to the newly allocated Code object.
if (!self_reference.is_null()) { if (!self_reference.is_null()) {
@ -5422,6 +5428,16 @@ intptr_t Heap::PromotedSpaceSize() {
} }
intptr_t Heap::PromotedSpaceSizeOfObjects() {
return old_pointer_space_->SizeOfObjects()
+ old_data_space_->SizeOfObjects()
+ code_space_->SizeOfObjects()
+ map_space_->SizeOfObjects()
+ cell_space_->SizeOfObjects()
+ lo_space_->SizeOfObjects();
}
int Heap::PromotedExternalMemorySize() { int Heap::PromotedExternalMemorySize() {
if (amount_of_external_allocated_memory_ if (amount_of_external_allocated_memory_
<= amount_of_external_allocated_memory_at_last_global_gc_) return 0; <= amount_of_external_allocated_memory_at_last_global_gc_) return 0;
@ -6523,15 +6539,11 @@ int KeyedLookupCache::Hash(Map* map, String* name) {
int KeyedLookupCache::Lookup(Map* map, String* name) { int KeyedLookupCache::Lookup(Map* map, String* name) {
int index = (Hash(map, name) & kHashMask); int index = (Hash(map, name) & kHashMask);
Key& key = keys_[index]; for (int i = 0; i < kEntriesPerBucket; i++) {
if ((key.map == map) && key.name->Equals(name)) { Key& key = keys_[index + i];
return field_offsets_[index]; if ((key.map == map) && key.name->Equals(name)) {
} return field_offsets_[index + i];
ASSERT(kEntriesPerBucket == 2); // There are two entries to check. }
// First entry in the bucket missed, check the second.
Key& key2 = keys_[index + 1];
if ((key2.map == map) && key2.name->Equals(name)) {
return field_offsets_[index + 1];
} }
return kNotFound; return kNotFound;
} }
@ -6541,13 +6553,29 @@ void KeyedLookupCache::Update(Map* map, String* name, int field_offset) {
String* symbol; String* symbol;
if (HEAP->LookupSymbolIfExists(name, &symbol)) { if (HEAP->LookupSymbolIfExists(name, &symbol)) {
int index = (Hash(map, symbol) & kHashMask); int index = (Hash(map, symbol) & kHashMask);
Key& key = keys_[index]; // After a GC there will be free slots, so we use them in order (this may
Key& key2 = keys_[index + 1]; // Second entry in the bucket. // help to get the most frequently used one in position 0).
// Demote the first entry to the second in the bucket. for (int i = 0; i< kEntriesPerBucket; i++) {
key2.map = key.map; Key& key = keys_[index];
key2.name = key.name; Object* free_entry_indicator = NULL;
field_offsets_[index + 1] = field_offsets_[index]; if (key.map == free_entry_indicator) {
key.map = map;
key.name = symbol;
field_offsets_[index + i] = field_offset;
return;
}
}
// No free entry found in this bucket, so we move them all down one and
// put the new entry at position zero.
for (int i = kEntriesPerBucket - 1; i > 0; i--) {
Key& key = keys_[index + i];
Key& key2 = keys_[index + i - 1];
key = key2;
field_offsets_[index + i] = field_offsets_[index + i - 1];
}
// Write the new first entry. // Write the new first entry.
Key& key = keys_[index];
key.map = map; key.map = map;
key.name = symbol; key.name = symbol;
field_offsets_[index] = field_offset; field_offsets_[index] = field_offset;

42
deps/v8/src/heap.h

@ -156,6 +156,7 @@ inline Heap* _inline_get_heap_();
V(Script, empty_script, EmptyScript) \ V(Script, empty_script, EmptyScript) \
V(Smi, real_stack_limit, RealStackLimit) \ V(Smi, real_stack_limit, RealStackLimit) \
V(StringDictionary, intrinsic_function_names, IntrinsicFunctionNames) \ V(StringDictionary, intrinsic_function_names, IntrinsicFunctionNames) \
V(Smi, arguments_adaptor_deopt_pc_offset, ArgumentsAdaptorDeoptPCOffset)
#define ROOT_LIST(V) \ #define ROOT_LIST(V) \
STRONG_ROOT_LIST(V) \ STRONG_ROOT_LIST(V) \
@ -1067,7 +1068,7 @@ class Heap {
// Heap root getters. We have versions with and without type::cast() here. // Heap root getters. We have versions with and without type::cast() here.
// You can't use type::cast during GC because the assert fails. // You can't use type::cast during GC because the assert fails.
// TODO(1490): Try removing the unchecked accessors, now that GC marking does // TODO(1490): Try removing the unchecked accessors, now that GC marking does
// not corrupt the stack. // not corrupt the map.
#define ROOT_ACCESSOR(type, name, camel_name) \ #define ROOT_ACCESSOR(type, name, camel_name) \
type* name() { \ type* name() { \
return type::cast(roots_[k##camel_name##RootIndex]); \ return type::cast(roots_[k##camel_name##RootIndex]); \
@ -1381,6 +1382,7 @@ class Heap {
void CheckNewSpaceExpansionCriteria(); void CheckNewSpaceExpansionCriteria();
inline void IncrementYoungSurvivorsCounter(int survived) { inline void IncrementYoungSurvivorsCounter(int survived) {
ASSERT(survived >= 0);
young_survivors_after_last_gc_ = survived; young_survivors_after_last_gc_ = survived;
survived_since_last_expansion_ += survived; survived_since_last_expansion_ += survived;
} }
@ -1430,6 +1432,7 @@ class Heap {
// Returns the size of objects residing in non new spaces. // Returns the size of objects residing in non new spaces.
intptr_t PromotedSpaceSize(); intptr_t PromotedSpaceSize();
intptr_t PromotedSpaceSizeOfObjects();
double total_regexp_code_generated() { return total_regexp_code_generated_; } double total_regexp_code_generated() { return total_regexp_code_generated_; }
void IncreaseTotalRegexpCodeGenerated(int size) { void IncreaseTotalRegexpCodeGenerated(int size) {
@ -1517,6 +1520,11 @@ class Heap {
return seed; return seed;
} }
void SetArgumentsAdaptorDeoptPCOffset(int pc_offset) {
ASSERT(arguments_adaptor_deopt_pc_offset() == Smi::FromInt(0));
set_arguments_adaptor_deopt_pc_offset(Smi::FromInt(pc_offset));
}
private: private:
Heap(); Heap();
@ -1799,11 +1807,13 @@ class Heap {
enum SurvivalRateTrend { INCREASING, STABLE, DECREASING, FLUCTUATING }; enum SurvivalRateTrend { INCREASING, STABLE, DECREASING, FLUCTUATING };
static const int kYoungSurvivalRateThreshold = 90; static const int kYoungSurvivalRateHighThreshold = 90;
static const int kYoungSurvivalRateLowThreshold = 10;
static const int kYoungSurvivalRateAllowedDeviation = 15; static const int kYoungSurvivalRateAllowedDeviation = 15;
int young_survivors_after_last_gc_; int young_survivors_after_last_gc_;
int high_survival_rate_period_length_; int high_survival_rate_period_length_;
int low_survival_rate_period_length_;
double survival_rate_; double survival_rate_;
SurvivalRateTrend previous_survival_rate_trend_; SurvivalRateTrend previous_survival_rate_trend_;
SurvivalRateTrend survival_rate_trend_; SurvivalRateTrend survival_rate_trend_;
@ -1836,18 +1846,28 @@ class Heap {
} }
} }
bool IsIncreasingSurvivalTrend() { bool IsStableOrDecreasingSurvivalTrend() {
return survival_rate_trend() == INCREASING; switch (survival_rate_trend()) {
case STABLE:
case DECREASING:
return true;
default:
return false;
}
} }
bool IsDecreasingSurvivalTrend() { bool IsIncreasingSurvivalTrend() {
return survival_rate_trend() == DECREASING; return survival_rate_trend() == INCREASING;
} }
bool IsHighSurvivalRate() { bool IsHighSurvivalRate() {
return high_survival_rate_period_length_ > 0; return high_survival_rate_period_length_ > 0;
} }
bool IsLowSurvivalRate() {
return low_survival_rate_period_length_ > 0;
}
void SelectScavengingVisitorsTable(); void SelectScavengingVisitorsTable();
void StartIdleRound() { void StartIdleRound() {
@ -2135,13 +2155,17 @@ class KeyedLookupCache {
// Clear the cache. // Clear the cache.
void Clear(); void Clear();
static const int kLength = 128; static const int kLength = 256;
static const int kCapacityMask = kLength - 1; static const int kCapacityMask = kLength - 1;
static const int kMapHashShift = 5; static const int kMapHashShift = 5;
static const int kHashMask = -2; // Zero the last bit. static const int kHashMask = -4; // Zero the last two bits.
static const int kEntriesPerBucket = 2; static const int kEntriesPerBucket = 4;
static const int kNotFound = -1; static const int kNotFound = -1;
// kEntriesPerBucket should be a power of 2.
STATIC_ASSERT((kEntriesPerBucket & (kEntriesPerBucket - 1)) == 0);
STATIC_ASSERT(kEntriesPerBucket == -kHashMask);
private: private:
KeyedLookupCache() { KeyedLookupCache() {
for (int i = 0; i < kLength; ++i) { for (int i = 0; i < kLength; ++i) {

17
deps/v8/src/hydrogen-instructions.cc

@ -1339,6 +1339,23 @@ Range* HShl::InferRange() {
} }
Range* HLoadKeyedSpecializedArrayElement::InferRange() {
switch (elements_kind()) {
case EXTERNAL_PIXEL_ELEMENTS:
return new Range(0, 255);
case EXTERNAL_BYTE_ELEMENTS:
return new Range(-128, 127);
case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
return new Range(0, 255);
case EXTERNAL_SHORT_ELEMENTS:
return new Range(-32768, 32767);
case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
return new Range(0, 65535);
default:
return HValue::InferRange();
}
}
void HCompareGeneric::PrintDataTo(StringStream* stream) { void HCompareGeneric::PrintDataTo(StringStream* stream) {
stream->Add(Token::Name(token())); stream->Add(Token::Name(token()));

7
deps/v8/src/hydrogen-instructions.h

@ -764,6 +764,7 @@ class HValue: public ZoneObject {
int flags_; int flags_;
GVNFlagSet gvn_flags_; GVNFlagSet gvn_flags_;
private:
DISALLOW_COPY_AND_ASSIGN(HValue); DISALLOW_COPY_AND_ASSIGN(HValue);
}; };
@ -1340,9 +1341,11 @@ class HStackCheck: public HTemplateInstruction<1> {
class HEnterInlined: public HTemplateInstruction<0> { class HEnterInlined: public HTemplateInstruction<0> {
public: public:
HEnterInlined(Handle<JSFunction> closure, HEnterInlined(Handle<JSFunction> closure,
int arguments_count,
FunctionLiteral* function, FunctionLiteral* function,
CallKind call_kind) CallKind call_kind)
: closure_(closure), : closure_(closure),
arguments_count_(arguments_count),
function_(function), function_(function),
call_kind_(call_kind) { call_kind_(call_kind) {
} }
@ -1350,6 +1353,7 @@ class HEnterInlined: public HTemplateInstruction<0> {
virtual void PrintDataTo(StringStream* stream); virtual void PrintDataTo(StringStream* stream);
Handle<JSFunction> closure() const { return closure_; } Handle<JSFunction> closure() const { return closure_; }
int arguments_count() const { return arguments_count_; }
FunctionLiteral* function() const { return function_; } FunctionLiteral* function() const { return function_; }
CallKind call_kind() const { return call_kind_; } CallKind call_kind() const { return call_kind_; }
@ -1361,6 +1365,7 @@ class HEnterInlined: public HTemplateInstruction<0> {
private: private:
Handle<JSFunction> closure_; Handle<JSFunction> closure_;
int arguments_count_;
FunctionLiteral* function_; FunctionLiteral* function_;
CallKind call_kind_; CallKind call_kind_;
}; };
@ -3844,6 +3849,8 @@ class HLoadKeyedSpecializedArrayElement: public HTemplateInstruction<2> {
HValue* key() { return OperandAt(1); } HValue* key() { return OperandAt(1); }
ElementsKind elements_kind() const { return elements_kind_; } ElementsKind elements_kind() const { return elements_kind_; }
virtual Range* InferRange();
DECLARE_CONCRETE_INSTRUCTION(LoadKeyedSpecializedArrayElement) DECLARE_CONCRETE_INSTRUCTION(LoadKeyedSpecializedArrayElement)
protected: protected:

76
deps/v8/src/hydrogen.cc

@ -167,8 +167,7 @@ void HBasicBlock::Finish(HControlInstruction* end) {
void HBasicBlock::Goto(HBasicBlock* block, bool drop_extra) { void HBasicBlock::Goto(HBasicBlock* block, bool drop_extra) {
if (block->IsInlineReturnTarget()) { if (block->IsInlineReturnTarget()) {
AddInstruction(new(zone()) HLeaveInlined); AddInstruction(new(zone()) HLeaveInlined);
last_environment_ = last_environment()->outer(); last_environment_ = last_environment()->DiscardInlined(drop_extra);
if (drop_extra) last_environment_->Drop(1);
} }
AddSimulate(AstNode::kNoNumber); AddSimulate(AstNode::kNoNumber);
HGoto* instr = new(zone()) HGoto(block); HGoto* instr = new(zone()) HGoto(block);
@ -182,8 +181,7 @@ void HBasicBlock::AddLeaveInlined(HValue* return_value,
ASSERT(target->IsInlineReturnTarget()); ASSERT(target->IsInlineReturnTarget());
ASSERT(return_value != NULL); ASSERT(return_value != NULL);
AddInstruction(new(zone()) HLeaveInlined); AddInstruction(new(zone()) HLeaveInlined);
last_environment_ = last_environment()->outer(); last_environment_ = last_environment()->DiscardInlined(drop_extra);
if (drop_extra) last_environment_->Drop(1);
last_environment()->Push(return_value); last_environment()->Push(return_value);
AddSimulate(AstNode::kNoNumber); AddSimulate(AstNode::kNoNumber);
HGoto* instr = new(zone()) HGoto(target); HGoto* instr = new(zone()) HGoto(target);
@ -2076,6 +2074,7 @@ AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind)
for_typeof_(false) { for_typeof_(false) {
owner->set_ast_context(this); // Push. owner->set_ast_context(this); // Push.
#ifdef DEBUG #ifdef DEBUG
ASSERT(!owner->environment()->is_arguments_adaptor());
original_length_ = owner->environment()->length(); original_length_ = owner->environment()->length();
#endif #endif
} }
@ -2089,14 +2088,16 @@ AstContext::~AstContext() {
EffectContext::~EffectContext() { EffectContext::~EffectContext() {
ASSERT(owner()->HasStackOverflow() || ASSERT(owner()->HasStackOverflow() ||
owner()->current_block() == NULL || owner()->current_block() == NULL ||
owner()->environment()->length() == original_length_); (owner()->environment()->length() == original_length_ &&
!owner()->environment()->is_arguments_adaptor()));
} }
ValueContext::~ValueContext() { ValueContext::~ValueContext() {
ASSERT(owner()->HasStackOverflow() || ASSERT(owner()->HasStackOverflow() ||
owner()->current_block() == NULL || owner()->current_block() == NULL ||
owner()->environment()->length() == original_length_ + 1); (owner()->environment()->length() == original_length_ + 1 &&
!owner()->environment()->is_arguments_adaptor()));
} }
@ -4828,7 +4829,9 @@ bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) {
TraceInline(target, caller, "inline depth limit reached"); TraceInline(target, caller, "inline depth limit reached");
return false; return false;
} }
current_level++; if (!env->outer()->is_arguments_adaptor()) {
current_level++;
}
env = env->outer(); env = env->outer();
} }
@ -4876,11 +4879,8 @@ bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) {
return false; return false;
} }
// Don't inline functions that uses the arguments object or that // Don't inline functions that uses the arguments object.
// have a mismatching number of parameters. if (function->scope()->arguments() != NULL) {
int arity = expr->arguments()->length();
if (function->scope()->arguments() != NULL ||
arity != target_shared->formal_parameter_count()) {
TraceInline(target, caller, "target requires special argument handling"); TraceInline(target, caller, "target requires special argument handling");
return false; return false;
} }
@ -4944,6 +4944,7 @@ bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) {
HConstant* undefined = graph()->GetConstantUndefined(); HConstant* undefined = graph()->GetConstantUndefined();
HEnvironment* inner_env = HEnvironment* inner_env =
environment()->CopyForInlining(target, environment()->CopyForInlining(target,
expr->arguments()->length(),
function, function,
undefined, undefined,
call_kind); call_kind);
@ -4963,6 +4964,7 @@ bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) {
body_entry->SetJoinId(expr->ReturnId()); body_entry->SetJoinId(expr->ReturnId());
set_current_block(body_entry); set_current_block(body_entry);
AddInstruction(new(zone()) HEnterInlined(target, AddInstruction(new(zone()) HEnterInlined(target,
expr->arguments()->length(),
function, function,
call_kind)); call_kind));
VisitDeclarations(target_info.scope()->declarations()); VisitDeclarations(target_info.scope()->declarations());
@ -6902,7 +6904,8 @@ HEnvironment::HEnvironment(HEnvironment* outer,
outer_(outer), outer_(outer),
pop_count_(0), pop_count_(0),
push_count_(0), push_count_(0),
ast_id_(AstNode::kNoNumber) { ast_id_(AstNode::kNoNumber),
arguments_adaptor_(false) {
Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0); Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0);
} }
@ -6916,11 +6919,28 @@ HEnvironment::HEnvironment(const HEnvironment* other)
outer_(NULL), outer_(NULL),
pop_count_(0), pop_count_(0),
push_count_(0), push_count_(0),
ast_id_(other->ast_id()) { ast_id_(other->ast_id()),
arguments_adaptor_(false) {
Initialize(other); Initialize(other);
} }
HEnvironment::HEnvironment(HEnvironment* outer,
Handle<JSFunction> closure,
int arguments)
: closure_(closure),
values_(arguments),
assigned_variables_(0),
parameter_count_(arguments),
local_count_(0),
outer_(outer),
pop_count_(0),
push_count_(0),
ast_id_(AstNode::kNoNumber),
arguments_adaptor_(true) {
}
void HEnvironment::Initialize(int parameter_count, void HEnvironment::Initialize(int parameter_count,
int local_count, int local_count,
int stack_height) { int stack_height) {
@ -6944,6 +6964,7 @@ void HEnvironment::Initialize(const HEnvironment* other) {
pop_count_ = other->pop_count_; pop_count_ = other->pop_count_;
push_count_ = other->push_count_; push_count_ = other->push_count_;
ast_id_ = other->ast_id_; ast_id_ = other->ast_id_;
arguments_adaptor_ = other->arguments_adaptor_;
} }
@ -7047,20 +7068,36 @@ HEnvironment* HEnvironment::CopyAsLoopHeader(HBasicBlock* loop_header) const {
HEnvironment* HEnvironment::CopyForInlining( HEnvironment* HEnvironment::CopyForInlining(
Handle<JSFunction> target, Handle<JSFunction> target,
int arguments,
FunctionLiteral* function, FunctionLiteral* function,
HConstant* undefined, HConstant* undefined,
CallKind call_kind) const { CallKind call_kind) const {
ASSERT(!is_arguments_adaptor());
Zone* zone = closure()->GetIsolate()->zone();
// Outer environment is a copy of this one without the arguments. // Outer environment is a copy of this one without the arguments.
int arity = function->scope()->num_parameters(); int arity = function->scope()->num_parameters();
HEnvironment* outer = Copy(); HEnvironment* outer = Copy();
outer->Drop(arity + 1); // Including receiver. outer->Drop(arguments + 1); // Including receiver.
outer->ClearHistory(); outer->ClearHistory();
Zone* zone = closure()->GetIsolate()->zone();
if (arity != arguments) {
// Create artificial arguments adaptation environment.
outer = new(zone) HEnvironment(outer, target, arguments + 1);
for (int i = 0; i <= arguments; ++i) { // Include receiver.
outer->Push(ExpressionStackAt(arguments - i));
}
outer->ClearHistory();
}
HEnvironment* inner = HEnvironment* inner =
new(zone) HEnvironment(outer, function->scope(), target); new(zone) HEnvironment(outer, function->scope(), target);
// Get the argument values from the original environment. // Get the argument values from the original environment.
for (int i = 0; i <= arity; ++i) { // Include receiver. for (int i = 0; i <= arity; ++i) { // Include receiver.
HValue* push = ExpressionStackAt(arity - i); HValue* push = (i <= arguments) ?
ExpressionStackAt(arguments - i) : undefined;
inner->SetValueAt(i, push); inner->SetValueAt(i, push);
} }
// If the function we are inlining is a strict mode function or a // If the function we are inlining is a strict mode function or a
@ -7070,7 +7107,7 @@ HEnvironment* HEnvironment::CopyForInlining(
call_kind == CALL_AS_FUNCTION) { call_kind == CALL_AS_FUNCTION) {
inner->SetValueAt(0, undefined); inner->SetValueAt(0, undefined);
} }
inner->SetValueAt(arity + 1, outer->LookupContext()); inner->SetValueAt(arity + 1, LookupContext());
for (int i = arity + 2; i < inner->length(); ++i) { for (int i = arity + 2; i < inner->length(); ++i) {
inner->SetValueAt(i, undefined); inner->SetValueAt(i, undefined);
} }
@ -7086,7 +7123,7 @@ void HEnvironment::PrintTo(StringStream* stream) {
if (i == parameter_count()) stream->Add("specials\n"); if (i == parameter_count()) stream->Add("specials\n");
if (i == parameter_count() + specials_count()) stream->Add("locals\n"); if (i == parameter_count() + specials_count()) stream->Add("locals\n");
if (i == parameter_count() + specials_count() + local_count()) { if (i == parameter_count() + specials_count() + local_count()) {
stream->Add("expressions"); stream->Add("expressions\n");
} }
HValue* val = values_.at(i); HValue* val = values_.at(i);
stream->Add("%d: ", i); stream->Add("%d: ", i);
@ -7097,6 +7134,7 @@ void HEnvironment::PrintTo(StringStream* stream) {
} }
stream->Add("\n"); stream->Add("\n");
} }
PrintF("\n");
} }

17
deps/v8/src/hydrogen.h

@ -343,6 +343,17 @@ class HEnvironment: public ZoneObject {
Scope* scope, Scope* scope,
Handle<JSFunction> closure); Handle<JSFunction> closure);
bool is_arguments_adaptor() const {
return arguments_adaptor_;
}
HEnvironment* DiscardInlined(bool drop_extra) {
HEnvironment* outer = outer_->is_arguments_adaptor() ?
outer_->outer_ : outer_;
if (drop_extra) outer->Drop(1);
return outer;
}
// Simple accessors. // Simple accessors.
Handle<JSFunction> closure() const { return closure_; } Handle<JSFunction> closure() const { return closure_; }
const ZoneList<HValue*>* values() const { return &values_; } const ZoneList<HValue*>* values() const { return &values_; }
@ -427,6 +438,7 @@ class HEnvironment: public ZoneObject {
// environment is the outer environment but the top expression stack // environment is the outer environment but the top expression stack
// elements are moved to an inner environment as parameters. // elements are moved to an inner environment as parameters.
HEnvironment* CopyForInlining(Handle<JSFunction> target, HEnvironment* CopyForInlining(Handle<JSFunction> target,
int arguments,
FunctionLiteral* function, FunctionLiteral* function,
HConstant* undefined, HConstant* undefined,
CallKind call_kind) const; CallKind call_kind) const;
@ -450,6 +462,10 @@ class HEnvironment: public ZoneObject {
private: private:
explicit HEnvironment(const HEnvironment* other); explicit HEnvironment(const HEnvironment* other);
// Create an argument adaptor environment.
HEnvironment(HEnvironment* outer, Handle<JSFunction> closure, int arguments);
// True if index is included in the expression stack part of the environment. // True if index is included in the expression stack part of the environment.
bool HasExpressionAt(int index) const; bool HasExpressionAt(int index) const;
@ -478,6 +494,7 @@ class HEnvironment: public ZoneObject {
int pop_count_; int pop_count_;
int push_count_; int push_count_;
int ast_id_; int ast_id_;
bool arguments_adaptor_;
}; };

4
deps/v8/src/ia32/assembler-ia32-inl.h

@ -30,13 +30,15 @@
// The original source code covered by the above license above has been // The original source code covered by the above license above has been
// modified significantly by Google Inc. // 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 IA32 Assembler. // A light-weight IA32 Assembler.
#ifndef V8_IA32_ASSEMBLER_IA32_INL_H_ #ifndef V8_IA32_ASSEMBLER_IA32_INL_H_
#define V8_IA32_ASSEMBLER_IA32_INL_H_ #define V8_IA32_ASSEMBLER_IA32_INL_H_
#include "ia32/assembler-ia32.h"
#include "cpu.h" #include "cpu.h"
#include "debug.h" #include "debug.h"

3
deps/v8/src/ia32/builtins-ia32.cc

@ -537,7 +537,7 @@ static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
{ {
FrameScope scope(masm, StackFrame::INTERNAL); FrameScope scope(masm, StackFrame::INTERNAL);
// Pass the function and deoptimization type to the runtime system. // Pass deoptimization type to the runtime system.
__ push(Immediate(Smi::FromInt(static_cast<int>(type)))); __ push(Immediate(Smi::FromInt(static_cast<int>(type))));
__ CallRuntime(Runtime::kNotifyDeoptimized, 1); __ CallRuntime(Runtime::kNotifyDeoptimized, 1);
@ -1644,6 +1644,7 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
__ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
__ call(edx); __ call(edx);
masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
// Leave frame and return. // Leave frame and return.
LeaveArgumentsAdaptorFrame(masm); LeaveArgumentsAdaptorFrame(masm);
__ ret(0); __ ret(0);

126
deps/v8/src/ia32/deoptimizer-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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -299,12 +299,13 @@ void Deoptimizer::DoComputeOsrOutputFrame() {
ASSERT(Translation::BEGIN == opcode); ASSERT(Translation::BEGIN == opcode);
USE(opcode); USE(opcode);
int count = iterator.Next(); int count = iterator.Next();
iterator.Next(); // Drop JS frames count.
ASSERT(count == 1); ASSERT(count == 1);
USE(count); USE(count);
opcode = static_cast<Translation::Opcode>(iterator.Next()); opcode = static_cast<Translation::Opcode>(iterator.Next());
USE(opcode); USE(opcode);
ASSERT(Translation::FRAME == opcode); ASSERT(Translation::JS_FRAME == opcode);
unsigned node_id = iterator.Next(); unsigned node_id = iterator.Next();
USE(node_id); USE(node_id);
ASSERT(node_id == ast_id); ASSERT(node_id == ast_id);
@ -340,9 +341,7 @@ void Deoptimizer::DoComputeOsrOutputFrame() {
output_ = new FrameDescription*[1]; output_ = new FrameDescription*[1];
output_[0] = new(output_frame_size) FrameDescription( output_[0] = new(output_frame_size) FrameDescription(
output_frame_size, function_); output_frame_size, function_);
#ifdef DEBUG output_[0]->SetFrameType(StackFrame::JAVA_SCRIPT);
output_[0]->SetKind(Code::OPTIMIZED_FUNCTION);
#endif
// Clear the incoming parameters in the optimized frame to avoid // Clear the incoming parameters in the optimized frame to avoid
// confusing the garbage collector. // confusing the garbage collector.
@ -437,13 +436,112 @@ void Deoptimizer::DoComputeOsrOutputFrame() {
} }
void Deoptimizer::DoComputeFrame(TranslationIterator* iterator, void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator,
int frame_index) { int frame_index) {
// Read the ast node id, function, and frame height for this output frame. JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
Translation::Opcode opcode = unsigned height = iterator->Next();
static_cast<Translation::Opcode>(iterator->Next()); unsigned height_in_bytes = height * kPointerSize;
USE(opcode); if (FLAG_trace_deopt) {
ASSERT(Translation::FRAME == opcode); PrintF(" translating arguments adaptor => height=%d\n", height_in_bytes);
}
unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize;
unsigned input_frame_size = input_->GetFrameSize();
unsigned output_frame_size = height_in_bytes + fixed_frame_size;
// Allocate and store the output frame description.
FrameDescription* output_frame =
new(output_frame_size) FrameDescription(output_frame_size, function);
output_frame->SetFrameType(StackFrame::ARGUMENTS_ADAPTOR);
// Arguments adaptor can not be topmost or bottommost.
ASSERT(frame_index > 0 && frame_index < output_count_ - 1);
ASSERT(output_[frame_index] == NULL);
output_[frame_index] = output_frame;
// The top address of the frame is computed from the previous
// frame's top and this frame's size.
uint32_t top_address;
top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
output_frame->SetTop(top_address);
// Compute the incoming parameter translation.
int parameter_count = height;
unsigned output_offset = output_frame_size;
unsigned input_offset = input_frame_size;
for (int i = 0; i < parameter_count; ++i) {
output_offset -= kPointerSize;
DoTranslateCommand(iterator, frame_index, output_offset);
}
input_offset -= (parameter_count * kPointerSize);
// Read caller's PC from the previous frame.
output_offset -= kPointerSize;
input_offset -= kPointerSize;
intptr_t callers_pc = output_[frame_index - 1]->GetPc();
output_frame->SetFrameSlot(output_offset, callers_pc);
if (FLAG_trace_deopt) {
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's pc\n",
top_address + output_offset, output_offset, callers_pc);
}
// Read caller's FP from the previous frame, and set this frame's FP.
output_offset -= kPointerSize;
input_offset -= kPointerSize;
intptr_t value = output_[frame_index - 1]->GetFp();
output_frame->SetFrameSlot(output_offset, value);
intptr_t fp_value = top_address + output_offset;
output_frame->SetFp(fp_value);
if (FLAG_trace_deopt) {
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's fp\n",
fp_value, output_offset, value);
}
// A marker value is used in place of the context.
output_offset -= kPointerSize;
input_offset -= kPointerSize;
intptr_t context = reinterpret_cast<intptr_t>(
Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
output_frame->SetFrameSlot(output_offset, context);
if (FLAG_trace_deopt) {
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; context (adaptor sentinel)\n",
top_address + output_offset, output_offset, context);
}
// The function was mentioned explicitly in the ARGUMENTS_ADAPTOR_FRAME.
output_offset -= kPointerSize;
input_offset -= kPointerSize;
value = reinterpret_cast<intptr_t>(function);
output_frame->SetFrameSlot(output_offset, value);
if (FLAG_trace_deopt) {
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; function\n",
top_address + output_offset, output_offset, value);
}
// Number of incoming arguments.
output_offset -= kPointerSize;
input_offset -= kPointerSize;
value = reinterpret_cast<uint32_t>(Smi::FromInt(height - 1));
output_frame->SetFrameSlot(output_offset, value);
if (FLAG_trace_deopt) {
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; argc (%d)\n",
top_address + output_offset, output_offset, value, height - 1);
}
ASSERT(0 == output_offset);
Builtins* builtins = isolate_->builtins();
Code* adaptor_trampoline =
builtins->builtin(Builtins::kArgumentsAdaptorTrampoline);
uint32_t pc = reinterpret_cast<uint32_t>(
adaptor_trampoline->instruction_start() +
isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value());
output_frame->SetPc(pc);
}
void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
int frame_index) {
int node_id = iterator->Next(); int node_id = iterator->Next();
JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
unsigned height = iterator->Next(); unsigned height = iterator->Next();
@ -463,9 +561,7 @@ void Deoptimizer::DoComputeFrame(TranslationIterator* iterator,
// Allocate and store the output frame description. // Allocate and store the output frame description.
FrameDescription* output_frame = FrameDescription* output_frame =
new(output_frame_size) FrameDescription(output_frame_size, function); new(output_frame_size) FrameDescription(output_frame_size, function);
#ifdef DEBUG output_frame->SetFrameType(StackFrame::JAVA_SCRIPT);
output_frame->SetKind(Code::FUNCTION);
#endif
bool is_bottommost = (0 == frame_index); bool is_bottommost = (0 == frame_index);
bool is_topmost = (output_count_ - 1 == frame_index); bool is_topmost = (output_count_ - 1 == frame_index);

8
deps/v8/src/ia32/frames-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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -95,9 +95,11 @@ class ExitFrameConstants : public AllStatic {
class StandardFrameConstants : public AllStatic { class StandardFrameConstants : public AllStatic {
public: public:
// Fixed part of the frame consists of return address, caller fp,
// context and function.
// StandardFrame::IterateExpressions assumes that kContextOffset is the last // StandardFrame::IterateExpressions assumes that kContextOffset is the last
// object pointer. // object pointer.
static const int kFixedFrameSize = 4; // Currently unused. static const int kFixedFrameSize = 4 * kPointerSize;
static const int kExpressionsOffset = -3 * kPointerSize; static const int kExpressionsOffset = -3 * kPointerSize;
static const int kMarkerOffset = -2 * kPointerSize; static const int kMarkerOffset = -2 * kPointerSize;
static const int kContextOffset = -1 * kPointerSize; static const int kContextOffset = -1 * kPointerSize;
@ -123,6 +125,8 @@ class JavaScriptFrameConstants : public AllStatic {
class ArgumentsAdaptorFrameConstants : public AllStatic { class ArgumentsAdaptorFrameConstants : public AllStatic {
public: public:
static const int kLengthOffset = StandardFrameConstants::kExpressionsOffset; static const int kLengthOffset = StandardFrameConstants::kExpressionsOffset;
static const int kFrameSize =
StandardFrameConstants::kFixedFrameSize + kPointerSize;
}; };

59
deps/v8/src/ia32/ic-ia32.cc

@ -538,20 +538,30 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
// Load the key (consisting of map and symbol) from the cache and // Load the key (consisting of map and symbol) from the cache and
// check for match. // check for match.
Label try_second_entry, hit_on_first_entry, load_in_object_property; Label load_in_object_property;
static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket;
Label hit_on_nth_entry[kEntriesPerBucket];
ExternalReference cache_keys = ExternalReference cache_keys =
ExternalReference::keyed_lookup_cache_keys(masm->isolate()); ExternalReference::keyed_lookup_cache_keys(masm->isolate());
__ mov(edi, ecx);
__ shl(edi, kPointerSizeLog2 + 1);
__ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys));
__ j(not_equal, &try_second_entry);
__ add(edi, Immediate(kPointerSize));
__ cmp(eax, Operand::StaticArray(edi, times_1, cache_keys));
__ j(equal, &hit_on_first_entry);
__ bind(&try_second_entry); for (int i = 0; i < kEntriesPerBucket - 1; i++) {
Label try_next_entry;
__ mov(edi, ecx);
__ shl(edi, kPointerSizeLog2 + 1);
if (i != 0) {
__ add(edi, Immediate(kPointerSize * i * 2));
}
__ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys));
__ j(not_equal, &try_next_entry);
__ add(edi, Immediate(kPointerSize));
__ cmp(eax, Operand::StaticArray(edi, times_1, cache_keys));
__ j(equal, &hit_on_nth_entry[i]);
__ bind(&try_next_entry);
}
__ lea(edi, Operand(ecx, 1)); __ lea(edi, Operand(ecx, 1));
__ shl(edi, kPointerSizeLog2 + 1); __ shl(edi, kPointerSizeLog2 + 1);
__ add(edi, Immediate(kPointerSize * (kEntriesPerBucket - 1) * 2));
__ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys)); __ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys));
__ j(not_equal, &slow); __ j(not_equal, &slow);
__ add(edi, Immediate(kPointerSize)); __ add(edi, Immediate(kPointerSize));
@ -566,22 +576,21 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
ExternalReference cache_field_offsets = ExternalReference cache_field_offsets =
ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate()); ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate());
// Hit on second entry. // Hit on nth entry.
__ add(ecx, Immediate(1)); for (int i = kEntriesPerBucket - 1; i >= 0; i--) {
__ mov(edi, __ bind(&hit_on_nth_entry[i]);
Operand::StaticArray(ecx, times_pointer_size, cache_field_offsets)); if (i != 0) {
__ movzx_b(ecx, FieldOperand(ebx, Map::kInObjectPropertiesOffset)); __ add(ecx, Immediate(i));
__ sub(edi, ecx); }
__ j(above_equal, &property_array_property); __ mov(edi,
__ jmp(&load_in_object_property); Operand::StaticArray(ecx, times_pointer_size, cache_field_offsets));
__ movzx_b(ecx, FieldOperand(ebx, Map::kInObjectPropertiesOffset));
// Hit on first entry. __ sub(edi, ecx);
__ bind(&hit_on_first_entry); __ j(above_equal, &property_array_property);
__ mov(edi, if (i != 0) {
Operand::StaticArray(ecx, times_pointer_size, cache_field_offsets)); __ jmp(&load_in_object_property);
__ movzx_b(ecx, FieldOperand(ebx, Map::kInObjectPropertiesOffset)); }
__ sub(edi, ecx); }
__ j(above_equal, &property_array_property);
// Load in-object property. // Load in-object property.
__ bind(&load_in_object_property); __ bind(&load_in_object_property);

12
deps/v8/src/ia32/lithium-codegen-ia32.cc

@ -394,7 +394,11 @@ void LCodeGen::WriteTranslation(LEnvironment* environment,
WriteTranslation(environment->outer(), translation); WriteTranslation(environment->outer(), translation);
int closure_id = DefineDeoptimizationLiteral(environment->closure()); int closure_id = DefineDeoptimizationLiteral(environment->closure());
translation->BeginFrame(environment->ast_id(), closure_id, height); if (environment->is_arguments_adaptor()) {
translation->BeginArgumentsAdaptorFrame(closure_id, translation_size);
} else {
translation->BeginJSFrame(environment->ast_id(), closure_id, height);
}
for (int i = 0; i < translation_size; ++i) { for (int i = 0; i < translation_size; ++i) {
LOperand* value = environment->values()->at(i); LOperand* value = environment->values()->at(i);
// spilled_registers_ and spilled_double_registers_ are either // spilled_registers_ and spilled_double_registers_ are either
@ -543,10 +547,14 @@ void LCodeGen::RegisterEnvironmentForDeoptimization(
// |>------------ translation_size ------------<| // |>------------ translation_size ------------<|
int frame_count = 0; int frame_count = 0;
int jsframe_count = 0;
for (LEnvironment* e = environment; e != NULL; e = e->outer()) { for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
++frame_count; ++frame_count;
if (!e->is_arguments_adaptor()) {
++jsframe_count;
}
} }
Translation translation(&translations_, frame_count); Translation translation(&translations_, frame_count, jsframe_count);
WriteTranslation(environment, &translation); WriteTranslation(environment, &translation);
int deoptimization_index = deoptimizations_.length(); int deoptimization_index = deoptimizations_.length();
int pc_offset = masm()->pc_offset(); int pc_offset = masm()->pc_offset();

24
deps/v8/src/ia32/lithium-ia32.cc

@ -1013,15 +1013,17 @@ LEnvironment* LChunkBuilder::CreateEnvironment(
LEnvironment* outer = LEnvironment* outer =
CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator); CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator);
int ast_id = hydrogen_env->ast_id(); int ast_id = hydrogen_env->ast_id();
ASSERT(ast_id != AstNode::kNoNumber); ASSERT(ast_id != AstNode::kNoNumber || hydrogen_env->is_arguments_adaptor());
int value_count = hydrogen_env->length(); int value_count = hydrogen_env->length();
LEnvironment* result = LEnvironment* result =
new(zone()) LEnvironment(hydrogen_env->closure(), new(zone()) LEnvironment(hydrogen_env->closure(),
hydrogen_env->is_arguments_adaptor(),
ast_id, ast_id,
hydrogen_env->parameter_count(), hydrogen_env->parameter_count(),
argument_count_, argument_count_,
value_count, value_count,
outer); outer);
int argument_index = *argument_index_accumulator;
for (int i = 0; i < value_count; ++i) { for (int i = 0; i < value_count; ++i) {
if (hydrogen_env->is_special_index(i)) continue; if (hydrogen_env->is_special_index(i)) continue;
@ -1030,13 +1032,17 @@ LEnvironment* LChunkBuilder::CreateEnvironment(
if (value->IsArgumentsObject()) { if (value->IsArgumentsObject()) {
op = NULL; op = NULL;
} else if (value->IsPushArgument()) { } else if (value->IsPushArgument()) {
op = new(zone()) LArgument((*argument_index_accumulator)++); op = new(zone()) LArgument(argument_index++);
} else { } else {
op = UseAny(value); op = UseAny(value);
} }
result->AddValue(op, value->representation()); result->AddValue(op, value->representation());
} }
if (!hydrogen_env->is_arguments_adaptor()) {
*argument_index_accumulator = argument_index;
}
return result; return result;
} }
@ -2002,12 +2008,11 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement( LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
HLoadKeyedSpecializedArrayElement* instr) { HLoadKeyedSpecializedArrayElement* instr) {
ElementsKind elements_kind = instr->elements_kind(); ElementsKind elements_kind = instr->elements_kind();
Representation representation(instr->representation());
ASSERT( ASSERT(
(representation.IsInteger32() && (instr->representation().IsInteger32() &&
(elements_kind != EXTERNAL_FLOAT_ELEMENTS) && (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
(elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) || (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
(representation.IsDouble() && (instr->representation().IsDouble() &&
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) || ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS)))); (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
ASSERT(instr->key()->representation().IsInteger32()); ASSERT(instr->key()->representation().IsInteger32());
@ -2070,13 +2075,12 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement(
LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement( LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
HStoreKeyedSpecializedArrayElement* instr) { HStoreKeyedSpecializedArrayElement* instr) {
Representation representation(instr->value()->representation());
ElementsKind elements_kind = instr->elements_kind(); ElementsKind elements_kind = instr->elements_kind();
ASSERT( ASSERT(
(representation.IsInteger32() && (instr->value()->representation().IsInteger32() &&
(elements_kind != EXTERNAL_FLOAT_ELEMENTS) && (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
(elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) || (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
(representation.IsDouble() && (instr->value()->representation().IsDouble() &&
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) || ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS)))); (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
ASSERT(instr->external_pointer()->representation().IsExternal()); ASSERT(instr->external_pointer()->representation().IsExternal());
@ -2380,6 +2384,7 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
HEnvironment* outer = current_block_->last_environment(); HEnvironment* outer = current_block_->last_environment();
HConstant* undefined = graph()->GetConstantUndefined(); HConstant* undefined = graph()->GetConstantUndefined();
HEnvironment* inner = outer->CopyForInlining(instr->closure(), HEnvironment* inner = outer->CopyForInlining(instr->closure(),
instr->arguments_count(),
instr->function(), instr->function(),
undefined, undefined,
instr->call_kind()); instr->call_kind());
@ -2390,7 +2395,8 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
HEnvironment* outer = current_block_->last_environment()->outer(); HEnvironment* outer = current_block_->last_environment()->
DiscardInlined(false);
current_block_->UpdateEnvironment(outer); current_block_->UpdateEnvironment(outer);
return NULL; return NULL;
} }

8
deps/v8/src/jsregexp.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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -35,9 +35,11 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
class NodeVisitor;
class RegExpCompiler;
class RegExpMacroAssembler; class RegExpMacroAssembler;
class RegExpNode;
class RegExpTree;
class RegExpImpl { class RegExpImpl {
public: public:

12
deps/v8/src/lithium-allocator.cc

@ -161,9 +161,8 @@ LiveRange::LiveRange(int id)
next_(NULL), next_(NULL),
current_interval_(NULL), current_interval_(NULL),
last_processed_use_(NULL), last_processed_use_(NULL),
spill_start_index_(kMaxInt) { spill_operand_(new LOperand()),
spill_operand_ = new LUnallocated(LUnallocated::IGNORE); spill_start_index_(kMaxInt) { }
}
void LiveRange::set_assigned_register(int reg, RegisterKind register_kind) { void LiveRange::set_assigned_register(int reg, RegisterKind register_kind) {
@ -184,14 +183,15 @@ void LiveRange::MakeSpilled() {
bool LiveRange::HasAllocatedSpillOperand() const { bool LiveRange::HasAllocatedSpillOperand() const {
return spill_operand_ != NULL && !spill_operand_->IsUnallocated(); ASSERT(spill_operand_ != NULL);
return !spill_operand_->IsIgnored();
} }
void LiveRange::SetSpillOperand(LOperand* operand) { void LiveRange::SetSpillOperand(LOperand* operand) {
ASSERT(!operand->IsUnallocated()); ASSERT(!operand->IsUnallocated());
ASSERT(spill_operand_ != NULL); ASSERT(spill_operand_ != NULL);
ASSERT(spill_operand_->IsUnallocated()); ASSERT(spill_operand_->IsIgnored());
spill_operand_->ConvertTo(operand->kind(), operand->index()); spill_operand_->ConvertTo(operand->kind(), operand->index());
} }
@ -1643,7 +1643,7 @@ void LAllocator::RecordUse(HValue* value, LUnallocated* operand) {
int LAllocator::max_initial_value_ids() { int LAllocator::max_initial_value_ids() {
return LUnallocated::kMaxVirtualRegisters / 32; return LUnallocated::kMaxVirtualRegisters / 16;
} }

4
deps/v8/src/lithium.cc

@ -36,6 +36,7 @@ void LOperand::PrintTo(StringStream* stream) {
LUnallocated* unalloc = NULL; LUnallocated* unalloc = NULL;
switch (kind()) { switch (kind()) {
case INVALID: case INVALID:
stream->Add("(0)");
break; break;
case UNALLOCATED: case UNALLOCATED:
unalloc = LUnallocated::cast(this); unalloc = LUnallocated::cast(this);
@ -70,9 +71,6 @@ void LOperand::PrintTo(StringStream* stream) {
case LUnallocated::ANY: case LUnallocated::ANY:
stream->Add("(-)"); stream->Add("(-)");
break; break;
case LUnallocated::IGNORE:
stream->Add("(0)");
break;
} }
break; break;
case CONSTANT_OPERAND: case CONSTANT_OPERAND:

21
deps/v8/src/lithium.h

@ -59,6 +59,7 @@ class LOperand: public ZoneObject {
bool IsDoubleRegister() const { return kind() == DOUBLE_REGISTER; } bool IsDoubleRegister() const { return kind() == DOUBLE_REGISTER; }
bool IsArgument() const { return kind() == ARGUMENT; } bool IsArgument() const { return kind() == ARGUMENT; }
bool IsUnallocated() const { return kind() == UNALLOCATED; } bool IsUnallocated() const { return kind() == UNALLOCATED; }
bool IsIgnored() const { return kind() == INVALID; }
bool Equals(LOperand* other) const { return value_ == other->value_; } bool Equals(LOperand* other) const { return value_ == other->value_; }
int VirtualRegister(); int VirtualRegister();
@ -89,8 +90,7 @@ class LUnallocated: public LOperand {
FIXED_SLOT, FIXED_SLOT,
MUST_HAVE_REGISTER, MUST_HAVE_REGISTER,
WRITABLE_REGISTER, WRITABLE_REGISTER,
SAME_AS_FIRST_INPUT, SAME_AS_FIRST_INPUT
IGNORE
}; };
// Lifetime of operand inside the instruction. // Lifetime of operand inside the instruction.
@ -121,9 +121,9 @@ class LUnallocated: public LOperand {
// The superclass has a KindField. Some policies have a signed fixed // The superclass has a KindField. Some policies have a signed fixed
// index in the upper bits. // index in the upper bits.
static const int kPolicyWidth = 4; static const int kPolicyWidth = 3;
static const int kLifetimeWidth = 1; static const int kLifetimeWidth = 1;
static const int kVirtualRegisterWidth = 17; static const int kVirtualRegisterWidth = 18;
static const int kPolicyShift = kKindFieldWidth; static const int kPolicyShift = kKindFieldWidth;
static const int kLifetimeShift = kPolicyShift + kPolicyWidth; static const int kLifetimeShift = kPolicyShift + kPolicyWidth;
@ -143,12 +143,10 @@ class LUnallocated: public LOperand {
kVirtualRegisterWidth> { kVirtualRegisterWidth> {
}; };
static const int kMaxVirtualRegisters = 1 << (kVirtualRegisterWidth + 1); static const int kMaxVirtualRegisters = 1 << kVirtualRegisterWidth;
static const int kMaxFixedIndex = 63; static const int kMaxFixedIndex = 63;
static const int kMinFixedIndex = -64; static const int kMinFixedIndex = -64;
bool HasIgnorePolicy() const { return policy() == IGNORE; }
bool HasNoPolicy() const { return policy() == NONE; }
bool HasAnyPolicy() const { bool HasAnyPolicy() const {
return policy() == ANY; return policy() == ANY;
} }
@ -234,9 +232,7 @@ class LMoveOperands BASE_EMBEDDED {
} }
bool IsIgnored() const { bool IsIgnored() const {
return destination_ != NULL && return destination_ != NULL && destination_->IsIgnored();
destination_->IsUnallocated() &&
LUnallocated::cast(destination_)->HasIgnorePolicy();
} }
// We clear both operands to indicate move that's been eliminated. // We clear both operands to indicate move that's been eliminated.
@ -443,12 +439,14 @@ class LPointerMap: public ZoneObject {
class LEnvironment: public ZoneObject { class LEnvironment: public ZoneObject {
public: public:
LEnvironment(Handle<JSFunction> closure, LEnvironment(Handle<JSFunction> closure,
bool is_arguments_adaptor,
int ast_id, int ast_id,
int parameter_count, int parameter_count,
int argument_count, int argument_count,
int value_count, int value_count,
LEnvironment* outer) LEnvironment* outer)
: closure_(closure), : closure_(closure),
is_arguments_adaptor_(is_arguments_adaptor),
arguments_stack_height_(argument_count), arguments_stack_height_(argument_count),
deoptimization_index_(Safepoint::kNoDeoptimizationIndex), deoptimization_index_(Safepoint::kNoDeoptimizationIndex),
translation_index_(-1), translation_index_(-1),
@ -505,8 +503,11 @@ class LEnvironment: public ZoneObject {
void PrintTo(StringStream* stream); void PrintTo(StringStream* stream);
bool is_arguments_adaptor() const { return is_arguments_adaptor_; }
private: private:
Handle<JSFunction> closure_; Handle<JSFunction> closure_;
bool is_arguments_adaptor_;
int arguments_stack_height_; int arguments_stack_height_;
int deoptimization_index_; int deoptimization_index_;
int translation_index_; int translation_index_;

13
deps/v8/src/mark-compact-inl.h

@ -66,6 +66,19 @@ void MarkCompactCollector::MarkObject(HeapObject* obj, MarkBit mark_bit) {
} }
bool MarkCompactCollector::MarkObjectWithoutPush(HeapObject* object) {
MarkBit mark = Marking::MarkBitFrom(object);
bool old_mark = mark.Get();
if (!old_mark) SetMark(object, mark);
return old_mark;
}
void MarkCompactCollector::MarkObjectAndPush(HeapObject* object) {
if (!MarkObjectWithoutPush(object)) marking_deque_.PushBlack(object);
}
void MarkCompactCollector::SetMark(HeapObject* obj, MarkBit mark_bit) { void MarkCompactCollector::SetMark(HeapObject* obj, MarkBit mark_bit) {
ASSERT(!mark_bit.Get()); ASSERT(!mark_bit.Get());
ASSERT(Marking::MarkBitFrom(obj) == mark_bit); ASSERT(Marking::MarkBitFrom(obj) == mark_bit);

213
deps/v8/src/mark-compact.cc

@ -710,16 +710,17 @@ class CodeFlusher {
SharedFunctionInfo* candidate) { SharedFunctionInfo* candidate) {
Code* code = candidate->code(); Code* code = candidate->code();
return reinterpret_cast<SharedFunctionInfo**>( return reinterpret_cast<SharedFunctionInfo**>(
code->address() + Code::kNextCodeFlushingCandidateOffset); code->address() + Code::kGCMetadataOffset);
} }
static SharedFunctionInfo* GetNextCandidate(SharedFunctionInfo* candidate) { static SharedFunctionInfo* GetNextCandidate(SharedFunctionInfo* candidate) {
return *GetNextCandidateField(candidate); return reinterpret_cast<SharedFunctionInfo*>(
candidate->code()->gc_metadata());
} }
static void SetNextCandidate(SharedFunctionInfo* candidate, static void SetNextCandidate(SharedFunctionInfo* candidate,
SharedFunctionInfo* next_candidate) { SharedFunctionInfo* next_candidate) {
*GetNextCandidateField(candidate) = next_candidate; candidate->code()->set_gc_metadata(next_candidate);
} }
Isolate* isolate_; Isolate* isolate_;
@ -1672,6 +1673,16 @@ void MarkCompactCollector::MarkMapContents(Map* map) {
} }
void MarkCompactCollector::MarkAccessorPairSlot(HeapObject* accessors,
int offset) {
Object** slot = HeapObject::RawField(accessors, offset);
HeapObject* accessor = HeapObject::cast(*slot);
if (accessor->IsMap()) return;
RecordSlot(slot, slot, accessor);
MarkObjectAndPush(accessor);
}
void MarkCompactCollector::MarkDescriptorArray( void MarkCompactCollector::MarkDescriptorArray(
DescriptorArray* descriptors) { DescriptorArray* descriptors) {
MarkBit descriptors_mark = Marking::MarkBitFrom(descriptors); MarkBit descriptors_mark = Marking::MarkBitFrom(descriptors);
@ -1699,27 +1710,37 @@ void MarkCompactCollector::MarkDescriptorArray(
PropertyDetails details(Smi::cast(contents->get(i + 1))); PropertyDetails details(Smi::cast(contents->get(i + 1)));
Object** slot = contents->data_start() + i; Object** slot = contents->data_start() + i;
Object* value = *slot; if (!(*slot)->IsHeapObject()) continue;
if (!value->IsHeapObject()) continue; HeapObject* value = HeapObject::cast(*slot);
RecordSlot(slot, slot, *slot); RecordSlot(slot, slot, *slot);
if (details.IsProperty()) { switch (details.type()) {
HeapObject* object = HeapObject::cast(value); case NORMAL:
MarkBit mark = Marking::MarkBitFrom(HeapObject::cast(object)); case FIELD:
if (!mark.Get()) { case CONSTANT_FUNCTION:
SetMark(HeapObject::cast(object), mark); case HANDLER:
marking_deque_.PushBlack(object); case INTERCEPTOR:
} MarkObjectAndPush(value);
} else if (details.type() == ELEMENTS_TRANSITION && value->IsFixedArray()) { break;
// For maps with multiple elements transitions, the transition maps are case CALLBACKS:
// stored in a FixedArray. Keep the fixed array alive but not the maps if (!value->IsAccessorPair()) {
// that it refers to. MarkObjectAndPush(value);
HeapObject* object = HeapObject::cast(value); } else if (!MarkObjectWithoutPush(value)) {
MarkBit mark = Marking::MarkBitFrom(HeapObject::cast(object)); MarkAccessorPairSlot(value, AccessorPair::kGetterOffset);
if (!mark.Get()) { MarkAccessorPairSlot(value, AccessorPair::kSetterOffset);
SetMark(HeapObject::cast(object), mark); }
} break;
case ELEMENTS_TRANSITION:
// For maps with multiple elements transitions, the transition maps are
// stored in a FixedArray. Keep the fixed array alive but not the maps
// that it refers to.
if (value->IsFixedArray()) MarkObjectWithoutPush(value);
break;
case MAP_TRANSITION:
case CONSTANT_TRANSITION:
case NULL_DESCRIPTOR:
break;
} }
} }
// The DescriptorArray descriptors contains a pointer to its contents array, // The DescriptorArray descriptors contains a pointer to its contents array,
@ -2290,88 +2311,92 @@ void MarkCompactCollector::ClearNonLiveTransitions() {
map->unchecked_constructor()->unchecked_shared()->AttachInitialMap(map); map->unchecked_constructor()->unchecked_shared()->AttachInitialMap(map);
} }
// Clear dead prototype transitions. ClearNonLivePrototypeTransitions(map);
int number_of_transitions = map->NumberOfProtoTransitions(); ClearNonLiveMapTransitions(map, map_mark);
FixedArray* prototype_transitions = map->prototype_transitions(); }
}
int new_number_of_transitions = 0;
const int header = Map::kProtoTransitionHeaderSize;
const int proto_offset = void MarkCompactCollector::ClearNonLivePrototypeTransitions(Map* map) {
header + Map::kProtoTransitionPrototypeOffset; int number_of_transitions = map->NumberOfProtoTransitions();
const int map_offset = header + Map::kProtoTransitionMapOffset; FixedArray* prototype_transitions = map->prototype_transitions();
const int step = Map::kProtoTransitionElementsPerEntry;
for (int i = 0; i < number_of_transitions; i++) { int new_number_of_transitions = 0;
Object* prototype = prototype_transitions->get(proto_offset + i * step); const int header = Map::kProtoTransitionHeaderSize;
Object* cached_map = prototype_transitions->get(map_offset + i * step); const int proto_offset = header + Map::kProtoTransitionPrototypeOffset;
if (IsMarked(prototype) && IsMarked(cached_map)) { const int map_offset = header + Map::kProtoTransitionMapOffset;
int proto_index = proto_offset + new_number_of_transitions * step; const int step = Map::kProtoTransitionElementsPerEntry;
int map_index = map_offset + new_number_of_transitions * step; for (int i = 0; i < number_of_transitions; i++) {
if (new_number_of_transitions != i) { Object* prototype = prototype_transitions->get(proto_offset + i * step);
prototype_transitions->set_unchecked( Object* cached_map = prototype_transitions->get(map_offset + i * step);
heap_, if (IsMarked(prototype) && IsMarked(cached_map)) {
proto_index, int proto_index = proto_offset + new_number_of_transitions * step;
prototype, int map_index = map_offset + new_number_of_transitions * step;
UPDATE_WRITE_BARRIER); if (new_number_of_transitions != i) {
prototype_transitions->set_unchecked( prototype_transitions->set_unchecked(
heap_, heap_,
map_index, proto_index,
cached_map, prototype,
SKIP_WRITE_BARRIER); UPDATE_WRITE_BARRIER);
} prototype_transitions->set_unchecked(
Object** slot = heap_,
HeapObject::RawField(prototype_transitions, map_index,
FixedArray::OffsetOfElementAt(proto_index)); cached_map,
RecordSlot(slot, slot, prototype); SKIP_WRITE_BARRIER);
new_number_of_transitions++;
} }
Object** slot =
HeapObject::RawField(prototype_transitions,
FixedArray::OffsetOfElementAt(proto_index));
RecordSlot(slot, slot, prototype);
new_number_of_transitions++;
} }
}
if (new_number_of_transitions != number_of_transitions) { if (new_number_of_transitions != number_of_transitions) {
map->SetNumberOfProtoTransitions(new_number_of_transitions); map->SetNumberOfProtoTransitions(new_number_of_transitions);
} }
// Fill slots that became free with undefined value. // Fill slots that became free with undefined value.
for (int i = new_number_of_transitions * step; for (int i = new_number_of_transitions * step;
i < number_of_transitions * step; i < number_of_transitions * step;
i++) { i++) {
prototype_transitions->set_undefined(heap_, header + i); prototype_transitions->set_undefined(heap_, header + i);
} }
}
// Follow the chain of back pointers to find the prototype.
Map* current = map;
while (current->IsMap()) {
current = reinterpret_cast<Map*>(current->prototype());
ASSERT(current->IsHeapObject());
}
Object* real_prototype = current;
// Follow back pointers, setting them to prototype, void MarkCompactCollector::ClearNonLiveMapTransitions(Map* map,
// clearing map transitions when necessary. MarkBit map_mark) {
current = map; // Follow the chain of back pointers to find the prototype.
bool on_dead_path = !map_mark.Get(); Map* real_prototype = map;
Object* next; while (real_prototype->IsMap()) {
while (current->IsMap()) { real_prototype = reinterpret_cast<Map*>(real_prototype->prototype());
next = current->prototype(); ASSERT(real_prototype->IsHeapObject());
// There should never be a dead map above a live map. }
MarkBit current_mark = Marking::MarkBitFrom(current);
bool is_alive = current_mark.Get();
ASSERT(on_dead_path || is_alive);
// A live map above a dead map indicates a dead transition. // Follow back pointers, setting them to prototype, clearing map transitions
// This test will always be false on the first iteration. // when necessary.
if (on_dead_path && is_alive) { Map* current = map;
on_dead_path = false; bool current_is_alive = map_mark.Get();
current->ClearNonLiveTransitions(heap(), real_prototype); bool on_dead_path = !current_is_alive;
} while (current->IsMap()) {
*HeapObject::RawField(current, Map::kPrototypeOffset) = Object* next = current->prototype();
real_prototype; // There should never be a dead map above a live map.
ASSERT(on_dead_path || current_is_alive);
if (is_alive) { // A live map above a dead map indicates a dead transition. This test will
Object** slot = HeapObject::RawField(current, Map::kPrototypeOffset); // always be false on the first iteration.
RecordSlot(slot, slot, real_prototype); if (on_dead_path && current_is_alive) {
} on_dead_path = false;
current = reinterpret_cast<Map*>(next); current->ClearNonLiveTransitions(heap(), real_prototype);
} }
Object** slot = HeapObject::RawField(current, Map::kPrototypeOffset);
*slot = real_prototype;
if (current_is_alive) RecordSlot(slot, slot, real_prototype);
current = reinterpret_cast<Map*>(next);
current_is_alive = Marking::MarkBitFrom(current).Get();
} }
} }

6
deps/v8/src/mark-compact.h

@ -628,6 +628,9 @@ class MarkCompactCollector {
// This is for non-incremental marking. // This is for non-incremental marking.
INLINE(void MarkObject(HeapObject* obj, MarkBit mark_bit)); INLINE(void MarkObject(HeapObject* obj, MarkBit mark_bit));
INLINE(bool MarkObjectWithoutPush(HeapObject* object));
INLINE(void MarkObjectAndPush(HeapObject* value));
// Marks the object black. This is for non-incremental marking. // Marks the object black. This is for non-incremental marking.
INLINE(void SetMark(HeapObject* obj, MarkBit mark_bit)); INLINE(void SetMark(HeapObject* obj, MarkBit mark_bit));
@ -645,6 +648,7 @@ class MarkCompactCollector {
// Mark a Map and its DescriptorArray together, skipping transitions. // Mark a Map and its DescriptorArray together, skipping transitions.
void MarkMapContents(Map* map); void MarkMapContents(Map* map);
void MarkAccessorPairSlot(HeapObject* accessors, int offset);
void MarkDescriptorArray(DescriptorArray* descriptors); void MarkDescriptorArray(DescriptorArray* descriptors);
// Mark the heap roots and all objects reachable from them. // Mark the heap roots and all objects reachable from them.
@ -692,6 +696,8 @@ class MarkCompactCollector {
// Map transitions from a live map to a dead map must be killed. // Map transitions from a live map to a dead map must be killed.
// We replace them with a null descriptor, with the same key. // We replace them with a null descriptor, with the same key.
void ClearNonLiveTransitions(); void ClearNonLiveTransitions();
void ClearNonLivePrototypeTransitions(Map* map);
void ClearNonLiveMapTransitions(Map* map, MarkBit map_mark);
// Marking detaches initial maps from SharedFunctionInfo objects // Marking detaches initial maps from SharedFunctionInfo objects
// to make this reference weak. We need to reattach initial maps // to make this reference weak. We need to reattach initial maps

1
deps/v8/src/mips/assembler-mips-inl.h

@ -37,6 +37,7 @@
#define V8_MIPS_ASSEMBLER_MIPS_INL_H_ #define V8_MIPS_ASSEMBLER_MIPS_INL_H_
#include "mips/assembler-mips.h" #include "mips/assembler-mips.h"
#include "cpu.h" #include "cpu.h"
#include "debug.h" #include "debug.h"

55
deps/v8/src/mips/ic-mips.cc

@ -1038,21 +1038,27 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
// Load the key (consisting of map and symbol) from the cache and // Load the key (consisting of map and symbol) from the cache and
// check for match. // check for match.
Label try_second_entry, hit_on_first_entry, load_in_object_property; Label load_in_object_property;
static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket;
Label hit_on_nth_entry[kEntriesPerBucket];
ExternalReference cache_keys = ExternalReference cache_keys =
ExternalReference::keyed_lookup_cache_keys(isolate); ExternalReference::keyed_lookup_cache_keys(isolate);
__ li(t0, Operand(cache_keys)); __ li(t0, Operand(cache_keys));
__ sll(at, a3, kPointerSizeLog2 + 1); __ sll(at, a3, kPointerSizeLog2 + 1);
__ addu(t0, t0, at); __ addu(t0, t0, at);
__ lw(t1, MemOperand(t0));
__ Branch(&try_second_entry, ne, a2, Operand(t1));
__ lw(t1, MemOperand(t0, kPointerSize));
__ Branch(&hit_on_first_entry, eq, a0, Operand(t1));
__ bind(&try_second_entry); for (int i = 0; i < kEntriesPerBucket - 1; i++) {
__ lw(t1, MemOperand(t0, kPointerSize * 2)); Label try_next_entry;
__ lw(t1, MemOperand(t0, kPointerSize * i * 2));
__ Branch(&try_next_entry, ne, a2, Operand(t1));
__ lw(t1, MemOperand(t0, kPointerSize * (i * 2 + 1)));
__ Branch(&hit_on_nth_entry[i], eq, a0, Operand(t1));
__ bind(&try_next_entry);
}
__ lw(t1, MemOperand(t0, kPointerSize * (kEntriesPerBucket - 1) * 2));
__ Branch(&slow, ne, a2, Operand(t1)); __ Branch(&slow, ne, a2, Operand(t1));
__ lw(t1, MemOperand(t0, kPointerSize * 3)); __ lw(t1, MemOperand(t0, kPointerSize * ((kEntriesPerBucket - 1) * 2 + 1)));
__ Branch(&slow, ne, a0, Operand(t1)); __ Branch(&slow, ne, a0, Operand(t1));
// Get field offset. // Get field offset.
@ -1063,25 +1069,20 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
ExternalReference cache_field_offsets = ExternalReference cache_field_offsets =
ExternalReference::keyed_lookup_cache_field_offsets(isolate); ExternalReference::keyed_lookup_cache_field_offsets(isolate);
// Hit on second entry. // Hit on nth entry.
__ li(t0, Operand(cache_field_offsets)); for (int i = kEntriesPerBucket - 1; i >= 0; i--) {
__ sll(at, a3, kPointerSizeLog2); __ bind(&hit_on_nth_entry[i]);
__ addu(at, t0, at); __ li(t0, Operand(cache_field_offsets));
__ lw(t1, MemOperand(at, kPointerSize)); __ sll(at, a3, kPointerSizeLog2);
__ lbu(t2, FieldMemOperand(a2, Map::kInObjectPropertiesOffset)); __ addu(at, t0, at);
__ Subu(t1, t1, t2); __ lw(t1, MemOperand(at, kPointerSize * i));
__ Branch(&property_array_property, ge, t1, Operand(zero_reg)); __ lbu(t2, FieldMemOperand(a2, Map::kInObjectPropertiesOffset));
__ Branch(&load_in_object_property); __ Subu(t1, t1, t2);
__ Branch(&property_array_property, ge, t1, Operand(zero_reg));
// Hit on first entry. if (i != 0) {
__ bind(&hit_on_first_entry); __ Branch(&load_in_object_property);
__ li(t0, Operand(cache_field_offsets)); }
__ sll(at, a3, kPointerSizeLog2); }
__ addu(at, t0, at);
__ lw(t1, MemOperand(at));
__ lbu(t2, FieldMemOperand(a2, Map::kInObjectPropertiesOffset));
__ Subu(t1, t1, t2);
__ Branch(&property_array_property, ge, t1, Operand(zero_reg));
// Load in-object property. // Load in-object property.
__ bind(&load_in_object_property); __ bind(&load_in_object_property);

3
deps/v8/src/objects-inl.h

@ -4042,8 +4042,7 @@ INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset) ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
ACCESSORS(Code, handler_table, FixedArray, kHandlerTableOffset) ACCESSORS(Code, handler_table, FixedArray, kHandlerTableOffset)
ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset) ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset)
ACCESSORS(Code, next_code_flushing_candidate, ACCESSORS(Code, gc_metadata, Object, kGCMetadataOffset)
Object, kNextCodeFlushingCandidateOffset)
byte* Code::instruction_start() { byte* Code::instruction_start() {

55
deps/v8/src/objects.cc

@ -4954,15 +4954,43 @@ class IntrusiveMapTransitionIterator {
Map* Next() { Map* Next() {
ASSERT(IsIterating()); ASSERT(IsIterating());
FixedArray* contents = ContentArray(); FixedArray* contents = ContentArray();
// Attention, tricky index manipulation ahead: Every entry in the contents
// array consists of a value/details pair, so the index is typically even.
// An exception is made for CALLBACKS entries: An even index means we look
// at its getter, and an odd index means we look at its setter.
int index = Smi::cast(*ContentHeader())->value(); int index = Smi::cast(*ContentHeader())->value();
while (index < contents->length()) { while (index < contents->length()) {
int next_index = index + 2; PropertyDetails details(Smi::cast(contents->get(index | 1)));
PropertyDetails details(Smi::cast(contents->get(index + 1))); switch (details.type()) {
if (details.IsTransition()) { case MAP_TRANSITION:
*ContentHeader() = Smi::FromInt(next_index); case CONSTANT_TRANSITION:
return static_cast<Map*>(contents->get(index)); case ELEMENTS_TRANSITION:
// We definitely have a map transition.
*ContentHeader() = Smi::FromInt(index + 2);
return static_cast<Map*>(contents->get(index));
case CALLBACKS: {
// We might have a map transition in a getter or in a setter.
AccessorPair* accessors =
static_cast<AccessorPair*>(contents->get(index & ~1));
Object* accessor =
((index & 1) == 0) ? accessors->getter() : accessors->setter();
index++;
if (accessor->IsMap()) {
*ContentHeader() = Smi::FromInt(index);
return static_cast<Map*>(accessor);
}
break;
}
case NORMAL:
case FIELD:
case CONSTANT_FUNCTION:
case HANDLER:
case INTERCEPTOR:
case NULL_DESCRIPTOR:
// We definitely have no map transition.
index += 2;
break;
} }
index = next_index;
} }
*ContentHeader() = descriptor_array_->GetHeap()->fixed_array_map(); *ContentHeader() = descriptor_array_->GetHeap()->fixed_array_map();
return NULL; return NULL;
@ -8113,8 +8141,11 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint(FILE* out) {
static_cast<Translation::Opcode>(iterator.Next()); static_cast<Translation::Opcode>(iterator.Next());
ASSERT(Translation::BEGIN == opcode); ASSERT(Translation::BEGIN == opcode);
int frame_count = iterator.Next(); int frame_count = iterator.Next();
PrintF(out, " %s {count=%d}\n", Translation::StringFor(opcode), int jsframe_count = iterator.Next();
frame_count); PrintF(out, " %s {frame count=%d, js frame count=%d}\n",
Translation::StringFor(opcode),
frame_count,
jsframe_count);
while (iterator.HasNext() && while (iterator.HasNext() &&
Translation::BEGIN != Translation::BEGIN !=
@ -8126,7 +8157,7 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint(FILE* out) {
UNREACHABLE(); UNREACHABLE();
break; break;
case Translation::FRAME: { case Translation::JS_FRAME: {
int ast_id = iterator.Next(); int ast_id = iterator.Next();
int function_id = iterator.Next(); int function_id = iterator.Next();
JSFunction* function = JSFunction* function =
@ -8138,6 +8169,12 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint(FILE* out) {
break; break;
} }
case Translation::ARGUMENTS_ADAPTOR_FRAME: {
unsigned height = iterator.Next();
PrintF(out, "{arguments adaptor, height=%d}", height);
break;
}
case Translation::DUPLICATE: case Translation::DUPLICATE:
break; break;

11
deps/v8/src/objects.h

@ -4050,11 +4050,10 @@ class Code: public HeapObject {
// [deoptimization_data]: Array containing data for deopt. // [deoptimization_data]: Array containing data for deopt.
DECL_ACCESSORS(deoptimization_data, FixedArray) DECL_ACCESSORS(deoptimization_data, FixedArray)
// [code_flushing_candidate]: Field only used during garbage // [gc_metadata]: Field used to hold GC related metadata. The contents of this
// collection to hold code flushing candidates. The contents of this
// field does not have to be traced during garbage collection since // field does not have to be traced during garbage collection since
// it is only used by the garbage collector itself. // it is only used by the garbage collector itself.
DECL_ACCESSORS(next_code_flushing_candidate, Object) DECL_ACCESSORS(gc_metadata, Object)
// Unchecked accessors to be used during GC. // Unchecked accessors to be used during GC.
inline ByteArray* unchecked_relocation_info(); inline ByteArray* unchecked_relocation_info();
@ -4278,10 +4277,8 @@ class Code: public HeapObject {
static const int kHandlerTableOffset = kRelocationInfoOffset + kPointerSize; static const int kHandlerTableOffset = kRelocationInfoOffset + kPointerSize;
static const int kDeoptimizationDataOffset = static const int kDeoptimizationDataOffset =
kHandlerTableOffset + kPointerSize; kHandlerTableOffset + kPointerSize;
static const int kNextCodeFlushingCandidateOffset = static const int kGCMetadataOffset = kDeoptimizationDataOffset + kPointerSize;
kDeoptimizationDataOffset + kPointerSize; static const int kFlagsOffset = kGCMetadataOffset + kPointerSize;
static const int kFlagsOffset =
kNextCodeFlushingCandidateOffset + kPointerSize;
static const int kKindSpecificFlagsOffset = kFlagsOffset + kIntSize; static const int kKindSpecificFlagsOffset = kFlagsOffset + kIntSize;
static const int kKindSpecificFlagsSize = 2 * kIntSize; static const int kKindSpecificFlagsSize = 2 * kIntSize;

15
deps/v8/src/platform-freebsd.cc

@ -464,15 +464,8 @@ class Thread::PlatformData : public Malloced {
Thread::Thread(const Options& options) Thread::Thread(const Options& options)
: data_(new PlatformData), : data_(new PlatformData),
stack_size_(options.stack_size) { stack_size_(options.stack_size()) {
set_name(options.name); set_name(options.name());
}
Thread::Thread(const char* name)
: data_(new PlatformData),
stack_size_(0) {
set_name(name);
} }
@ -717,8 +710,10 @@ class SignalSender : public Thread {
FULL_INTERVAL FULL_INTERVAL
}; };
static const int kSignalSenderStackSize = 32 * KB;
explicit SignalSender(int interval) explicit SignalSender(int interval)
: Thread("SignalSender"), : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)),
interval_(interval) {} interval_(interval) {}
static void AddActiveSampler(Sampler* sampler) { static void AddActiveSampler(Sampler* sampler) {

15
deps/v8/src/platform-linux.cc

@ -720,15 +720,8 @@ class Thread::PlatformData : public Malloced {
Thread::Thread(const Options& options) Thread::Thread(const Options& options)
: data_(new PlatformData()), : data_(new PlatformData()),
stack_size_(options.stack_size) { stack_size_(options.stack_size()) {
set_name(options.name); set_name(options.name());
}
Thread::Thread(const char* name)
: data_(new PlatformData()),
stack_size_(0) {
set_name(name);
} }
@ -1035,8 +1028,10 @@ class SignalSender : public Thread {
FULL_INTERVAL FULL_INTERVAL
}; };
static const int kSignalSenderStackSize = 32 * KB;
explicit SignalSender(int interval) explicit SignalSender(int interval)
: Thread("SignalSender"), : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)),
vm_tgid_(getpid()), vm_tgid_(getpid()),
interval_(interval) {} interval_(interval) {}

17
deps/v8/src/platform-macos.cc

@ -473,17 +473,11 @@ class Thread::PlatformData : public Malloced {
pthread_t thread_; // Thread handle for pthread. pthread_t thread_; // Thread handle for pthread.
}; };
Thread::Thread(const Options& options)
: data_(new PlatformData),
stack_size_(options.stack_size) {
set_name(options.name);
}
Thread::Thread(const char* name) Thread::Thread(const Options& options)
: data_(new PlatformData), : data_(new PlatformData),
stack_size_(0) { stack_size_(options.stack_size()) {
set_name(name); set_name(options.name());
} }
@ -736,10 +730,13 @@ class Sampler::PlatformData : public Malloced {
thread_act_t profiled_thread_; thread_act_t profiled_thread_;
}; };
class SamplerThread : public Thread { class SamplerThread : public Thread {
public: public:
static const int kSamplerThreadStackSize = 32 * KB;
explicit SamplerThread(int interval) explicit SamplerThread(int interval)
: Thread("SamplerThread"), : Thread(Thread::Options("SamplerThread", kSamplerThreadStackSize)),
interval_(interval) {} interval_(interval) {}
static void AddActiveSampler(Sampler* sampler) { static void AddActiveSampler(Sampler* sampler) {

15
deps/v8/src/platform-openbsd.cc

@ -512,15 +512,8 @@ class Thread::PlatformData : public Malloced {
Thread::Thread(const Options& options) Thread::Thread(const Options& options)
: data_(new PlatformData()), : data_(new PlatformData()),
stack_size_(options.stack_size) { stack_size_(options.stack_size()) {
set_name(options.name); set_name(options.name());
}
Thread::Thread(const char* name)
: data_(new PlatformData()),
stack_size_(0) {
set_name(name);
} }
@ -789,8 +782,10 @@ class SignalSender : public Thread {
FULL_INTERVAL FULL_INTERVAL
}; };
static const int kSignalSenderStackSize = 32 * KB;
explicit SignalSender(int interval) explicit SignalSender(int interval)
: Thread("SignalSender"), : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)),
vm_tgid_(getpid()), vm_tgid_(getpid()),
interval_(interval) {} interval_(interval) {}

54
deps/v8/src/platform-solaris.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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -53,8 +53,8 @@
#include "v8.h" #include "v8.h"
#include "platform.h" #include "platform.h"
#include "vm-state-inl.h"
#include "v8threads.h" #include "v8threads.h"
#include "vm-state-inl.h"
// It seems there is a bug in some Solaris distributions (experienced in // It seems there is a bug in some Solaris distributions (experienced in
@ -84,33 +84,6 @@ namespace internal {
static const pthread_t kNoThread = (pthread_t) 0; static const pthread_t kNoThread = (pthread_t) 0;
static void* GetRandomMmapAddr() {
Isolate* isolate = Isolate::UncheckedCurrent();
// Note that the current isolate isn't set up in a call path via
// CpuFeatures::Probe. We don't care about randomization in this case because
// the code page is immediately freed.
if (isolate != NULL) {
#ifdef V8_TARGET_ARCH_X64
uint64_t rnd1 = V8::RandomPrivate(isolate);
uint64_t rnd2 = V8::RandomPrivate(isolate);
uint64_t raw_addr = (rnd1 << 32) ^ rnd2;
// Currently available CPUs have 48 bits of virtual addressing. Truncate
// the hint address to 46 bits to give the kernel a fighting chance of
// fulfilling our placement request.
raw_addr &= V8_UINT64_C(0x3ffffffff000);
#else
uint32_t raw_addr = V8::RandomPrivate(isolate);
// The range 0x20000000 - 0x60000000 is relatively unpopulated across a
// variety of ASLR modes (PAE kernel, NX compat mode, etc).
raw_addr &= 0x3ffff000;
raw_addr += 0x20000000;
#endif
return reinterpret_cast<void*>(raw_addr);
}
return NULL;
}
double ceiling(double x) { double ceiling(double x) {
return ceil(x); return ceil(x);
} }
@ -167,7 +140,7 @@ double OS::LocalTimeOffset() {
// We keep the lowest and highest addresses mapped as a quick way of // We keep the lowest and highest addresses mapped as a quick way of
// determining that pointers are outside the heap (used mostly in assertions // determining that pointers are outside the heap (used mostly in assertions
// and verification). The estimate is conservative, ie, not all addresses in // and verification). The estimate is conservative, i.e., not all addresses in
// 'allocated' space are actually allocated to our heap. The range is // 'allocated' space are actually allocated to our heap. The range is
// [lowest, highest), inclusive on the low and and exclusive on the high end. // [lowest, highest), inclusive on the low and and exclusive on the high end.
static void* lowest_ever_allocated = reinterpret_cast<void*>(-1); static void* lowest_ever_allocated = reinterpret_cast<void*>(-1);
@ -363,7 +336,7 @@ VirtualMemory::VirtualMemory(size_t size, size_t alignment)
ASSERT(IsAligned(alignment, static_cast<intptr_t>(OS::AllocateAlignment()))); ASSERT(IsAligned(alignment, static_cast<intptr_t>(OS::AllocateAlignment())));
size_t request_size = RoundUp(size + alignment, size_t request_size = RoundUp(size + alignment,
static_cast<intptr_t>(OS::AllocateAlignment())); static_cast<intptr_t>(OS::AllocateAlignment()));
void* reservation = mmap(GetRandomMmapAddr(), void* reservation = mmap(OS::GetRandomMmapAddr(),
request_size, request_size,
PROT_NONE, PROT_NONE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
@ -429,7 +402,7 @@ bool VirtualMemory::Uncommit(void* address, size_t size) {
void* VirtualMemory::ReserveRegion(size_t size) { void* VirtualMemory::ReserveRegion(size_t size) {
void* result = mmap(GetRandomMmapAddr(), void* result = mmap(OS::GetRandomMmapAddr(),
size, size,
PROT_NONE, PROT_NONE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
@ -480,17 +453,11 @@ class Thread::PlatformData : public Malloced {
pthread_t thread_; // Thread handle for pthread. pthread_t thread_; // Thread handle for pthread.
}; };
Thread::Thread(const Options& options)
: data_(new PlatformData()),
stack_size_(options.stack_size) {
set_name(options.name);
}
Thread::Thread(const char* name) Thread::Thread(const Options& options)
: data_(new PlatformData()), : data_(new PlatformData()),
stack_size_(0) { stack_size_(options.stack_size()) {
set_name(name); set_name(options.name());
} }
@ -737,8 +704,10 @@ class SignalSender : public Thread {
FULL_INTERVAL FULL_INTERVAL
}; };
static const int kSignalSenderStackSize = 32 * KB;
explicit SignalSender(int interval) explicit SignalSender(int interval)
: Thread("SignalSender"), : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)),
interval_(interval) {} interval_(interval) {}
static void InstallSignalHandler() { static void InstallSignalHandler() {
@ -870,6 +839,7 @@ class SignalSender : public Thread {
static bool signal_handler_installed_; static bool signal_handler_installed_;
static struct sigaction old_signal_handler_; static struct sigaction old_signal_handler_;
private:
DISALLOW_COPY_AND_ASSIGN(SignalSender); DISALLOW_COPY_AND_ASSIGN(SignalSender);
}; };

15
deps/v8/src/platform-win32.cc

@ -1526,16 +1526,9 @@ class Thread::PlatformData : public Malloced {
// handle until it is started. // handle until it is started.
Thread::Thread(const Options& options) Thread::Thread(const Options& options)
: stack_size_(options.stack_size) { : stack_size_(options.stack_size()) {
data_ = new PlatformData(kNoThread); data_ = new PlatformData(kNoThread);
set_name(options.name); set_name(options.name());
}
Thread::Thread(const char* name)
: stack_size_(0) {
data_ = new PlatformData(kNoThread);
set_name(name);
} }
@ -1901,8 +1894,10 @@ class Sampler::PlatformData : public Malloced {
class SamplerThread : public Thread { class SamplerThread : public Thread {
public: public:
static const int kSamplerThreadStackSize = 32 * KB;
explicit SamplerThread(int interval) explicit SamplerThread(int interval)
: Thread("SamplerThread"), : Thread(Thread::Options("SamplerThread", kSamplerThreadStackSize)),
interval_(interval) {} interval_(interval) {}
static void AddActiveSampler(Sampler* sampler) { static void AddActiveSampler(Sampler* sampler) {

16
deps/v8/src/platform.h

@ -412,16 +412,22 @@ class Thread {
LOCAL_STORAGE_KEY_MAX_VALUE = kMaxInt LOCAL_STORAGE_KEY_MAX_VALUE = kMaxInt
}; };
struct Options { class Options {
Options() : name("v8:<unknown>"), stack_size(0) {} public:
Options() : name_("v8:<unknown>"), stack_size_(0) {}
Options(const char* name, int stack_size = 0)
: name_(name), stack_size_(stack_size) {}
const char* name() const { return name_; }
int stack_size() const { return stack_size_; }
const char* name; private:
int stack_size; const char* name_;
int stack_size_;
}; };
// Create new thread. // Create new thread.
explicit Thread(const Options& options); explicit Thread(const Options& options);
explicit Thread(const char* name);
virtual ~Thread(); virtual ~Thread();
// Start new thread by calling the Run() method in the new thread. // Start new thread by calling the Run() method in the new thread.

124
deps/v8/src/runtime.cc

@ -8126,13 +8126,15 @@ static SmartArrayPointer<Handle<Object> > GetCallerArguments(
List<JSFunction*> functions(2); List<JSFunction*> functions(2);
frame->GetFunctions(&functions); frame->GetFunctions(&functions);
if (functions.length() > 1) { if (functions.length() > 1) {
int inlined_frame_index = functions.length() - 1; int inlined_jsframe_index = functions.length() - 1;
JSFunction* inlined_function = functions[inlined_frame_index]; JSFunction* inlined_function = functions[inlined_jsframe_index];
int args_count = inlined_function->shared()->formal_parameter_count(); Vector<SlotRef> args_slots =
ScopedVector<SlotRef> args_slots(args_count); SlotRef::ComputeSlotMappingForArguments(
SlotRef::ComputeSlotMappingForArguments(frame, frame,
inlined_frame_index, inlined_jsframe_index,
&args_slots); inlined_function->shared()->formal_parameter_count());
int args_count = args_slots.length();
*total_argc = prefix_argc + args_count; *total_argc = prefix_argc + args_count;
SmartArrayPointer<Handle<Object> > param_data( SmartArrayPointer<Handle<Object> > param_data(
@ -8141,6 +8143,9 @@ static SmartArrayPointer<Handle<Object> > GetCallerArguments(
Handle<Object> val = args_slots[i].GetValue(); Handle<Object> val = args_slots[i].GetValue();
param_data[prefix_argc + i] = val; param_data[prefix_argc + i] = val;
} }
args_slots.Dispose();
return param_data; return param_data;
} else { } else {
it.AdvanceToArgumentsFrame(); it.AdvanceToArgumentsFrame();
@ -8486,14 +8491,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyDeoptimized) {
static_cast<Deoptimizer::BailoutType>(args.smi_at(0)); static_cast<Deoptimizer::BailoutType>(args.smi_at(0));
Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate); Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
ASSERT(isolate->heap()->IsAllocationAllowed()); ASSERT(isolate->heap()->IsAllocationAllowed());
int frames = deoptimizer->output_count(); int jsframes = deoptimizer->jsframe_count();
deoptimizer->MaterializeHeapNumbers(); deoptimizer->MaterializeHeapNumbers();
delete deoptimizer; delete deoptimizer;
JavaScriptFrameIterator it(isolate); JavaScriptFrameIterator it(isolate);
JavaScriptFrame* frame = NULL; JavaScriptFrame* frame = NULL;
for (int i = 0; i < frames - 1; i++) it.Advance(); for (int i = 0; i < jsframes - 1; i++) it.Advance();
frame = it.frame(); frame = it.frame();
RUNTIME_ASSERT(frame->function()->IsJSFunction()); RUNTIME_ASSERT(frame->function()->IsJSFunction());
@ -10703,13 +10708,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameCount) {
class FrameInspector { class FrameInspector {
public: public:
FrameInspector(JavaScriptFrame* frame, FrameInspector(JavaScriptFrame* frame,
int inlined_frame_index, int inlined_jsframe_index,
Isolate* isolate) Isolate* isolate)
: frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) { : frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) {
// Calculate the deoptimized frame. // Calculate the deoptimized frame.
if (frame->is_optimized()) { if (frame->is_optimized()) {
deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame( deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame(
frame, inlined_frame_index, isolate); frame, inlined_jsframe_index, isolate);
} }
has_adapted_arguments_ = frame_->has_adapted_arguments(); has_adapted_arguments_ = frame_->has_adapted_arguments();
is_optimized_ = frame_->is_optimized(); is_optimized_ = frame_->is_optimized();
@ -10825,8 +10830,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
return heap->undefined_value(); return heap->undefined_value();
} }
int inlined_frame_index = 0; // Inlined frame index in optimized frame.
int count = 0; int count = 0;
JavaScriptFrameIterator it(isolate, id); JavaScriptFrameIterator it(isolate, id);
for (; !it.done(); it.Advance()) { for (; !it.done(); it.Advance()) {
@ -10835,11 +10838,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
} }
if (it.done()) return heap->undefined_value(); if (it.done()) return heap->undefined_value();
if (it.frame()->is_optimized()) { bool is_optimized = it.frame()->is_optimized();
inlined_frame_index =
int inlined_jsframe_index = 0; // Inlined frame index in optimized frame.
if (is_optimized) {
inlined_jsframe_index =
it.frame()->GetInlineCount() - (index - count) - 1; it.frame()->GetInlineCount() - (index - count) - 1;
} }
FrameInspector frame_inspector(it.frame(), inlined_frame_index, isolate); FrameInspector frame_inspector(it.frame(), inlined_jsframe_index, isolate);
// Traverse the saved contexts chain to find the active context for the // Traverse the saved contexts chain to find the active context for the
// selected frame. // selected frame.
@ -10853,12 +10859,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
it.frame()->LookupCode()->SourcePosition(it.frame()->pc()); it.frame()->LookupCode()->SourcePosition(it.frame()->pc());
// Check for constructor frame. Inlined frames cannot be construct calls. // Check for constructor frame. Inlined frames cannot be construct calls.
bool inlined_frame = bool inlined_frame = is_optimized && inlined_jsframe_index != 0;
it.frame()->is_optimized() && inlined_frame_index != 0;
bool constructor = !inlined_frame && it.frame()->IsConstructor(); bool constructor = !inlined_frame && it.frame()->IsConstructor();
// Get scope info and read from it for local variable information. // Get scope info and read from it for local variable information.
Handle<JSFunction> function(JSFunction::cast(it.frame()->function())); Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
Handle<SharedFunctionInfo> shared(function->shared()); Handle<SharedFunctionInfo> shared(function->shared());
Handle<ScopeInfo> scope_info(shared->scope_info()); Handle<ScopeInfo> scope_info(shared->scope_info());
ASSERT(*scope_info != ScopeInfo::Empty()); ASSERT(*scope_info != ScopeInfo::Empty());
@ -10895,7 +10900,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
// Check whether this frame is positioned at return. If not top // Check whether this frame is positioned at return. If not top
// frame or if the frame is optimized it cannot be at a return. // frame or if the frame is optimized it cannot be at a return.
bool at_return = false; bool at_return = false;
if (!it.frame()->is_optimized() && index == 0) { if (!is_optimized && index == 0) {
at_return = isolate->debug()->IsBreakAtReturn(it.frame()); at_return = isolate->debug()->IsBreakAtReturn(it.frame());
} }
@ -10935,7 +10940,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
// the provided parameters whereas the function frame always have the number // the provided parameters whereas the function frame always have the number
// of arguments matching the functions parameters. The rest of the // of arguments matching the functions parameters. The rest of the
// information (except for what is collected above) is the same. // information (except for what is collected above) is the same.
if (it.frame()->has_adapted_arguments()) { if ((inlined_jsframe_index == 0) && it.frame()->has_adapted_arguments()) {
it.AdvanceToArgumentsFrame(); it.AdvanceToArgumentsFrame();
frame_inspector.SetArgumentsFrame(it.frame()); frame_inspector.SetArgumentsFrame(it.frame());
} }
@ -10946,11 +10951,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
if (argument_count < frame_inspector.GetParametersCount()) { if (argument_count < frame_inspector.GetParametersCount()) {
argument_count = frame_inspector.GetParametersCount(); argument_count = frame_inspector.GetParametersCount();
} }
#ifdef DEBUG
if (it.frame()->is_optimized()) {
ASSERT_EQ(argument_count, frame_inspector.GetParametersCount());
}
#endif
// Calculate the size of the result. // Calculate the size of the result.
int details_size = kFrameDetailsFirstDynamicIndex + int details_size = kFrameDetailsFirstDynamicIndex +
@ -10992,9 +10992,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
if (*save->context() == *isolate->debug()->debug_context()) { if (*save->context() == *isolate->debug()->debug_context()) {
flags |= 1 << 0; flags |= 1 << 0;
} }
if (it.frame()->is_optimized()) { if (is_optimized) {
flags |= 1 << 1; flags |= 1 << 1;
flags |= inlined_frame_index << 2; flags |= inlined_jsframe_index << 2;
} }
details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags)); details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
@ -11011,7 +11011,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
} }
// Parameter value. // Parameter value.
if (i < it.frame()->ComputeParametersCount()) { if (i < frame_inspector.GetParametersCount()) {
// Get the value from the stack. // Get the value from the stack.
details->set(details_index++, frame_inspector.GetParameter(i)); details->set(details_index++, frame_inspector.GetParameter(i));
} else { } else {
@ -11084,14 +11084,13 @@ static bool CopyContextLocalsToScopeObject(
// Create a plain JSObject which materializes the local scope for the specified // Create a plain JSObject which materializes the local scope for the specified
// frame. // frame.
static Handle<JSObject> MaterializeLocalScope( static Handle<JSObject> MaterializeLocalScopeWithFrameInspector(
Isolate* isolate, Isolate* isolate,
JavaScriptFrame* frame, JavaScriptFrame* frame,
int inlined_frame_index) { FrameInspector* frame_inspector) {
Handle<JSFunction> function(JSFunction::cast(frame->function())); Handle<JSFunction> function(JSFunction::cast(frame_inspector->GetFunction()));
Handle<SharedFunctionInfo> shared(function->shared()); Handle<SharedFunctionInfo> shared(function->shared());
Handle<ScopeInfo> scope_info(shared->scope_info()); Handle<ScopeInfo> scope_info(shared->scope_info());
FrameInspector frame_inspector(frame, inlined_frame_index, isolate);
// Allocate and initialize a JSObject with all the arguments, stack locals // Allocate and initialize a JSObject with all the arguments, stack locals
// heap locals and extension properties of the debugged function. // heap locals and extension properties of the debugged function.
@ -11100,11 +11099,15 @@ static Handle<JSObject> MaterializeLocalScope(
// First fill all parameters. // First fill all parameters.
for (int i = 0; i < scope_info->ParameterCount(); ++i) { for (int i = 0; i < scope_info->ParameterCount(); ++i) {
Handle<Object> value(
i < frame_inspector->GetParametersCount() ?
frame_inspector->GetParameter(i) : isolate->heap()->undefined_value());
RETURN_IF_EMPTY_HANDLE_VALUE( RETURN_IF_EMPTY_HANDLE_VALUE(
isolate, isolate,
SetProperty(local_scope, SetProperty(local_scope,
Handle<String>(scope_info->ParameterName(i)), Handle<String>(scope_info->ParameterName(i)),
Handle<Object>(frame_inspector.GetParameter(i)), value,
NONE, NONE,
kNonStrictMode), kNonStrictMode),
Handle<JSObject>()); Handle<JSObject>());
@ -11116,7 +11119,7 @@ static Handle<JSObject> MaterializeLocalScope(
isolate, isolate,
SetProperty(local_scope, SetProperty(local_scope,
Handle<String>(scope_info->StackLocalName(i)), Handle<String>(scope_info->StackLocalName(i)),
Handle<Object>(frame_inspector.GetExpression(i)), Handle<Object>(frame_inspector->GetExpression(i)),
NONE, NONE,
kNonStrictMode), kNonStrictMode),
Handle<JSObject>()); Handle<JSObject>());
@ -11163,6 +11166,17 @@ static Handle<JSObject> MaterializeLocalScope(
} }
static Handle<JSObject> MaterializeLocalScope(
Isolate* isolate,
JavaScriptFrame* frame,
int inlined_jsframe_index) {
FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
return MaterializeLocalScopeWithFrameInspector(isolate,
frame,
&frame_inspector);
}
// Create a plain JSObject which materializes the closure content for the // Create a plain JSObject which materializes the closure content for the
// context. // context.
static Handle<JSObject> MaterializeClosure(Isolate* isolate, static Handle<JSObject> MaterializeClosure(Isolate* isolate,
@ -11268,10 +11282,10 @@ class ScopeIterator {
ScopeIterator(Isolate* isolate, ScopeIterator(Isolate* isolate,
JavaScriptFrame* frame, JavaScriptFrame* frame,
int inlined_frame_index) int inlined_jsframe_index)
: isolate_(isolate), : isolate_(isolate),
frame_(frame), frame_(frame),
inlined_frame_index_(inlined_frame_index), inlined_jsframe_index_(inlined_jsframe_index),
function_(JSFunction::cast(frame->function())), function_(JSFunction::cast(frame->function())),
context_(Context::cast(frame->context())), context_(Context::cast(frame->context())),
nested_scope_chain_(4) { nested_scope_chain_(4) {
@ -11428,7 +11442,7 @@ class ScopeIterator {
case ScopeIterator::ScopeTypeLocal: case ScopeIterator::ScopeTypeLocal:
// Materialize the content of the local scope into a JSObject. // Materialize the content of the local scope into a JSObject.
ASSERT(nested_scope_chain_.length() == 1); ASSERT(nested_scope_chain_.length() == 1);
return MaterializeLocalScope(isolate_, frame_, inlined_frame_index_); return MaterializeLocalScope(isolate_, frame_, inlined_jsframe_index_);
case ScopeIterator::ScopeTypeWith: case ScopeIterator::ScopeTypeWith:
// Return the with object. // Return the with object.
return Handle<JSObject>(JSObject::cast(CurrentContext()->extension())); return Handle<JSObject>(JSObject::cast(CurrentContext()->extension()));
@ -11524,7 +11538,7 @@ class ScopeIterator {
private: private:
Isolate* isolate_; Isolate* isolate_;
JavaScriptFrame* frame_; JavaScriptFrame* frame_;
int inlined_frame_index_; int inlined_jsframe_index_;
Handle<JSFunction> function_; Handle<JSFunction> function_;
Handle<Context> context_; Handle<Context> context_;
List<Handle<ScopeInfo> > nested_scope_chain_; List<Handle<ScopeInfo> > nested_scope_chain_;
@ -11586,7 +11600,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
if (!maybe_check->ToObject(&check)) return maybe_check; if (!maybe_check->ToObject(&check)) return maybe_check;
} }
CONVERT_CHECKED(Smi, wrapped_id, args[1]); CONVERT_CHECKED(Smi, wrapped_id, args[1]);
CONVERT_NUMBER_CHECKED(int, inlined_frame_index, Int32, args[2]); CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]); CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
// Get the frame where the debugging is performed. // Get the frame where the debugging is performed.
@ -11596,7 +11610,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
// Find the requested scope. // Find the requested scope.
int n = 0; int n = 0;
ScopeIterator it(isolate, frame, inlined_frame_index); ScopeIterator it(isolate, frame, inlined_jsframe_index);
for (; !it.Done() && n < index; it.Next()) { for (; !it.Done() && n < index; it.Next()) {
n++; n++;
} }
@ -11994,12 +12008,12 @@ static Handle<Context> CopyNestedScopeContextChain(Isolate* isolate,
Handle<JSFunction> function, Handle<JSFunction> function,
Handle<Context> base, Handle<Context> base,
JavaScriptFrame* frame, JavaScriptFrame* frame,
int inlined_frame_index) { int inlined_jsframe_index) {
HandleScope scope(isolate); HandleScope scope(isolate);
List<Handle<ScopeInfo> > scope_chain; List<Handle<ScopeInfo> > scope_chain;
List<Handle<Context> > context_chain; List<Handle<Context> > context_chain;
ScopeIterator it(isolate, frame, inlined_frame_index); ScopeIterator it(isolate, frame, inlined_jsframe_index);
for (; it.Type() != ScopeIterator::ScopeTypeGlobal && for (; it.Type() != ScopeIterator::ScopeTypeGlobal &&
it.Type() != ScopeIterator::ScopeTypeLocal ; it.Next()) { it.Type() != ScopeIterator::ScopeTypeLocal ; it.Next()) {
ASSERT(!it.Done()); ASSERT(!it.Done());
@ -12056,8 +12070,7 @@ static Handle<Context> CopyNestedScopeContextChain(Isolate* isolate,
// Runtime_DebugEvaluate. // Runtime_DebugEvaluate.
static Handle<Object> GetArgumentsObject(Isolate* isolate, static Handle<Object> GetArgumentsObject(Isolate* isolate,
JavaScriptFrame* frame, JavaScriptFrame* frame,
int inlined_frame_index, FrameInspector* frame_inspector,
Handle<JSFunction> function,
Handle<ScopeInfo> scope_info, Handle<ScopeInfo> scope_info,
Handle<Context> function_context) { Handle<Context> function_context) {
// Try to find the value of 'arguments' to pass as parameter. If it is not // Try to find the value of 'arguments' to pass as parameter. If it is not
@ -12081,9 +12094,8 @@ static Handle<Object> GetArgumentsObject(Isolate* isolate,
} }
} }
FrameInspector frame_inspector(frame, inlined_frame_index, isolate); Handle<JSFunction> function(JSFunction::cast(frame_inspector->GetFunction()));
int length = frame_inspector->GetParametersCount();
int length = frame_inspector.GetParametersCount();
Handle<JSObject> arguments = Handle<JSObject> arguments =
isolate->factory()->NewArgumentsObject(function, length); isolate->factory()->NewArgumentsObject(function, length);
Handle<FixedArray> array = isolate->factory()->NewFixedArray(length); Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
@ -12091,7 +12103,7 @@ static Handle<Object> GetArgumentsObject(Isolate* isolate,
AssertNoAllocation no_gc; AssertNoAllocation no_gc;
WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc); WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
array->set(i, frame_inspector.GetParameter(i), mode); array->set(i, frame_inspector->GetParameter(i), mode);
} }
arguments->set_elements(*array); arguments->set_elements(*array);
return arguments; return arguments;
@ -12127,7 +12139,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
} }
} }
CONVERT_CHECKED(Smi, wrapped_id, args[1]); CONVERT_CHECKED(Smi, wrapped_id, args[1]);
CONVERT_NUMBER_CHECKED(int, inlined_frame_index, Int32, args[2]); CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
CONVERT_ARG_CHECKED(String, source, 3); CONVERT_ARG_CHECKED(String, source, 3);
CONVERT_BOOLEAN_CHECKED(disable_break, args[4]); CONVERT_BOOLEAN_CHECKED(disable_break, args[4]);
Handle<Object> additional_context(args[5]); Handle<Object> additional_context(args[5]);
@ -12139,7 +12151,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
StackFrame::Id id = UnwrapFrameId(wrapped_id); StackFrame::Id id = UnwrapFrameId(wrapped_id);
JavaScriptFrameIterator it(isolate, id); JavaScriptFrameIterator it(isolate, id);
JavaScriptFrame* frame = it.frame(); JavaScriptFrame* frame = it.frame();
Handle<JSFunction> function(JSFunction::cast(frame->function())); FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
Handle<ScopeInfo> scope_info(function->shared()->scope_info()); Handle<ScopeInfo> scope_info(function->shared()->scope_info());
// Traverse the saved contexts chain to find the active context for the // Traverse the saved contexts chain to find the active context for the
@ -12166,8 +12179,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
#endif #endif
// Materialize the content of the local scope into a JSObject. // Materialize the content of the local scope into a JSObject.
Handle<JSObject> local_scope = MaterializeLocalScope( Handle<JSObject> local_scope = MaterializeLocalScopeWithFrameInspector(
isolate, frame, inlined_frame_index); isolate, frame, &frame_inspector);
RETURN_IF_EMPTY_HANDLE(isolate, local_scope); RETURN_IF_EMPTY_HANDLE(isolate, local_scope);
// Allocate a new context for the debug evaluation and set the extension // Allocate a new context for the debug evaluation and set the extension
@ -12187,7 +12200,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
go_between, go_between,
context, context,
frame, frame,
inlined_frame_index); inlined_jsframe_index);
if (additional_context->IsJSObject()) { if (additional_context->IsJSObject()) {
Handle<JSObject> extension = Handle<JSObject>::cast(additional_context); Handle<JSObject> extension = Handle<JSObject>::cast(additional_context);
@ -12227,8 +12240,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
Handle<Object> arguments = GetArgumentsObject(isolate, Handle<Object> arguments = GetArgumentsObject(isolate,
frame, frame,
inlined_frame_index, &frame_inspector,
function,
scope_info, scope_info,
function_context); function_context);

32
deps/v8/src/serialize.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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -1081,36 +1081,6 @@ void SnapshotByteSink::PutInt(uintptr_t integer, const char* description) {
PutSection(static_cast<int>(integer & 0x7f), "IntLastPart"); PutSection(static_cast<int>(integer & 0x7f), "IntLastPart");
} }
#ifdef DEBUG
void Deserializer::Synchronize(const char* tag) {
int data = source_->Get();
// If this assert fails then that indicates that you have a mismatch between
// the number of GC roots when serializing and deserializing.
ASSERT_EQ(kSynchronize, data);
do {
int character = source_->Get();
if (character == 0) break;
if (FLAG_debug_serialization) {
PrintF("%c", character);
}
} while (true);
if (FLAG_debug_serialization) {
PrintF("\n");
}
}
void Serializer::Synchronize(const char* tag) {
sink_->Put(kSynchronize, tag);
int character;
do {
character = *tag++;
sink_->PutSection(character, "TagCharacter");
} while (character != 0);
}
#endif
Serializer::Serializer(SnapshotByteSink* sink) Serializer::Serializer(SnapshotByteSink* sink)
: sink_(sink), : sink_(sink),

7
deps/v8/src/serialize.h

@ -341,10 +341,6 @@ class Deserializer: public SerializerDeserializer {
// Deserialize a single object and the objects reachable from it. // Deserialize a single object and the objects reachable from it.
void DeserializePartial(Object** root); void DeserializePartial(Object** root);
#ifdef DEBUG
virtual void Synchronize(const char* tag);
#endif
private: private:
virtual void VisitPointers(Object** start, Object** end); virtual void VisitPointers(Object** start, Object** end);
@ -485,9 +481,6 @@ class Serializer : public SerializerDeserializer {
SerializationAddressMapper* address_mapper() { return &address_mapper_; } SerializationAddressMapper* address_mapper() { return &address_mapper_; }
void PutRoot( void PutRoot(
int index, HeapObject* object, HowToCode how, WhereToPoint where); int index, HeapObject* object, HowToCode how, WhereToPoint where);
#ifdef DEBUG
virtual void Synchronize(const char* tag);
#endif
protected: protected:
static const int kInvalidRootIndex = -1; static const int kInvalidRootIndex = -1;

22
deps/v8/src/spaces.cc

@ -922,14 +922,13 @@ bool NewSpace::SetUp(int reserved_semispace_capacity,
2 * heap()->ReservedSemiSpaceSize()); 2 * heap()->ReservedSemiSpaceSize());
ASSERT(IsAddressAligned(chunk_base_, 2 * reserved_semispace_capacity, 0)); ASSERT(IsAddressAligned(chunk_base_, 2 * reserved_semispace_capacity, 0));
if (!to_space_.SetUp(chunk_base_, to_space_.SetUp(chunk_base_,
initial_semispace_capacity, initial_semispace_capacity,
maximum_semispace_capacity)) { maximum_semispace_capacity);
return false; from_space_.SetUp(chunk_base_ + reserved_semispace_capacity,
} initial_semispace_capacity,
if (!from_space_.SetUp(chunk_base_ + reserved_semispace_capacity, maximum_semispace_capacity);
initial_semispace_capacity, if (!to_space_.Commit()) {
maximum_semispace_capacity)) {
return false; return false;
} }
@ -1162,7 +1161,7 @@ void NewSpace::Verify() {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// SemiSpace implementation // SemiSpace implementation
bool SemiSpace::SetUp(Address start, void SemiSpace::SetUp(Address start,
int initial_capacity, int initial_capacity,
int maximum_capacity) { int maximum_capacity) {
// Creates a space in the young generation. The constructor does not // Creates a space in the young generation. The constructor does not
@ -1181,8 +1180,6 @@ bool SemiSpace::SetUp(Address start,
object_mask_ = address_mask_ | kHeapObjectTagMask; object_mask_ = address_mask_ | kHeapObjectTagMask;
object_expected_ = reinterpret_cast<uintptr_t>(start) | kHeapObjectTag; object_expected_ = reinterpret_cast<uintptr_t>(start) | kHeapObjectTag;
age_mark_ = start_; age_mark_ = start_;
return Commit();
} }
@ -1232,6 +1229,9 @@ bool SemiSpace::Uncommit() {
bool SemiSpace::GrowTo(int new_capacity) { bool SemiSpace::GrowTo(int new_capacity) {
if (!is_committed()) {
if (!Commit()) return false;
}
ASSERT((new_capacity & Page::kPageAlignmentMask) == 0); ASSERT((new_capacity & Page::kPageAlignmentMask) == 0);
ASSERT(new_capacity <= maximum_capacity_); ASSERT(new_capacity <= maximum_capacity_);
ASSERT(new_capacity > capacity_); ASSERT(new_capacity > capacity_);

2
deps/v8/src/spaces.h

@ -1834,7 +1834,7 @@ class SemiSpace : public Space {
current_page_(NULL) { } current_page_(NULL) { }
// Sets up the semispace using the given chunk. // Sets up the semispace using the given chunk.
bool SetUp(Address start, int initial_capacity, int maximum_capacity); void SetUp(Address start, int initial_capacity, int maximum_capacity);
// Tear down the space. Heap memory was not allocated by the space, so it // Tear down the space. Heap memory was not allocated by the space, so it
// is not deallocated here. // is not deallocated here.

3
deps/v8/src/type-info.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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -223,6 +223,7 @@ class CaseClause;
class CompareOperation; class CompareOperation;
class CompilationInfo; class CompilationInfo;
class CountOperation; class CountOperation;
class Expression;
class Property; class Property;
class SmallMapList; class SmallMapList;
class UnaryOperation; class UnaryOperation;

19
deps/v8/src/v8globals.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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -107,14 +107,12 @@ const uint32_t kQuietNaNHighBitsMask = 0xfff << (51 - 32);
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Forward declarations for frequently used classes // Forward declarations for frequently used classes
// (sorted alphabetically)
class AccessorInfo; class AccessorInfo;
class Allocation; class Allocation;
class Arguments; class Arguments;
class Assembler; class Assembler;
class AssertNoAllocation; class AssertNoAllocation;
class BreakableStatement;
class Code; class Code;
class CodeGenerator; class CodeGenerator;
class CodeStub; class CodeStub;
@ -124,10 +122,8 @@ class Debugger;
class DebugInfo; class DebugInfo;
class Descriptor; class Descriptor;
class DescriptorArray; class DescriptorArray;
class Expression;
class ExternalReference; class ExternalReference;
class FixedArray; class FixedArray;
class FunctionLiteral;
class FunctionTemplateInfo; class FunctionTemplateInfo;
class MemoryChunk; class MemoryChunk;
class SeededNumberDictionary; class SeededNumberDictionary;
@ -138,7 +134,6 @@ class Heap;
class HeapObject; class HeapObject;
class IC; class IC;
class InterceptorInfo; class InterceptorInfo;
class IterationStatement;
class JSArray; class JSArray;
class JSFunction; class JSFunction;
class JSObject; class JSObject;
@ -149,31 +144,19 @@ class Map;
class MapSpace; class MapSpace;
class MarkCompactCollector; class MarkCompactCollector;
class NewSpace; class NewSpace;
class NodeVisitor;
class Object; class Object;
class MaybeObject; class MaybeObject;
class OldSpace; class OldSpace;
class Property;
class Foreign; class Foreign;
class RegExpNode;
struct RegExpCompileData;
class RegExpTree;
class RegExpCompiler;
class RegExpVisitor;
class Scope; class Scope;
class ScopeInfo; class ScopeInfo;
class Script; class Script;
class Slot;
class Smi; class Smi;
template <typename Config, class Allocator = FreeStoreAllocationPolicy> template <typename Config, class Allocator = FreeStoreAllocationPolicy>
class SplayTree; class SplayTree;
class Statement;
class String; class String;
class Struct; class Struct;
class SwitchStatement;
class AstVisitor;
class Variable; class Variable;
class VariableProxy;
class RelocInfo; class RelocInfo;
class Deserializer; class Deserializer;
class MessageLocation; class MessageLocation;

2
deps/v8/src/version.cc

@ -34,7 +34,7 @@
// cannot be changed without changing the SCons build script. // cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 3 #define MAJOR_VERSION 3
#define MINOR_VERSION 8 #define MINOR_VERSION 8
#define BUILD_NUMBER 8 #define BUILD_NUMBER 9
#define PATCH_LEVEL 0 #define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise. // Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.) // (Boolean macro values are not supported by all preprocessors.)

4
deps/v8/src/x64/assembler-x64-inl.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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -28,6 +28,8 @@
#ifndef V8_X64_ASSEMBLER_X64_INL_H_ #ifndef V8_X64_ASSEMBLER_X64_INL_H_
#define V8_X64_ASSEMBLER_X64_INL_H_ #define V8_X64_ASSEMBLER_X64_INL_H_
#include "x64/assembler-x64.h"
#include "cpu.h" #include "cpu.h"
#include "debug.h" #include "debug.h"
#include "v8memory.h" #include "v8memory.h"

1
deps/v8/src/x64/builtins-x64.cc

@ -1547,6 +1547,7 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
__ bind(&invoke); __ bind(&invoke);
__ call(rdx); __ call(rdx);
masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset());
// Leave frame and return. // Leave frame and return.
LeaveArgumentsAdaptorFrame(masm); LeaveArgumentsAdaptorFrame(masm);
__ ret(0); __ ret(0);

131
deps/v8/src/x64/deoptimizer-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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -206,12 +206,13 @@ void Deoptimizer::DoComputeOsrOutputFrame() {
ASSERT(Translation::BEGIN == opcode); ASSERT(Translation::BEGIN == opcode);
USE(opcode); USE(opcode);
int count = iterator.Next(); int count = iterator.Next();
iterator.Skip(1); // Drop JS frame count.
ASSERT(count == 1); ASSERT(count == 1);
USE(count); USE(count);
opcode = static_cast<Translation::Opcode>(iterator.Next()); opcode = static_cast<Translation::Opcode>(iterator.Next());
USE(opcode); USE(opcode);
ASSERT(Translation::FRAME == opcode); ASSERT(Translation::JS_FRAME == opcode);
unsigned node_id = iterator.Next(); unsigned node_id = iterator.Next();
USE(node_id); USE(node_id);
ASSERT(node_id == ast_id); ASSERT(node_id == ast_id);
@ -247,9 +248,7 @@ void Deoptimizer::DoComputeOsrOutputFrame() {
output_ = new FrameDescription*[1]; output_ = new FrameDescription*[1];
output_[0] = new(output_frame_size) FrameDescription( output_[0] = new(output_frame_size) FrameDescription(
output_frame_size, function_); output_frame_size, function_);
#ifdef DEBUG output_[0]->SetFrameType(StackFrame::JAVA_SCRIPT);
output_[0]->SetKind(Code::OPTIMIZED_FUNCTION);
#endif
// Clear the incoming parameters in the optimized frame to avoid // Clear the incoming parameters in the optimized frame to avoid
// confusing the garbage collector. // confusing the garbage collector.
@ -338,13 +337,117 @@ void Deoptimizer::DoComputeOsrOutputFrame() {
} }
void Deoptimizer::DoComputeFrame(TranslationIterator* iterator, void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator,
int frame_index) { int frame_index) {
// Read the ast node id, function, and frame height for this output frame. JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
Translation::Opcode opcode = unsigned height = iterator->Next();
static_cast<Translation::Opcode>(iterator->Next()); unsigned height_in_bytes = height * kPointerSize;
USE(opcode); if (FLAG_trace_deopt) {
ASSERT(Translation::FRAME == opcode); PrintF(" translating arguments adaptor => height=%d\n", height_in_bytes);
}
unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize;
unsigned input_frame_size = input_->GetFrameSize();
unsigned output_frame_size = height_in_bytes + fixed_frame_size;
// Allocate and store the output frame description.
FrameDescription* output_frame =
new(output_frame_size) FrameDescription(output_frame_size, function);
output_frame->SetFrameType(StackFrame::ARGUMENTS_ADAPTOR);
// Arguments adaptor can not be topmost or bottommost.
ASSERT(frame_index > 0 && frame_index < output_count_ - 1);
ASSERT(output_[frame_index] == NULL);
output_[frame_index] = output_frame;
// The top address of the frame is computed from the previous
// frame's top and this frame's size.
intptr_t top_address;
top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
output_frame->SetTop(top_address);
// Compute the incoming parameter translation.
int parameter_count = height;
unsigned output_offset = output_frame_size;
unsigned input_offset = input_frame_size;
for (int i = 0; i < parameter_count; ++i) {
output_offset -= kPointerSize;
DoTranslateCommand(iterator, frame_index, output_offset);
}
input_offset -= (parameter_count * kPointerSize);
// Read caller's PC from the previous frame.
output_offset -= kPointerSize;
input_offset -= kPointerSize;
intptr_t callers_pc = output_[frame_index - 1]->GetPc();
output_frame->SetFrameSlot(output_offset, callers_pc);
if (FLAG_trace_deopt) {
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
V8PRIxPTR " ; caller's pc\n",
top_address + output_offset, output_offset, callers_pc);
}
// Read caller's FP from the previous frame, and set this frame's FP.
output_offset -= kPointerSize;
input_offset -= kPointerSize;
intptr_t value = output_[frame_index - 1]->GetFp();
output_frame->SetFrameSlot(output_offset, value);
intptr_t fp_value = top_address + output_offset;
output_frame->SetFp(fp_value);
if (FLAG_trace_deopt) {
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
V8PRIxPTR " ; caller's fp\n",
fp_value, output_offset, value);
}
// A marker value is used in place of the context.
output_offset -= kPointerSize;
input_offset -= kPointerSize;
intptr_t context = reinterpret_cast<intptr_t>(
Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
output_frame->SetFrameSlot(output_offset, context);
if (FLAG_trace_deopt) {
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
V8PRIxPTR " ; context (adaptor sentinel)\n",
top_address + output_offset, output_offset, context);
}
// The function was mentioned explicitly in the ARGUMENTS_ADAPTOR_FRAME.
output_offset -= kPointerSize;
input_offset -= kPointerSize;
value = reinterpret_cast<intptr_t>(function);
output_frame->SetFrameSlot(output_offset, value);
if (FLAG_trace_deopt) {
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
V8PRIxPTR " ; function\n",
top_address + output_offset, output_offset, value);
}
// Number of incoming arguments.
output_offset -= kPointerSize;
input_offset -= kPointerSize;
value = reinterpret_cast<intptr_t>(Smi::FromInt(height - 1));
output_frame->SetFrameSlot(output_offset, value);
if (FLAG_trace_deopt) {
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
V8PRIxPTR " ; argc (%d)\n",
top_address + output_offset, output_offset, value, height - 1);
}
ASSERT(0 == output_offset);
Builtins* builtins = isolate_->builtins();
Code* adaptor_trampoline =
builtins->builtin(Builtins::kArgumentsAdaptorTrampoline);
intptr_t pc_value = reinterpret_cast<intptr_t>(
adaptor_trampoline->instruction_start() +
isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value());
output_frame->SetPc(pc_value);
}
void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
int frame_index) {
int node_id = iterator->Next(); int node_id = iterator->Next();
JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
unsigned height = iterator->Next(); unsigned height = iterator->Next();
@ -364,9 +467,7 @@ void Deoptimizer::DoComputeFrame(TranslationIterator* iterator,
// Allocate and store the output frame description. // Allocate and store the output frame description.
FrameDescription* output_frame = FrameDescription* output_frame =
new(output_frame_size) FrameDescription(output_frame_size, function); new(output_frame_size) FrameDescription(output_frame_size, function);
#ifdef DEBUG output_frame->SetFrameType(StackFrame::JAVA_SCRIPT);
output_frame->SetKind(Code::FUNCTION);
#endif
bool is_bottommost = (0 == frame_index); bool is_bottommost = (0 == frame_index);
bool is_topmost = (output_count_ - 1 == frame_index); bool is_topmost = (output_count_ - 1 == frame_index);

7
deps/v8/src/x64/frames-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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -87,6 +87,9 @@ class ExitFrameConstants : public AllStatic {
class StandardFrameConstants : public AllStatic { class StandardFrameConstants : public AllStatic {
public: public:
// Fixed part of the frame consists of return address, caller fp,
// context and function.
static const int kFixedFrameSize = 4 * kPointerSize;
static const int kExpressionsOffset = -3 * kPointerSize; static const int kExpressionsOffset = -3 * kPointerSize;
static const int kMarkerOffset = -2 * kPointerSize; static const int kMarkerOffset = -2 * kPointerSize;
static const int kContextOffset = -1 * kPointerSize; static const int kContextOffset = -1 * kPointerSize;
@ -112,6 +115,8 @@ class JavaScriptFrameConstants : public AllStatic {
class ArgumentsAdaptorFrameConstants : public AllStatic { class ArgumentsAdaptorFrameConstants : public AllStatic {
public: public:
static const int kLengthOffset = StandardFrameConstants::kExpressionsOffset; static const int kLengthOffset = StandardFrameConstants::kExpressionsOffset;
static const int kFrameSize =
StandardFrameConstants::kFixedFrameSize + kPointerSize;
}; };

63
deps/v8/src/x64/ic-x64.cc

@ -467,43 +467,50 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
// Load the key (consisting of map and symbol) from the cache and // Load the key (consisting of map and symbol) from the cache and
// check for match. // check for match.
Label try_second_entry, hit_on_first_entry, load_in_object_property; Label load_in_object_property;
static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket;
Label hit_on_nth_entry[kEntriesPerBucket];
ExternalReference cache_keys ExternalReference cache_keys
= ExternalReference::keyed_lookup_cache_keys(masm->isolate()); = ExternalReference::keyed_lookup_cache_keys(masm->isolate());
__ movq(rdi, rcx);
__ shl(rdi, Immediate(kPointerSizeLog2 + 1)); for (int i = 0; i < kEntriesPerBucket - 1; i++) {
__ LoadAddress(kScratchRegister, cache_keys); Label try_next_entry;
__ cmpq(rbx, Operand(kScratchRegister, rdi, times_1, 0)); __ movq(rdi, rcx);
__ j(not_equal, &try_second_entry); __ shl(rdi, Immediate(kPointerSizeLog2 + 1));
__ cmpq(rax, Operand(kScratchRegister, rdi, times_1, kPointerSize)); __ LoadAddress(kScratchRegister, cache_keys);
__ j(equal, &hit_on_first_entry); int off = kPointerSize * i * 2;
__ cmpq(rbx, Operand(kScratchRegister, rdi, times_1, off));
__ bind(&try_second_entry); __ j(not_equal, &try_next_entry);
__ cmpq(rbx, Operand(kScratchRegister, rdi, times_1, kPointerSize * 2)); __ cmpq(rax, Operand(kScratchRegister, rdi, times_1, off + kPointerSize));
__ j(equal, &hit_on_nth_entry[i]);
__ bind(&try_next_entry);
}
int off = kPointerSize * (kEntriesPerBucket - 1) * 2;
__ cmpq(rbx, Operand(kScratchRegister, rdi, times_1, off));
__ j(not_equal, &slow); __ j(not_equal, &slow);
__ cmpq(rax, Operand(kScratchRegister, rdi, times_1, kPointerSize * 3)); __ cmpq(rax, Operand(kScratchRegister, rdi, times_1, off + kPointerSize));
__ j(not_equal, &slow); __ j(not_equal, &slow);
// Get field offset, which is a 32-bit integer. // Get field offset, which is a 32-bit integer.
ExternalReference cache_field_offsets ExternalReference cache_field_offsets
= ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate()); = ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate());
// Hit on second entry. // Hit on nth entry.
__ LoadAddress(kScratchRegister, cache_field_offsets); for (int i = kEntriesPerBucket - 1; i >= 0; i--) {
__ addl(rcx, Immediate(1)); __ bind(&hit_on_nth_entry[i]);
__ movl(rdi, Operand(kScratchRegister, rcx, times_4, 0)); if (i != 0) {
__ movzxbq(rcx, FieldOperand(rbx, Map::kInObjectPropertiesOffset)); __ addl(rcx, Immediate(i));
__ subq(rdi, rcx); }
__ j(above_equal, &property_array_property); __ LoadAddress(kScratchRegister, cache_field_offsets);
__ jmp(&load_in_object_property); __ movl(rdi, Operand(kScratchRegister, rcx, times_4, 0));
__ movzxbq(rcx, FieldOperand(rbx, Map::kInObjectPropertiesOffset));
// Hit on first entry. __ subq(rdi, rcx);
__ bind(&hit_on_first_entry); __ j(above_equal, &property_array_property);
__ LoadAddress(kScratchRegister, cache_field_offsets); if (i != 0) {
__ movl(rdi, Operand(kScratchRegister, rcx, times_4, 0)); __ jmp(&load_in_object_property);
__ movzxbq(rcx, FieldOperand(rbx, Map::kInObjectPropertiesOffset)); }
__ subq(rdi, rcx); }
__ j(above_equal, &property_array_property);
// Load in-object property. // Load in-object property.
__ bind(&load_in_object_property); __ bind(&load_in_object_property);

12
deps/v8/src/x64/lithium-codegen-x64.cc

@ -368,7 +368,11 @@ void LCodeGen::WriteTranslation(LEnvironment* environment,
WriteTranslation(environment->outer(), translation); WriteTranslation(environment->outer(), translation);
int closure_id = DefineDeoptimizationLiteral(environment->closure()); int closure_id = DefineDeoptimizationLiteral(environment->closure());
translation->BeginFrame(environment->ast_id(), closure_id, height); if (environment->is_arguments_adaptor()) {
translation->BeginArgumentsAdaptorFrame(closure_id, translation_size);
} else {
translation->BeginJSFrame(environment->ast_id(), closure_id, height);
}
for (int i = 0; i < translation_size; ++i) { for (int i = 0; i < translation_size; ++i) {
LOperand* value = environment->values()->at(i); LOperand* value = environment->values()->at(i);
// spilled_registers_ and spilled_double_registers_ are either // spilled_registers_ and spilled_double_registers_ are either
@ -504,10 +508,14 @@ void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment,
// |>------------ translation_size ------------<| // |>------------ translation_size ------------<|
int frame_count = 0; int frame_count = 0;
int jsframe_count = 0;
for (LEnvironment* e = environment; e != NULL; e = e->outer()) { for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
++frame_count; ++frame_count;
if (!e->is_arguments_adaptor()) {
++jsframe_count;
}
} }
Translation translation(&translations_, frame_count); Translation translation(&translations_, frame_count, jsframe_count);
WriteTranslation(environment, &translation); WriteTranslation(environment, &translation);
int deoptimization_index = deoptimizations_.length(); int deoptimization_index = deoptimizations_.length();
int pc_offset = masm()->pc_offset(); int pc_offset = masm()->pc_offset();

24
deps/v8/src/x64/lithium-x64.cc

@ -1000,14 +1000,16 @@ LEnvironment* LChunkBuilder::CreateEnvironment(
LEnvironment* outer = LEnvironment* outer =
CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator); CreateEnvironment(hydrogen_env->outer(), argument_index_accumulator);
int ast_id = hydrogen_env->ast_id(); int ast_id = hydrogen_env->ast_id();
ASSERT(ast_id != AstNode::kNoNumber); ASSERT(ast_id != AstNode::kNoNumber || hydrogen_env->is_arguments_adaptor());
int value_count = hydrogen_env->length(); int value_count = hydrogen_env->length();
LEnvironment* result = new LEnvironment(hydrogen_env->closure(), LEnvironment* result = new LEnvironment(hydrogen_env->closure(),
hydrogen_env->is_arguments_adaptor(),
ast_id, ast_id,
hydrogen_env->parameter_count(), hydrogen_env->parameter_count(),
argument_count_, argument_count_,
value_count, value_count,
outer); outer);
int argument_index = *argument_index_accumulator;
for (int i = 0; i < value_count; ++i) { for (int i = 0; i < value_count; ++i) {
if (hydrogen_env->is_special_index(i)) continue; if (hydrogen_env->is_special_index(i)) continue;
@ -1016,13 +1018,17 @@ LEnvironment* LChunkBuilder::CreateEnvironment(
if (value->IsArgumentsObject()) { if (value->IsArgumentsObject()) {
op = NULL; op = NULL;
} else if (value->IsPushArgument()) { } else if (value->IsPushArgument()) {
op = new LArgument((*argument_index_accumulator)++); op = new LArgument(argument_index++);
} else { } else {
op = UseAny(value); op = UseAny(value);
} }
result->AddValue(op, value->representation()); result->AddValue(op, value->representation());
} }
if (!hydrogen_env->is_arguments_adaptor()) {
*argument_index_accumulator = argument_index;
}
return result; return result;
} }
@ -1912,12 +1918,11 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement( LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
HLoadKeyedSpecializedArrayElement* instr) { HLoadKeyedSpecializedArrayElement* instr) {
ElementsKind elements_kind = instr->elements_kind(); ElementsKind elements_kind = instr->elements_kind();
Representation representation(instr->representation());
ASSERT( ASSERT(
(representation.IsInteger32() && (instr->representation().IsInteger32() &&
(elements_kind != EXTERNAL_FLOAT_ELEMENTS) && (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
(elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) || (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
(representation.IsDouble() && (instr->representation().IsDouble() &&
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) || ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS)))); (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
ASSERT(instr->key()->representation().IsInteger32()); ASSERT(instr->key()->representation().IsInteger32());
@ -1976,13 +1981,12 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement(
LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement( LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
HStoreKeyedSpecializedArrayElement* instr) { HStoreKeyedSpecializedArrayElement* instr) {
Representation representation(instr->value()->representation());
ElementsKind elements_kind = instr->elements_kind(); ElementsKind elements_kind = instr->elements_kind();
ASSERT( ASSERT(
(representation.IsInteger32() && (instr->value()->representation().IsInteger32() &&
(elements_kind != EXTERNAL_FLOAT_ELEMENTS) && (elements_kind != EXTERNAL_FLOAT_ELEMENTS) &&
(elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) || (elements_kind != EXTERNAL_DOUBLE_ELEMENTS)) ||
(representation.IsDouble() && (instr->value()->representation().IsDouble() &&
((elements_kind == EXTERNAL_FLOAT_ELEMENTS) || ((elements_kind == EXTERNAL_FLOAT_ELEMENTS) ||
(elements_kind == EXTERNAL_DOUBLE_ELEMENTS)))); (elements_kind == EXTERNAL_DOUBLE_ELEMENTS))));
ASSERT(instr->external_pointer()->representation().IsExternal()); ASSERT(instr->external_pointer()->representation().IsExternal());
@ -2245,6 +2249,7 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
HEnvironment* outer = current_block_->last_environment(); HEnvironment* outer = current_block_->last_environment();
HConstant* undefined = graph()->GetConstantUndefined(); HConstant* undefined = graph()->GetConstantUndefined();
HEnvironment* inner = outer->CopyForInlining(instr->closure(), HEnvironment* inner = outer->CopyForInlining(instr->closure(),
instr->arguments_count(),
instr->function(), instr->function(),
undefined, undefined,
instr->call_kind()); instr->call_kind());
@ -2255,7 +2260,8 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
HEnvironment* outer = current_block_->last_environment()->outer(); HEnvironment* outer = current_block_->last_environment()->
DiscardInlined(false);
current_block_->UpdateEnvironment(outer); current_block_->UpdateEnvironment(outer);
return NULL; return NULL;
} }

123
deps/v8/test/cctest/test-api.cc

@ -1189,7 +1189,6 @@ THREADED_TEST(GlobalPrototype) {
templ->Set("x", v8_num(200)); templ->Set("x", v8_num(200));
templ->SetAccessor(v8_str("m"), GetM); templ->SetAccessor(v8_str("m"), GetM);
LocalContext env(0, templ); LocalContext env(0, templ);
v8::Handle<v8::Object> obj(env->Global());
v8::Handle<Script> script(v8_compile("dummy()")); v8::Handle<Script> script(v8_compile("dummy()"));
v8::Handle<Value> result(script->Run()); v8::Handle<Value> result(script->Run());
CHECK_EQ(13.4, result->NumberValue()); CHECK_EQ(13.4, result->NumberValue());
@ -1847,7 +1846,7 @@ THREADED_TEST(DeepCrossLanguageRecursion) {
env->Global()->Set(v8_str("depth"), v8::Integer::New(0)); env->Global()->Set(v8_str("depth"), v8::Integer::New(0));
call_recursively_script = v8_compile("callScriptRecursively()"); call_recursively_script = v8_compile("callScriptRecursively()");
v8::Handle<Value> result(call_recursively_script->Run()); call_recursively_script->Run();
call_recursively_script = v8::Handle<Script>(); call_recursively_script = v8::Handle<Script>();
env->Global()->Set(v8_str("depth"), v8::Integer::New(0)); env->Global()->Set(v8_str("depth"), v8::Integer::New(0));
@ -4476,7 +4475,7 @@ THREADED_TEST(ExtensibleOnUndetectable) {
source = v8_str("undetectable.y = 2000;"); source = v8_str("undetectable.y = 2000;");
script = Script::Compile(source); script = Script::Compile(source);
Local<Value> result(script->Run()); script->Run();
ExpectBoolean("undetectable.y == undefined", true); ExpectBoolean("undetectable.y == undefined", true);
} }
@ -4829,9 +4828,10 @@ THREADED_TEST(NativeFunctionDeclarationError) {
const char* extension_names[] = { name }; const char* extension_names[] = { name };
v8::ExtensionConfiguration extensions(1, extension_names); v8::ExtensionConfiguration extensions(1, extension_names);
v8::Handle<Context> context(Context::New(&extensions)); v8::Handle<Context> context(Context::New(&extensions));
ASSERT(context.IsEmpty()); CHECK(context.IsEmpty());
} }
THREADED_TEST(NativeFunctionDeclarationErrorEscape) { THREADED_TEST(NativeFunctionDeclarationErrorEscape) {
v8::HandleScope handle_scope; v8::HandleScope handle_scope;
const char* name = "nativedeclerresc"; const char* name = "nativedeclerresc";
@ -4843,7 +4843,7 @@ THREADED_TEST(NativeFunctionDeclarationErrorEscape) {
const char* extension_names[] = { name }; const char* extension_names[] = { name };
v8::ExtensionConfiguration extensions(1, extension_names); v8::ExtensionConfiguration extensions(1, extension_names);
v8::Handle<Context> context(Context::New(&extensions)); v8::Handle<Context> context(Context::New(&extensions));
ASSERT(context.IsEmpty()); CHECK(context.IsEmpty());
} }
@ -5009,7 +5009,7 @@ TEST(RegexpOutOfMemory) {
Local<Script> script = Local<Script> script =
Script::Compile(String::New(js_code_causing_huge_string_flattening)); Script::Compile(String::New(js_code_causing_huge_string_flattening));
last_location = NULL; last_location = NULL;
Local<Value> result(script->Run()); script->Run();
CHECK(false); // Should not return. CHECK(false); // Should not return.
} }
@ -5787,7 +5787,6 @@ THREADED_TEST(ErrorConstruction) {
v8::Handle<String> message = v8_str("message"); v8::Handle<String> message = v8_str("message");
v8::Handle<Value> range_error = v8::Exception::RangeError(foo); v8::Handle<Value> range_error = v8::Exception::RangeError(foo);
CHECK(range_error->IsObject()); CHECK(range_error->IsObject());
v8::Handle<v8::Object> range_obj(range_error.As<v8::Object>());
CHECK(range_error.As<v8::Object>()->Get(message)->Equals(foo)); CHECK(range_error.As<v8::Object>()->Get(message)->Equals(foo));
v8::Handle<Value> reference_error = v8::Exception::ReferenceError(foo); v8::Handle<Value> reference_error = v8::Exception::ReferenceError(foo);
CHECK(reference_error->IsObject()); CHECK(reference_error->IsObject());
@ -7357,7 +7356,7 @@ THREADED_TEST(CallKnownGlobalReceiver) {
// Create new environment reusing the global object. // Create new environment reusing the global object.
LocalContext env(NULL, instance_template, global_object); LocalContext env(NULL, instance_template, global_object);
env->Global()->Set(v8_str("foo"), foo); env->Global()->Set(v8_str("foo"), foo);
Local<Value> value(Script::Compile(v8_str("foo()"))->Run()); Script::Compile(v8_str("foo()"))->Run();
} }
} }
@ -7683,6 +7682,7 @@ THREADED_TEST(Constructor) {
context->Global()->Set(v8_str("Fun"), cons); context->Global()->Set(v8_str("Fun"), cons);
Local<v8::Object> inst = cons->NewInstance(); Local<v8::Object> inst = cons->NewInstance();
i::Handle<i::JSObject> obj(v8::Utils::OpenHandle(*inst)); i::Handle<i::JSObject> obj(v8::Utils::OpenHandle(*inst));
CHECK(obj->IsJSObject());
Local<Value> value = CompileRun("(new Fun()).constructor === Fun"); Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
CHECK(value->BooleanValue()); CHECK(value->BooleanValue());
} }
@ -8154,6 +8154,7 @@ THREADED_TEST(CallAsFunction) {
{ Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(); { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
Local<ObjectTemplate> instance_template(t->InstanceTemplate()); Local<ObjectTemplate> instance_template(t->InstanceTemplate());
USE(instance_template);
Local<v8::Object> instance = t->GetFunction()->NewInstance(); Local<v8::Object> instance = t->GetFunction()->NewInstance();
context->Global()->Set(v8_str("obj2"), instance); context->Global()->Set(v8_str("obj2"), instance);
v8::TryCatch try_catch; v8::TryCatch try_catch;
@ -8783,10 +8784,10 @@ THREADED_TEST(InterceptorStoreIC) {
0, 0, 0, v8_str("data")); 0, 0, 0, v8_str("data"));
LocalContext context; LocalContext context;
context->Global()->Set(v8_str("o"), templ->NewInstance()); context->Global()->Set(v8_str("o"), templ->NewInstance());
v8::Handle<Value> value(CompileRun( CompileRun(
"for (var i = 0; i < 1000; i++) {" "for (var i = 0; i < 1000; i++) {"
" o.x = 42;" " o.x = 42;"
"}")); "}");
} }
@ -9254,11 +9255,11 @@ THREADED_TEST(InterceptorCallICFastApi_TrivialSignature) {
v8::Handle<v8::Function> fun = fun_templ->GetFunction(); v8::Handle<v8::Function> fun = fun_templ->GetFunction();
GenerateSomeGarbage(); GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance()); context->Global()->Set(v8_str("o"), fun->NewInstance());
v8::Handle<Value> value(CompileRun( CompileRun(
"var result = 0;" "var result = 0;"
"for (var i = 0; i < 100; i++) {" "for (var i = 0; i < 100; i++) {"
" result = o.method(41);" " result = o.method(41);"
"}")); "}");
CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value()); CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
CHECK_EQ(100, interceptor_call_count); CHECK_EQ(100, interceptor_call_count);
} }
@ -9281,14 +9282,14 @@ THREADED_TEST(InterceptorCallICFastApi_SimpleSignature) {
v8::Handle<v8::Function> fun = fun_templ->GetFunction(); v8::Handle<v8::Function> fun = fun_templ->GetFunction();
GenerateSomeGarbage(); GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance()); context->Global()->Set(v8_str("o"), fun->NewInstance());
v8::Handle<Value> value(CompileRun( CompileRun(
"o.foo = 17;" "o.foo = 17;"
"var receiver = {};" "var receiver = {};"
"receiver.__proto__ = o;" "receiver.__proto__ = o;"
"var result = 0;" "var result = 0;"
"for (var i = 0; i < 100; i++) {" "for (var i = 0; i < 100; i++) {"
" result = receiver.method(41);" " result = receiver.method(41);"
"}")); "}");
CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value()); CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
CHECK_EQ(100, interceptor_call_count); CHECK_EQ(100, interceptor_call_count);
} }
@ -9311,7 +9312,7 @@ THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
v8::Handle<v8::Function> fun = fun_templ->GetFunction(); v8::Handle<v8::Function> fun = fun_templ->GetFunction();
GenerateSomeGarbage(); GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance()); context->Global()->Set(v8_str("o"), fun->NewInstance());
v8::Handle<Value> value(CompileRun( CompileRun(
"o.foo = 17;" "o.foo = 17;"
"var receiver = {};" "var receiver = {};"
"receiver.__proto__ = o;" "receiver.__proto__ = o;"
@ -9323,7 +9324,7 @@ THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
" saved_result = result;" " saved_result = result;"
" receiver = {method: function(x) { return x - 1 }};" " receiver = {method: function(x) { return x - 1 }};"
" }" " }"
"}")); "}");
CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value()); CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value()); CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
CHECK_GE(interceptor_call_count, 50); CHECK_GE(interceptor_call_count, 50);
@ -9347,7 +9348,7 @@ THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
v8::Handle<v8::Function> fun = fun_templ->GetFunction(); v8::Handle<v8::Function> fun = fun_templ->GetFunction();
GenerateSomeGarbage(); GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance()); context->Global()->Set(v8_str("o"), fun->NewInstance());
v8::Handle<Value> value(CompileRun( CompileRun(
"o.foo = 17;" "o.foo = 17;"
"var receiver = {};" "var receiver = {};"
"receiver.__proto__ = o;" "receiver.__proto__ = o;"
@ -9359,7 +9360,7 @@ THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
" saved_result = result;" " saved_result = result;"
" o.method = function(x) { return x - 1 };" " o.method = function(x) { return x - 1 };"
" }" " }"
"}")); "}");
CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value()); CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value()); CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
CHECK_GE(interceptor_call_count, 50); CHECK_GE(interceptor_call_count, 50);
@ -9384,7 +9385,7 @@ THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
GenerateSomeGarbage(); GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance()); context->Global()->Set(v8_str("o"), fun->NewInstance());
v8::TryCatch try_catch; v8::TryCatch try_catch;
v8::Handle<Value> value(CompileRun( CompileRun(
"o.foo = 17;" "o.foo = 17;"
"var receiver = {};" "var receiver = {};"
"receiver.__proto__ = o;" "receiver.__proto__ = o;"
@ -9396,7 +9397,7 @@ THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
" saved_result = result;" " saved_result = result;"
" receiver = 333;" " receiver = 333;"
" }" " }"
"}")); "}");
CHECK(try_catch.HasCaught()); CHECK(try_catch.HasCaught());
CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"), CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
try_catch.Exception()->ToString()); try_catch.Exception()->ToString());
@ -9423,7 +9424,7 @@ THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
GenerateSomeGarbage(); GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance()); context->Global()->Set(v8_str("o"), fun->NewInstance());
v8::TryCatch try_catch; v8::TryCatch try_catch;
v8::Handle<Value> value(CompileRun( CompileRun(
"o.foo = 17;" "o.foo = 17;"
"var receiver = {};" "var receiver = {};"
"receiver.__proto__ = o;" "receiver.__proto__ = o;"
@ -9435,7 +9436,7 @@ THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
" saved_result = result;" " saved_result = result;"
" receiver = {method: receiver.method};" " receiver = {method: receiver.method};"
" }" " }"
"}")); "}");
CHECK(try_catch.HasCaught()); CHECK(try_catch.HasCaught());
CHECK_EQ(v8_str("TypeError: Illegal invocation"), CHECK_EQ(v8_str("TypeError: Illegal invocation"),
try_catch.Exception()->ToString()); try_catch.Exception()->ToString());
@ -9453,15 +9454,16 @@ THREADED_TEST(CallICFastApi_TrivialSignature) {
v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate(); v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
proto_templ->Set(v8_str("method"), method_templ); proto_templ->Set(v8_str("method"), method_templ);
v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate()); v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
USE(templ);
LocalContext context; LocalContext context;
v8::Handle<v8::Function> fun = fun_templ->GetFunction(); v8::Handle<v8::Function> fun = fun_templ->GetFunction();
GenerateSomeGarbage(); GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance()); context->Global()->Set(v8_str("o"), fun->NewInstance());
v8::Handle<Value> value(CompileRun( CompileRun(
"var result = 0;" "var result = 0;"
"for (var i = 0; i < 100; i++) {" "for (var i = 0; i < 100; i++) {"
" result = o.method(41);" " result = o.method(41);"
"}")); "}");
CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value()); CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
} }
@ -9476,18 +9478,19 @@ THREADED_TEST(CallICFastApi_SimpleSignature) {
v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate(); v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
proto_templ->Set(v8_str("method"), method_templ); proto_templ->Set(v8_str("method"), method_templ);
v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate()); v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
CHECK(!templ.IsEmpty());
LocalContext context; LocalContext context;
v8::Handle<v8::Function> fun = fun_templ->GetFunction(); v8::Handle<v8::Function> fun = fun_templ->GetFunction();
GenerateSomeGarbage(); GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance()); context->Global()->Set(v8_str("o"), fun->NewInstance());
v8::Handle<Value> value(CompileRun( CompileRun(
"o.foo = 17;" "o.foo = 17;"
"var receiver = {};" "var receiver = {};"
"receiver.__proto__ = o;" "receiver.__proto__ = o;"
"var result = 0;" "var result = 0;"
"for (var i = 0; i < 100; i++) {" "for (var i = 0; i < 100; i++) {"
" result = receiver.method(41);" " result = receiver.method(41);"
"}")); "}");
CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value()); CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
} }
@ -9502,11 +9505,12 @@ THREADED_TEST(CallICFastApi_SimpleSignature_Miss1) {
v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate(); v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
proto_templ->Set(v8_str("method"), method_templ); proto_templ->Set(v8_str("method"), method_templ);
v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate()); v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
CHECK(!templ.IsEmpty());
LocalContext context; LocalContext context;
v8::Handle<v8::Function> fun = fun_templ->GetFunction(); v8::Handle<v8::Function> fun = fun_templ->GetFunction();
GenerateSomeGarbage(); GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance()); context->Global()->Set(v8_str("o"), fun->NewInstance());
v8::Handle<Value> value(CompileRun( CompileRun(
"o.foo = 17;" "o.foo = 17;"
"var receiver = {};" "var receiver = {};"
"receiver.__proto__ = o;" "receiver.__proto__ = o;"
@ -9518,7 +9522,7 @@ THREADED_TEST(CallICFastApi_SimpleSignature_Miss1) {
" saved_result = result;" " saved_result = result;"
" receiver = {method: function(x) { return x - 1 }};" " receiver = {method: function(x) { return x - 1 }};"
" }" " }"
"}")); "}");
CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value()); CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value()); CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
} }
@ -9533,12 +9537,13 @@ THREADED_TEST(CallICFastApi_SimpleSignature_Miss2) {
v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate(); v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
proto_templ->Set(v8_str("method"), method_templ); proto_templ->Set(v8_str("method"), method_templ);
v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate()); v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
CHECK(!templ.IsEmpty());
LocalContext context; LocalContext context;
v8::Handle<v8::Function> fun = fun_templ->GetFunction(); v8::Handle<v8::Function> fun = fun_templ->GetFunction();
GenerateSomeGarbage(); GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance()); context->Global()->Set(v8_str("o"), fun->NewInstance());
v8::TryCatch try_catch; v8::TryCatch try_catch;
v8::Handle<Value> value(CompileRun( CompileRun(
"o.foo = 17;" "o.foo = 17;"
"var receiver = {};" "var receiver = {};"
"receiver.__proto__ = o;" "receiver.__proto__ = o;"
@ -9550,7 +9555,7 @@ THREADED_TEST(CallICFastApi_SimpleSignature_Miss2) {
" saved_result = result;" " saved_result = result;"
" receiver = 333;" " receiver = 333;"
" }" " }"
"}")); "}");
CHECK(try_catch.HasCaught()); CHECK(try_catch.HasCaught());
CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"), CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
try_catch.Exception()->ToString()); try_catch.Exception()->ToString());
@ -9578,7 +9583,7 @@ THREADED_TEST(InterceptorKeyedCallICKeyChange1) {
templ->SetNamedPropertyHandler(NoBlockGetterX); templ->SetNamedPropertyHandler(NoBlockGetterX);
LocalContext context; LocalContext context;
context->Global()->Set(v8_str("o"), templ->NewInstance()); context->Global()->Set(v8_str("o"), templ->NewInstance());
v8::Handle<Value> value(CompileRun( CompileRun(
"proto = new Object();" "proto = new Object();"
"proto.y = function(x) { return x + 1; };" "proto.y = function(x) { return x + 1; };"
"proto.z = function(x) { return x - 1; };" "proto.z = function(x) { return x - 1; };"
@ -9588,7 +9593,7 @@ THREADED_TEST(InterceptorKeyedCallICKeyChange1) {
"for (var i = 0; i < 10; i++) {" "for (var i = 0; i < 10; i++) {"
" if (i == 5) { method = 'z'; };" " if (i == 5) { method = 'z'; };"
" result += o[method](41);" " result += o[method](41);"
"}")); "}");
CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value()); CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
} }
@ -9604,7 +9609,7 @@ THREADED_TEST(InterceptorKeyedCallICKeyChange2) {
context->Global()->Set(v8_str("proto1"), templ->NewInstance()); context->Global()->Set(v8_str("proto1"), templ->NewInstance());
keyed_call_ic_function = keyed_call_ic_function =
v8_compile("function f(x) { return x - 1; }; f")->Run(); v8_compile("function f(x) { return x - 1; }; f")->Run();
v8::Handle<Value> value(CompileRun( CompileRun(
"o = new Object();" "o = new Object();"
"proto2 = new Object();" "proto2 = new Object();"
"o.y = function(x) { return x + 1; };" "o.y = function(x) { return x + 1; };"
@ -9616,7 +9621,7 @@ THREADED_TEST(InterceptorKeyedCallICKeyChange2) {
"for (var i = 0; i < 10; i++) {" "for (var i = 0; i < 10; i++) {"
" if (i == 5) { method = 'y'; };" " if (i == 5) { method = 'y'; };"
" result += o[method](41);" " result += o[method](41);"
"}")); "}");
CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value()); CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
} }
@ -9629,7 +9634,7 @@ THREADED_TEST(InterceptorKeyedCallICKeyChangeOnGlobal) {
templ->SetNamedPropertyHandler(NoBlockGetterX); templ->SetNamedPropertyHandler(NoBlockGetterX);
LocalContext context; LocalContext context;
context->Global()->Set(v8_str("o"), templ->NewInstance()); context->Global()->Set(v8_str("o"), templ->NewInstance());
v8::Handle<Value> value(CompileRun( CompileRun(
"function inc(x) { return x + 1; };" "function inc(x) { return x + 1; };"
"inc(1);" "inc(1);"
"function dec(x) { return x - 1; };" "function dec(x) { return x - 1; };"
@ -9642,7 +9647,7 @@ THREADED_TEST(InterceptorKeyedCallICKeyChangeOnGlobal) {
"for (var i = 0; i < 10; i++) {" "for (var i = 0; i < 10; i++) {"
" if (i == 5) { method = 'y'; };" " if (i == 5) { method = 'y'; };"
" result += o[method](41);" " result += o[method](41);"
"}")); "}");
CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value()); CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
} }
@ -9655,7 +9660,7 @@ THREADED_TEST(InterceptorKeyedCallICFromGlobal) {
LocalContext context; LocalContext context;
context->Global()->Set(v8_str("o"), templ_o->NewInstance()); context->Global()->Set(v8_str("o"), templ_o->NewInstance());
v8::Handle<Value> value(CompileRun( CompileRun(
"function len(x) { return x.length; };" "function len(x) { return x.length; };"
"o.__proto__ = this;" "o.__proto__ = this;"
"var m = 'parseFloat';" "var m = 'parseFloat';"
@ -9666,7 +9671,7 @@ THREADED_TEST(InterceptorKeyedCallICFromGlobal) {
" saved_result = result;" " saved_result = result;"
" };" " };"
" result = o[m]('239');" " result = o[m]('239');"
"}")); "}");
CHECK_EQ(3, context->Global()->Get(v8_str("result"))->Int32Value()); CHECK_EQ(3, context->Global()->Get(v8_str("result"))->Int32Value());
CHECK_EQ(239, context->Global()->Get(v8_str("saved_result"))->Int32Value()); CHECK_EQ(239, context->Global()->Get(v8_str("saved_result"))->Int32Value());
} }
@ -9679,7 +9684,7 @@ THREADED_TEST(InterceptorKeyedCallICMapChangeBefore) {
LocalContext context; LocalContext context;
context->Global()->Set(v8_str("proto"), templ_o->NewInstance()); context->Global()->Set(v8_str("proto"), templ_o->NewInstance());
v8::Handle<Value> value(CompileRun( CompileRun(
"var o = new Object();" "var o = new Object();"
"o.__proto__ = proto;" "o.__proto__ = proto;"
"o.method = function(x) { return x + 1; };" "o.method = function(x) { return x + 1; };"
@ -9688,7 +9693,7 @@ THREADED_TEST(InterceptorKeyedCallICMapChangeBefore) {
"for (var i = 0; i < 10; i++) {" "for (var i = 0; i < 10; i++) {"
" if (i == 5) { o.method = function(x) { return x - 1; }; };" " if (i == 5) { o.method = function(x) { return x - 1; }; };"
" result += o[m](41);" " result += o[m](41);"
"}")); "}");
CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value()); CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
} }
@ -9701,7 +9706,7 @@ THREADED_TEST(InterceptorKeyedCallICMapChangeAfter) {
LocalContext context; LocalContext context;
context->Global()->Set(v8_str("o"), templ_o->NewInstance()); context->Global()->Set(v8_str("o"), templ_o->NewInstance());
v8::Handle<Value> value(CompileRun( CompileRun(
"var proto = new Object();" "var proto = new Object();"
"o.__proto__ = proto;" "o.__proto__ = proto;"
"proto.method = function(x) { return x + 1; };" "proto.method = function(x) { return x + 1; };"
@ -9710,7 +9715,7 @@ THREADED_TEST(InterceptorKeyedCallICMapChangeAfter) {
"for (var i = 0; i < 10; i++) {" "for (var i = 0; i < 10; i++) {"
" if (i == 5) { proto.method = function(x) { return x - 1; }; };" " if (i == 5) { proto.method = function(x) { return x - 1; }; };"
" result += o[m](41);" " result += o[m](41);"
"}")); "}");
CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value()); CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
} }
@ -10627,6 +10632,7 @@ THREADED_TEST(NestedHandleScopeAndContexts) {
env->Enter(); env->Enter();
v8::Handle<Value> value = NestedScope(env); v8::Handle<Value> value = NestedScope(env);
v8::Handle<String> str(value->ToString()); v8::Handle<String> str(value->ToString());
CHECK(!str.IsEmpty());
env->Exit(); env->Exit();
env.Dispose(); env.Dispose();
} }
@ -10635,6 +10641,7 @@ THREADED_TEST(NestedHandleScopeAndContexts) {
THREADED_TEST(ExternalAllocatedMemory) { THREADED_TEST(ExternalAllocatedMemory) {
v8::HandleScope outer; v8::HandleScope outer;
v8::Persistent<Context> env(Context::New()); v8::Persistent<Context> env(Context::New());
CHECK(!env.IsEmpty());
const int kSize = 1024*1024; const int kSize = 1024*1024;
CHECK_EQ(v8::V8::AdjustAmountOfExternalAllocatedMemory(kSize), kSize); CHECK_EQ(v8::V8::AdjustAmountOfExternalAllocatedMemory(kSize), kSize);
CHECK_EQ(v8::V8::AdjustAmountOfExternalAllocatedMemory(-kSize), 0); CHECK_EQ(v8::V8::AdjustAmountOfExternalAllocatedMemory(-kSize), 0);
@ -10973,6 +10980,7 @@ THREADED_TEST(AccessControlRepeatedContextCreation) {
i::FunctionTemplateInfo::cast(internal_template->constructor())); i::FunctionTemplateInfo::cast(internal_template->constructor()));
CHECK(!constructor->access_check_info()->IsUndefined()); CHECK(!constructor->access_check_info()->IsUndefined());
v8::Persistent<Context> context0(Context::New(NULL, global_template)); v8::Persistent<Context> context0(Context::New(NULL, global_template));
CHECK(!context0.IsEmpty());
CHECK(!constructor->access_check_info()->IsUndefined()); CHECK(!constructor->access_check_info()->IsUndefined());
} }
@ -13048,11 +13056,6 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
const int kLargeElementCount = kXSize * kYSize * 4; const int kLargeElementCount = kXSize * kYSize * 4;
ElementType* large_array_data = ElementType* large_array_data =
static_cast<ElementType*>(malloc(kLargeElementCount * element_size)); static_cast<ElementType*>(malloc(kLargeElementCount * element_size));
i::Handle<ExternalArrayClass> large_array(
i::Handle<ExternalArrayClass>::cast(
FACTORY->NewExternalArray(kLargeElementCount,
array_type,
array_data)));
v8::Handle<v8::Object> large_obj = v8::Object::New(); v8::Handle<v8::Object> large_obj = v8::Object::New();
// Set the elements to be the external array. // Set the elements to be the external array.
large_obj->SetIndexedPropertiesToExternalArrayData(large_array_data, large_obj->SetIndexedPropertiesToExternalArrayData(large_array_data,
@ -13453,8 +13456,8 @@ TEST(CaptureStackTrace) {
v8::Handle<v8::String> overview_src = v8::String::New(overview_source); v8::Handle<v8::String> overview_src = v8::String::New(overview_source);
v8::Handle<Value> overview_result( v8::Handle<Value> overview_result(
v8::Script::New(overview_src, origin)->Run()); v8::Script::New(overview_src, origin)->Run());
ASSERT(!overview_result.IsEmpty()); CHECK(!overview_result.IsEmpty());
ASSERT(overview_result->IsObject()); CHECK(overview_result->IsObject());
// Test getting DETAILED information. // Test getting DETAILED information.
const char *detailed_source = const char *detailed_source =
@ -13473,8 +13476,8 @@ TEST(CaptureStackTrace) {
v8::Handle<v8::Script> detailed_script( v8::Handle<v8::Script> detailed_script(
v8::Script::New(detailed_src, &detailed_origin)); v8::Script::New(detailed_src, &detailed_origin));
v8::Handle<Value> detailed_result(detailed_script->Run()); v8::Handle<Value> detailed_result(detailed_script->Run());
ASSERT(!detailed_result.IsEmpty()); CHECK(!detailed_result.IsEmpty());
ASSERT(detailed_result->IsObject()); CHECK(detailed_result->IsObject());
} }
@ -13894,6 +13897,7 @@ static v8::Handle<Value> SpaghettiIncident(const v8::Arguments& args) {
v8::HandleScope scope; v8::HandleScope scope;
v8::TryCatch tc; v8::TryCatch tc;
v8::Handle<v8::String> str(args[0]->ToString()); v8::Handle<v8::String> str(args[0]->ToString());
USE(str);
if (tc.HasCaught()) if (tc.HasCaught())
return tc.ReThrow(); return tc.ReThrow();
return v8::Undefined(); return v8::Undefined();
@ -14038,6 +14042,17 @@ THREADED_TEST(ScriptOrigin) {
CHECK_EQ(0, script_origin_g.ResourceLineOffset()->Int32Value()); CHECK_EQ(0, script_origin_g.ResourceLineOffset()->Int32Value());
} }
THREADED_TEST(FunctionGetInferredName) {
v8::HandleScope scope;
LocalContext env;
v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
v8::Handle<v8::String> script = v8::String::New(
"var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
v8::Script::Compile(script, &origin)->Run();
v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
env->Global()->Get(v8::String::New("f")));
CHECK_EQ("foo.bar.baz", *v8::String::AsciiValue(f->GetInferredName()));
}
THREADED_TEST(ScriptLineNumber) { THREADED_TEST(ScriptLineNumber) {
v8::HandleScope scope; v8::HandleScope scope;
@ -15192,7 +15207,7 @@ TEST(RegExp) {
// RegExps are objects on which you can set properties. // RegExps are objects on which you can set properties.
re->Set(v8_str("property"), v8::Integer::New(32)); re->Set(v8_str("property"), v8::Integer::New(32));
v8::Handle<v8::Value> value(CompileRun("re.property")); v8::Handle<v8::Value> value(CompileRun("re.property"));
ASSERT_EQ(32, value->Int32Value()); CHECK_EQ(32, value->Int32Value());
v8::TryCatch try_catch; v8::TryCatch try_catch;
re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone); re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone);

5
deps/v8/test/cctest/test-compiler.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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -270,8 +270,7 @@ TEST(UncaughtThrow) {
CHECK(!fun.is_null()); CHECK(!fun.is_null());
bool has_pending_exception; bool has_pending_exception;
Handle<JSObject> global(Isolate::Current()->context()->global()); Handle<JSObject> global(Isolate::Current()->context()->global());
Handle<Object> result( Execution::Call(fun, global, 0, NULL, &has_pending_exception);
Execution::Call(fun, global, 0, NULL, &has_pending_exception));
CHECK(has_pending_exception); CHECK(has_pending_exception);
CHECK_EQ(42.0, Isolate::Current()->pending_exception()-> CHECK_EQ(42.0, Isolate::Current()->pending_exception()->
ToObjectChecked()->Number()); ToObjectChecked()->Number());

30
deps/v8/test/cctest/test-debug.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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -856,7 +856,7 @@ static void DebugEventRemoveBreakPoint(v8::DebugEvent event,
if (event == v8::Break) { if (event == v8::Break) {
break_point_hit_count++; break_point_hit_count++;
v8::Handle<v8::Function> fun(v8::Handle<v8::Function>::Cast(data)); CHECK(data->IsFunction());
ClearBreakPoint(debug_event_remove_break_point); ClearBreakPoint(debug_event_remove_break_point);
} }
} }
@ -1447,8 +1447,7 @@ TEST(BreakPointSurviveGC) {
// Test IC store break point with garbage collection. // Test IC store break point with garbage collection.
{ {
v8::Local<v8::Function> bar( CompileFunction(&env, "function foo(){}", "foo");
CompileFunction(&env, "function foo(){}", "foo"));
foo = CompileFunction(&env, "function foo(){bar=0;}", "foo"); foo = CompileFunction(&env, "function foo(){bar=0;}", "foo");
SetBreakPoint(foo, 0); SetBreakPoint(foo, 0);
} }
@ -1456,8 +1455,7 @@ TEST(BreakPointSurviveGC) {
// Test IC load break point with garbage collection. // Test IC load break point with garbage collection.
{ {
v8::Local<v8::Function> bar( CompileFunction(&env, "function foo(){}", "foo");
CompileFunction(&env, "function foo(){}", "foo"));
foo = CompileFunction(&env, "bar=1;function foo(){var x=bar;}", "foo"); foo = CompileFunction(&env, "bar=1;function foo(){var x=bar;}", "foo");
SetBreakPoint(foo, 0); SetBreakPoint(foo, 0);
} }
@ -1465,8 +1463,7 @@ TEST(BreakPointSurviveGC) {
// Test IC call break point with garbage collection. // Test IC call break point with garbage collection.
{ {
v8::Local<v8::Function> bar( CompileFunction(&env, "function foo(){}", "foo");
CompileFunction(&env, "function foo(){}", "foo"));
foo = CompileFunction(&env, foo = CompileFunction(&env,
"function bar(){};function foo(){bar();}", "function bar(){};function foo(){bar();}",
"foo"); "foo");
@ -1476,8 +1473,7 @@ TEST(BreakPointSurviveGC) {
// Test return break point with garbage collection. // Test return break point with garbage collection.
{ {
v8::Local<v8::Function> bar( CompileFunction(&env, "function foo(){}", "foo");
CompileFunction(&env, "function foo(){}", "foo"));
foo = CompileFunction(&env, "function foo(){}", "foo"); foo = CompileFunction(&env, "function foo(){}", "foo");
SetBreakPoint(foo, 0); SetBreakPoint(foo, 0);
} }
@ -1485,8 +1481,7 @@ TEST(BreakPointSurviveGC) {
// Test non IC break point with garbage collection. // Test non IC break point with garbage collection.
{ {
v8::Local<v8::Function> bar( CompileFunction(&env, "function foo(){}", "foo");
CompileFunction(&env, "function foo(){}", "foo"));
foo = CompileFunction(&env, "function foo(){var bar=0;}", "foo"); foo = CompileFunction(&env, "function foo(){var bar=0;}", "foo");
SetBreakPoint(foo, 0); SetBreakPoint(foo, 0);
} }
@ -3751,8 +3746,7 @@ TEST(BreakOnException) {
v8::internal::Isolate::Current()->TraceException(false); v8::internal::Isolate::Current()->TraceException(false);
// Create functions for testing break on exception. // Create functions for testing break on exception.
v8::Local<v8::Function> throws( CompileFunction(&env, "function throws(){throw 1;}", "throws");
CompileFunction(&env, "function throws(){throw 1;}", "throws"));
v8::Local<v8::Function> caught = v8::Local<v8::Function> caught =
CompileFunction(&env, CompileFunction(&env,
"function caught(){try {throws();} catch(e) {};}", "function caught(){try {throws();} catch(e) {};}",
@ -5549,8 +5543,6 @@ TEST(DebuggerUnload) {
// Get the test functions again. // Get the test functions again.
v8::Local<v8::Function> foo(v8::Local<v8::Function>::Cast( v8::Local<v8::Function> foo(v8::Local<v8::Function>::Cast(
env->Global()->Get(v8::String::New("foo")))); env->Global()->Get(v8::String::New("foo"))));
v8::Local<v8::Function> bar(v8::Local<v8::Function>::Cast(
env->Global()->Get(v8::String::New("foo"))));
foo->Call(env->Global(), 0, NULL); foo->Call(env->Global(), 0, NULL);
CHECK_EQ(0, break_point_hit_count); CHECK_EQ(0, break_point_hit_count);
@ -6028,6 +6020,8 @@ TEST(DebugGetLoadedScripts) {
EmptyExternalStringResource source_ext_str; EmptyExternalStringResource source_ext_str;
v8::Local<v8::String> source = v8::String::NewExternal(&source_ext_str); v8::Local<v8::String> source = v8::String::NewExternal(&source_ext_str);
v8::Handle<v8::Script> evil_script(v8::Script::Compile(source)); v8::Handle<v8::Script> evil_script(v8::Script::Compile(source));
// "use" evil_script to make the compiler happy.
(void) evil_script;
Handle<i::ExternalTwoByteString> i_source( Handle<i::ExternalTwoByteString> i_source(
i::ExternalTwoByteString::cast(*v8::Utils::OpenHandle(*source))); i::ExternalTwoByteString::cast(*v8::Utils::OpenHandle(*source)));
// This situation can happen if source was an external string disposed // This situation can happen if source was an external string disposed
@ -6675,7 +6669,7 @@ static void BreakMessageHandler(const v8::Debug::Message& message) {
break_point_hit_count++; break_point_hit_count++;
v8::HandleScope scope; v8::HandleScope scope;
v8::Handle<v8::String> json(message.GetJSON()); message.GetJSON();
SendContinueCommand(); SendContinueCommand();
} else if (message.IsEvent() && message.GetEvent() == v8::AfterCompile) { } else if (message.IsEvent() && message.GetEvent() == v8::AfterCompile) {
@ -6686,7 +6680,7 @@ static void BreakMessageHandler(const v8::Debug::Message& message) {
isolate->stack_guard()->DebugBreak(); isolate->stack_guard()->DebugBreak();
// Force serialization to trigger some internal JS execution. // Force serialization to trigger some internal JS execution.
v8::Handle<v8::String> json(message.GetJSON()); message.GetJSON();
// Restore previous state. // Restore previous state.
if (is_debug_break) { if (is_debug_break) {

4
deps/v8/test/cctest/test-deoptimization.cc

@ -1,4 +1,4 @@
// Copyright 2007-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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -237,7 +237,7 @@ TEST(DeoptimizeRecursive) {
v8::Local<v8::Function> fun = v8::Local<v8::Function> fun =
v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f"))); v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
Handle<v8::internal::JSFunction> f(v8::Utils::OpenHandle(*fun)); CHECK(!fun.IsEmpty());
} }

15
deps/v8/test/cctest/test-mark-compact.cc

@ -526,12 +526,25 @@ static intptr_t MemoryInUse() {
TEST(BootUpMemoryUse) { TEST(BootUpMemoryUse) {
intptr_t initial_memory = MemoryInUse(); intptr_t initial_memory = MemoryInUse();
FLAG_crankshaft = false; // Avoid flakiness.
// Only Linux has the proc filesystem and only if it is mapped. If it's not // Only Linux has the proc filesystem and only if it is mapped. If it's not
// there we just skip the test. // there we just skip the test.
if (initial_memory >= 0) { if (initial_memory >= 0) {
InitializeVM(); InitializeVM();
intptr_t booted_memory = MemoryInUse(); intptr_t booted_memory = MemoryInUse();
CHECK_LE(booted_memory - initial_memory, 16 * 1024 * 1024); if (sizeof(initial_memory) == 8) {
if (v8::internal::Snapshot::IsEnabled()) {
CHECK_LE(booted_memory - initial_memory, 6654 * 1024); // 6444.
} else {
CHECK_LE(booted_memory - initial_memory, 6777 * 1024); // 6596.
}
} else {
if (v8::internal::Snapshot::IsEnabled()) {
CHECK_LE(booted_memory - initial_memory, 6500 * 1024); // 6365.
} else {
CHECK_LE(booted_memory - initial_memory, 6654 * 1024); // 6424
}
}
} }
} }

4
deps/v8/test/cctest/test-parsing.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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -230,7 +230,7 @@ TEST(Preparsing) {
CHECK_EQ(11, error_location.end_pos); CHECK_EQ(11, error_location.end_pos);
// Should not crash. // Should not crash.
const char* message = pre_impl->BuildMessage(); const char* message = pre_impl->BuildMessage();
i::Vector<const char*> args(pre_impl->BuildArgs()); pre_impl->BuildArgs();
CHECK_GT(strlen(message), 0); CHECK_GT(strlen(message), 0);
} }

20
deps/v8/test/mjsunit/compiler/regress-funarguments.js

@ -1,4 +1,4 @@
// 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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -25,6 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax
// Test function.arguments. // Test function.arguments.
function A() {} function A() {}
@ -60,13 +62,16 @@ function hej(x) {
return o.g(x, "z"); return o.g(x, "z");
} }
function stress() { function opt() {
for (var i=0; i<5000000; i++) o.g(i, "g"); for (var k=0; k<2; k++) {
for (var j=0; j<5000000; j++) hej(j); for (var i=0; i<5; i++) o.g(i, "g");
for (var j=0; j<5; j++) hej(j);
}
%OptimizeFunctionOnNextCall(o.g);
%OptimizeFunctionOnNextCall(hej);
} }
stress(); opt();
assertArrayEquals([0, "g"], o.g(0, "g")); assertArrayEquals([0, "g"], o.g(0, "g"));
assertArrayEquals([1, "f"], o.g(1, "g")); assertArrayEquals([1, "f"], o.g(1, "g"));
assertArrayEquals([0, "h"], hej(0)); assertArrayEquals([0, "h"], hej(0));
@ -74,8 +79,7 @@ assertArrayEquals([1, "f"], hej(1));
o = new B(); o = new B();
stress(); opt();
assertArrayEquals([0, "f"], o.g(0, "g")); assertArrayEquals([0, "f"], o.g(0, "g"));
assertArrayEquals([1, "g"], o.g(1, "g")); assertArrayEquals([1, "g"], o.g(1, "g"));
assertArrayEquals([0, "f"], hej(0)); assertArrayEquals([0, "f"], hej(0));

174
deps/v8/test/mjsunit/debug-evaluate-locals-optimized-double.js

@ -1,4 +1,4 @@
// Copyright 2008 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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -34,6 +34,27 @@ var exception = false;
var testingConstructCall = false; var testingConstructCall = false;
var input = [
{a: 1, b: 2},
{a: 3, b: 4},
{a: 5, b: 6},
{a: 7, b: 8},
{a: 9, b: 10}
];
var expected = [
{ locals: {a0: 1.01, b0: 2.02}, args: { names: ["i", "x0", "y0"], values: [0, 3.03, 4.04] } },
{ locals: {a1: 3.03, b1: 4.04}, args: { names: ["i", "x1", "y1"], values: [1, 5.05, 6.06] } },
{ locals: {a2: 5.05, b2: 6.06}, args: { names: ["i"], values: [2] } },
{ locals: {a3: 7.07, b3: 8.08}, args: { names: ["i", "x3", "y3", "z3"],
values: [3, 9.09, 10.10, undefined] }
},
{ locals: {a4: 9.09, b4: 10.10}, args: { names: ["i", "x4", "y4"], values: [4, 11.11, 12.12] } }
];
function arraySum(arr) {
return arr.reduce(function (a, b) { return a + b; }, 0);
}
function listener(event, exec_state, event_data, data) { function listener(event, exec_state, event_data, data) {
try { try {
@ -44,42 +65,63 @@ function listener(event, exec_state, event_data, data) {
for (var i = 0; i < exec_state.frameCount(); i++) { for (var i = 0; i < exec_state.frameCount(); i++) {
var frame = exec_state.frame(i); var frame = exec_state.frame(i);
if (i < exec_state.frameCount() - 1) { if (i < exec_state.frameCount() - 1) {
var expected_a = i * 2 + 1 + (i * 2 + 1) / 100; var expected_args = expected[i].args;
var expected_b = i * 2 + 2 + (i * 2 + 2) / 100; var expected_locals = expected[i].locals;
var expected_x = (i + 1) * 2 + 1 + ((i + 1) * 2 + 1) / 100;
var expected_y = (i + 1) * 2 + 2 + ((i + 1) * 2 + 2) / 100; // All frames except the bottom one have expected locals.
var locals = {};
// All frames except the bottom one has normal variables a and b. for (var j = 0; j < frame.localCount(); j++) {
var a = ('a' === frame.localName(0)) ? 0 : 1; locals[frame.localName(j)] = frame.localValue(j).value();
var b = 1 - a; }
assertEquals('a', frame.localName(a)); assertPropertiesEqual(expected_locals, locals);
assertEquals('b', frame.localName(b));
assertEquals(expected_a, frame.localValue(a).value()); // All frames except the bottom one have expected arguments.
assertEquals(expected_b, frame.localValue(b).value()); for (var j = 0; j < expected_args.names.length; j++) {
assertEquals(expected_args.names[j], frame.argumentName(j));
// All frames except the bottom one has arguments variables x and y. assertEquals(expected_args.values[j], frame.argumentValue(j).value());
assertEquals('x', frame.argumentName(0)); }
assertEquals('y', frame.argumentName(1));
assertEquals(expected_x, frame.argumentValue(0).value());
assertEquals(expected_y, frame.argumentValue(1).value());
// All frames except the bottom one have two scopes. // All frames except the bottom one have two scopes.
assertEquals(2, frame.scopeCount()); assertEquals(2, frame.scopeCount());
assertEquals(debug.ScopeType.Local, frame.scope(0).scopeType()); assertEquals(debug.ScopeType.Local, frame.scope(0).scopeType());
assertEquals(debug.ScopeType.Global, frame.scope(1).scopeType()); assertEquals(debug.ScopeType.Global, frame.scope(1).scopeType());
assertEquals(expected_a, frame.scope(0).scopeObject().value()['a']);
assertEquals(expected_b, frame.scope(0).scopeObject().value()['b']); Object.keys(expected_locals).forEach(function (name) {
assertEquals(expected_x, frame.scope(0).scopeObject().value()['x']); assertEquals(expected_locals[name], frame.scope(0).scopeObject().value()[name]);
assertEquals(expected_y, frame.scope(0).scopeObject().value()['y']); });
for (var j = 0; j < expected_args.names.length; j++) {
var arg_name = expected_args.names[j];
var arg_value = expected_args.values[j];
assertEquals(arg_value, frame.scope(0).scopeObject().value()[arg_name]);
}
// Evaluate in the inlined frame. // Evaluate in the inlined frame.
assertEquals(expected_a, frame.evaluate('a').value()); Object.keys(expected_locals).forEach(function (name) {
assertEquals(expected_x, frame.evaluate('x').value()); assertEquals(expected_locals[name], frame.evaluate(name).value());
assertEquals(expected_x, frame.evaluate('arguments[0]').value()); });
assertEquals(expected_a + expected_b + expected_x + expected_y,
frame.evaluate('a + b + x + y').value()); for (var j = 0; j < expected_args.names.length; j++) {
assertEquals(expected_x + expected_y, var arg_name = expected_args.names[j];
frame.evaluate('arguments[0] + arguments[1]').value()); var arg_value = expected_args.values[j];
assertEquals(arg_value, frame.evaluate(arg_name).value());
assertEquals(arg_value, frame.evaluate('arguments['+j+']').value());
}
var expected_args_sum = arraySum(expected_args.values);
var expected_locals_sum =
arraySum(Object.keys(expected_locals).
map(function (k) { return expected_locals[k]; }));
assertEquals(expected_locals_sum + expected_args_sum,
frame.evaluate(Object.keys(expected_locals).join('+') + ' + ' +
expected_args.names.join('+')).value());
var arguments_sum = expected_args.names.map(function(_, idx) {
return "arguments[" + idx + "]";
}).join('+');
assertEquals(expected_args_sum,
frame.evaluate(arguments_sum).value());
} else { } else {
// The bottom frame only have the global scope. // The bottom frame only have the global scope.
assertEquals(1, frame.scopeCount()); assertEquals(1, frame.scopeCount());
@ -121,62 +163,64 @@ function listener(event, exec_state, event_data, data) {
listenerComplete = true; listenerComplete = true;
} }
} catch (e) { } catch (e) {
exception = e exception = e.toString() + e.stack;
}; };
}; };
f();f();f(); for (var i = 0; i < 4; i++) f(input.length - 1, 11.11, 12.12);
%OptimizeFunctionOnNextCall(f); %OptimizeFunctionOnNextCall(f);
f(); f(input.length - 1, 11.11, 12.12);
// Add the debug event listener. // Add the debug event listener.
Debug.setListener(listener); Debug.setListener(listener);
function h(x, y) { function h(i, x0, y0) {
var a = 1; var a0 = input[i].a;
var b = 2; var b0 = input[i].b;
a = a + a / 100; a0 = a0 + a0 / 100;
b = b + b / 100; b0 = b0 + b0 / 100;
debugger; // Breakpoint. debugger; // Breakpoint.
}; };
function g3(x, y) { function g3(i, x1, y1) {
var a = 3; var a1 = input[i].a;
var b = 4; var b1 = input[i].b;
a = a + a / 100; a1 = a1 + a1 / 100;
b = b + b / 100; b1 = b1 + b1 / 100;
h(a, b); h(i - 1, a1, b1);
return a+b; return a1+b1;
}; };
function g2(x, y) { function g2(i) {
var a = 5; var a2 = input[i].a;
var b = 6; var b2 = input[i].b;
a = a + a / 100; a2 = a2 + a2 / 100;
b = b + b / 100; b2 = b2 + b2 / 100;
g3(a, b); g3(i - 1, a2, b2);
}; };
function g1(x, y) { function g1(i, x3, y3, z3) {
var a = 7; var a3 = input[i].a;
var b = 8; var b3 = input[i].b;
a = a + a / 100; a3 = a3 + a3 / 100;
b = b + b / 100; b3 = b3 + b3 / 100;
g2(a, b); g2(i - 1, a3, b3);
}; };
function f(x, y) { function f(i, x4, y4) {
var a = 9; var a4 = input[i].a;
var b = 10; var b4 = input[i].b;
a = a + a / 100; a4 = a4 + a4 / 100;
b = b + b / 100; b4 = b4 + b4 / 100;
g1(a, b); g1(i - 1, a4, b4);
}; };
// Test calling f normally and as a constructor. // Test calling f normally and as a constructor.
f(11.11, 12.12); f(input.length - 1, 11.11, 12.12);
f(input.length - 1, 11.11, 12.12, "");
testingConstructCall = true; testingConstructCall = true;
new f(11.11, 12.12); new f(input.length - 1, 11.11, 12.12);
new f(input.length - 1, 11.11, 12.12, "");
// Make sure that the debug event listener vas invoked. // Make sure that the debug event listener vas invoked.
assertFalse(exception, "exception in listener " + exception) assertFalse(exception, "exception in listener " + exception)

160
deps/v8/test/mjsunit/debug-evaluate-locals-optimized.js

@ -1,4 +1,4 @@
// Copyright 2008 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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -34,6 +34,17 @@ var exception = false;
var testingConstructCall = false; var testingConstructCall = false;
var expected = [
{ locals: {a0: 1, b0: 2}, args: { names: ["i", "x0", "y0"], values: [0, 3, 4] } },
{ locals: {a1: 3, b1: 4}, args: { names: ["i", "x1", "y1"], values: [1, 5, 6] } },
{ locals: {a2: 5, b2: 6}, args: { names: ["i"], values: [2] } },
{ locals: {a3: 7, b3: 8}, args: { names: ["i", "x3", "y3", "z3"], values: [3, 9, 10, undefined] } },
{ locals: {a4: 9, b4: 10}, args: { names: ["i", "x4", "y4"], values: [4, 11, 12] } }
];
function arraySum(arr) {
return arr.reduce(function (a, b) { return a + b; }, 0);
}
function listener(event, exec_state, event_data, data) { function listener(event, exec_state, event_data, data) {
try { try {
@ -44,42 +55,63 @@ function listener(event, exec_state, event_data, data) {
for (var i = 0; i < exec_state.frameCount(); i++) { for (var i = 0; i < exec_state.frameCount(); i++) {
var frame = exec_state.frame(i); var frame = exec_state.frame(i);
if (i < exec_state.frameCount() - 1) { if (i < exec_state.frameCount() - 1) {
var expected_a = i * 2 + 1; var expected_args = expected[i].args;
var expected_b = i * 2 + 2; var expected_locals = expected[i].locals;
var expected_x = (i + 1) * 2 + 1;
var expected_y = (i + 1) * 2 + 2; // All frames except the bottom one have expected locals.
var locals = {};
// All frames except the bottom one has normal variables a and b. for (var j = 0; j < frame.localCount(); j++) {
var a = ('a' === frame.localName(0)) ? 0 : 1; locals[frame.localName(j)] = frame.localValue(j).value();
var b = 1 - a; }
assertEquals('a', frame.localName(a)); assertPropertiesEqual(expected_locals, locals);
assertEquals('b', frame.localName(b));
assertEquals(expected_a, frame.localValue(a).value()); // All frames except the bottom one have expected arguments.
assertEquals(expected_b, frame.localValue(b).value()); for (var j = 0; j < expected_args.names.length; j++) {
assertEquals(expected_args.names[j], frame.argumentName(j));
// All frames except the bottom one has arguments variables x and y. assertEquals(expected_args.values[j], frame.argumentValue(j).value());
assertEquals('x', frame.argumentName(0)); }
assertEquals('y', frame.argumentName(1));
assertEquals(expected_x, frame.argumentValue(0).value());
assertEquals(expected_y, frame.argumentValue(1).value());
// All frames except the bottom one have two scopes. // All frames except the bottom one have two scopes.
assertEquals(2, frame.scopeCount()); assertEquals(2, frame.scopeCount());
assertEquals(debug.ScopeType.Local, frame.scope(0).scopeType()); assertEquals(debug.ScopeType.Local, frame.scope(0).scopeType());
assertEquals(debug.ScopeType.Global, frame.scope(1).scopeType()); assertEquals(debug.ScopeType.Global, frame.scope(1).scopeType());
assertEquals(expected_a, frame.scope(0).scopeObject().value()['a']);
assertEquals(expected_b, frame.scope(0).scopeObject().value()['b']); Object.keys(expected_locals).forEach(function (name) {
assertEquals(expected_x, frame.scope(0).scopeObject().value()['x']); assertEquals(expected_locals[name], frame.scope(0).scopeObject().value()[name]);
assertEquals(expected_y, frame.scope(0).scopeObject().value()['y']); });
for (var j = 0; j < expected_args.names.length; j++) {
var arg_name = expected_args.names[j];
var arg_value = expected_args.values[j];
assertEquals(arg_value, frame.scope(0).scopeObject().value()[arg_name]);
}
// Evaluate in the inlined frame. // Evaluate in the inlined frame.
assertEquals(expected_a, frame.evaluate('a').value()); Object.keys(expected_locals).forEach(function (name) {
assertEquals(expected_x, frame.evaluate('x').value()); assertEquals(expected_locals[name], frame.evaluate(name).value());
assertEquals(expected_x, frame.evaluate('arguments[0]').value()); });
assertEquals(expected_a + expected_b + expected_x + expected_y,
frame.evaluate('a + b + x + y').value()); for (var j = 0; j < expected_args.names.length; j++) {
assertEquals(expected_x + expected_y, var arg_name = expected_args.names[j];
frame.evaluate('arguments[0] + arguments[1]').value()); var arg_value = expected_args.values[j];
assertEquals(arg_value, frame.evaluate(arg_name).value());
assertEquals(arg_value, frame.evaluate('arguments['+j+']').value());
}
var expected_args_sum = arraySum(expected_args.values);
var expected_locals_sum =
arraySum(Object.keys(expected_locals).
map(function (k) { return expected_locals[k]; }));
assertEquals(expected_locals_sum + expected_args_sum,
frame.evaluate(Object.keys(expected_locals).join('+') + ' + ' +
expected_args.names.join('+')).value());
var arguments_sum = expected_args.names.map(function(_, idx) {
return "arguments[" + idx + "]";
}).join('+');
assertEquals(expected_args_sum,
frame.evaluate(arguments_sum).value());
} else { } else {
// The bottom frame only have the global scope. // The bottom frame only have the global scope.
assertEquals(1, frame.scopeCount()); assertEquals(1, frame.scopeCount());
@ -121,51 +153,53 @@ function listener(event, exec_state, event_data, data) {
listenerComplete = true; listenerComplete = true;
} }
} catch (e) { } catch (e) {
exception = e.stack; exception = e.toString() + e.stack;
}; };
}; };
f();f();f(); for (var i = 0; i < 4; i++) f(expected.length - 1, 11, 12);
%OptimizeFunctionOnNextCall(f); %OptimizeFunctionOnNextCall(f);
f(); f(expected.length - 1, 11, 12);
// Add the debug event listener. // Add the debug event listener.
Debug.setListener(listener); Debug.setListener(listener);
function h(x, y) { function h(i, x0, y0) {
var a = 1; var a0 = expected[i].locals.a0;
var b = 2; var b0 = expected[i].locals.b0;
debugger; // Breakpoint. debugger; // Breakpoint.
}; }
function g3(x, y) { function g3(i, x1, y1) {
var a = 3; var a1 = expected[i].locals.a1;
var b = 4; var b1 = expected[i].locals.b1;
h(a, b); h(i - 1, a1, b1);
}; }
function g2(x, y) { function g2(i) {
var a = 5; var a2 = expected[i].locals.a2;
var b = 6; var b2 = expected[i].locals.b2;
g3(a, b); g3(i - 1, a2, b2);
}; }
function g1(x, y) { function g1(i, x3, y3, z3) {
var a = 7; var a3 = expected[i].locals.a3;
var b = 8; var b3 = expected[i].locals.b3;
g2(a, b); g2(i - 1, a3, b3);
}; }
function f(x, y) { function f(i, x4, y4) {
var a = 9; var a4 = expected[i].locals.a4;
var b = 10; var b4 = expected[i].locals.b4;
g1(a, b); g1(i - 1, a4, b4);
}; }
// Test calling f normally and as a constructor. // Test calling f normally and as a constructor.
f(11, 12); f(expected.length - 1, 11, 12);
f(expected.length - 1, 11, 12, 0);
testingConstructCall = true; testingConstructCall = true;
new f(11, 12); new f(expected.length - 1, 11, 12);
new f(expected.length - 1, 11, 12, 0);
// Make sure that the debug event listener vas invoked. // Make sure that the debug event listener vas invoked.
assertFalse(exception, "exception in listener " + exception) assertFalse(exception, "exception in listener " + exception)

103
deps/v8/test/mjsunit/regress/regress-1229.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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -29,59 +29,116 @@
// Check that %NewObjectFromBound works correctly when called from optimized // Check that %NewObjectFromBound works correctly when called from optimized
// frame. // frame.
function foo(x, y, z) { function foo1(x, y, z) {
assertEquals(1, x); assertEquals(1, x);
assertEquals(2, y); assertEquals(2, y);
assertEquals(3, z); assertEquals(3, z);
} }
var foob = foo.bind({}, 1); function foo2(x, y, z) {
assertEquals(1, x);
assertEquals(2, y);
assertEquals(undefined, z);
}
function f(y, z) { function foo3(x, y, z) {
return %NewObjectFromBound(foob); assertEquals(1, x);
assertEquals(2, y);
assertEquals(3, z);
}
var foob1 = foo1.bind({}, 1);
var foob2 = foo2.bind({}, 1);
var foob3 = foo3.bind({}, 1);
function f1(y, z) {
return %NewObjectFromBound(foob1);
}
function f2(y, z) {
return %NewObjectFromBound(foob2);
}
function f3(y, z) {
return %NewObjectFromBound(foob3);
} }
// Check that %NewObjectFromBound looks at correct frame for inlined function. // Check that %NewObjectFromBound looks at correct frame for inlined function.
function g(z, y) { function g1(z, y) {
return f(y, z); /* f should be inlined into g, note rotated arguments */ return f1(y, z); /* f should be inlined into g, note rotated arguments */
}
function g2(z, y, x) {
return f2(y); /* f should be inlined into g, note argument count mismatch */
}
function g3(z, y, x) {
return f3(x, y, z); /* f should be inlined into g, note argument count mismatch */
} }
// Check that %NewObjectFromBound looks at correct frame for inlined function. // Check that %NewObjectFromBound looks at correct frame for inlined function.
function ff(x) { } function ff(x) { }
function h(z2, y2) { function h1(z2, y2) {
var local_z = z2 >> 1; var local_z = z2 >> 1;
ff(local_z); ff(local_z);
var local_y = y2 >> 1; var local_y = y2 >> 1;
ff(local_y); ff(local_y);
return f(local_y, local_z); /* f should be inlined into h */ return f1(local_y, local_z); /* f should be inlined into h */
} }
for (var i = 0; i < 5; i++) f(2, 3); function h2(z2, y2, x2) {
%OptimizeFunctionOnNextCall(f); var local_z = z2 >> 1;
f(2, 3); ff(local_z);
var local_y = y2 >> 1;
ff(local_y);
return f2(local_y); /* f should be inlined into h */
}
function h3(z2, y2, x2) {
var local_z = z2 >> 1;
ff(local_z);
var local_y = y2 >> 1;
ff(local_y);
var local_x = x2 >> 1;
ff(local_x);
return f3(local_x, local_y, local_z); /* f should be inlined into h */
}
for (var i = 0; i < 5; i++) g(3, 2);
%OptimizeFunctionOnNextCall(g);
g(3, 2);
for (var i = 0; i < 5; i++) h(6, 4); function invoke(f, args) {
%OptimizeFunctionOnNextCall(h); for (var i = 0; i < 5; i++) f.apply(this, args);
h(6, 4); %OptimizeFunctionOnNextCall(f);
f.apply(this, args);
}
invoke(f1, [2, 3]);
invoke(f2, [2]);
invoke(f3, [2, 3, 4]);
invoke(g1, [3, 2]);
invoke(g2, [3, 2, 4]);
invoke(g3, [4, 3, 2]);
invoke(h1, [6, 4]);
invoke(h2, [6, 4, 8]);
invoke(h3, [8, 6, 4]);
// Check that %_IsConstructCall returns correct value when inlined // Check that %_IsConstructCall returns correct value when inlined
var NON_CONSTRUCT_MARKER = {}; var NON_CONSTRUCT_MARKER = {};
var CONSTRUCT_MARKER = {}; var CONSTRUCT_MARKER = {};
function baz() { function baz(x) {
return (!%_IsConstructCall()) ? NON_CONSTRUCT_MARKER : CONSTRUCT_MARKER; return (!%_IsConstructCall()) ? NON_CONSTRUCT_MARKER : CONSTRUCT_MARKER;
} }
function bar(x, y, z) { function bar(x, y, z) {
var non_construct = baz(0); /* baz should be inlined */
assertEquals(non_construct, NON_CONSTRUCT_MARKER);
var non_construct = baz(); /* baz should be inlined */ var non_construct = baz(); /* baz should be inlined */
assertEquals(non_construct, NON_CONSTRUCT_MARKER); assertEquals(non_construct, NON_CONSTRUCT_MARKER);
var construct = new baz(); var non_construct = baz(0, 0); /* baz should be inlined */
assertEquals(non_construct, NON_CONSTRUCT_MARKER);
var construct = new baz(0);
assertEquals(construct, CONSTRUCT_MARKER); assertEquals(construct, CONSTRUCT_MARKER);
} }
for (var i = 0; i < 5; i++) new bar(1, 2, 3); invoke(bar, [1, 2, 3]);
%OptimizeFunctionOnNextCall(bar);
bar(1, 2, 3);

5
deps/v8/tools/js2c.py

@ -128,12 +128,13 @@ def ExpandMacros(lines, macros):
end = pattern_match.end() end = pattern_match.end()
assert lines[end - 1] == '(' assert lines[end - 1] == '('
last_match = end last_match = end
arg_index = 0 arg_index = [0] # Wrap state into array, to work around Python "scoping"
mapping = { } mapping = { }
def add_arg(str): def add_arg(str):
# Remember to expand recursively in the arguments # Remember to expand recursively in the arguments
replacement = ExpandMacros(str.strip(), macros) replacement = ExpandMacros(str.strip(), macros)
mapping[macro.args[arg_index]] = replacement mapping[macro.args[arg_index[0]]] = replacement
arg_index[0] += 1
while end < len(lines) and height > 0: while end < len(lines) and height > 0:
# We don't count commas at higher nesting levels. # We don't count commas at higher nesting levels.
if lines[end] == ',' and height == 1: if lines[end] == ',' and height == 1:

4
deps/v8/tools/test.py

@ -1211,6 +1211,7 @@ def BuildOptions():
dest="suppress_dialogs", default=True, action="store_true") dest="suppress_dialogs", default=True, action="store_true")
result.add_option("--no-suppress-dialogs", help="Display Windows dialogs for crashing tests", result.add_option("--no-suppress-dialogs", help="Display Windows dialogs for crashing tests",
dest="suppress_dialogs", action="store_false") dest="suppress_dialogs", action="store_false")
result.add_option("--mips-arch-variant", help="mips architecture variant: mips32r1/mips32r2", default="mips32r2");
result.add_option("--shell", help="Path to V8 shell", default="d8") result.add_option("--shell", help="Path to V8 shell", default="d8")
result.add_option("--isolates", help="Whether to test isolates", default=False, action="store_true") result.add_option("--isolates", help="Whether to test isolates", default=False, action="store_true")
result.add_option("--store-unexpected-output", result.add_option("--store-unexpected-output",
@ -1272,6 +1273,9 @@ def ProcessOptions(options):
if options.snapshot: if options.snapshot:
options.scons_flags.append("snapshot=on") options.scons_flags.append("snapshot=on")
global VARIANT_FLAGS global VARIANT_FLAGS
if options.mips_arch_variant:
options.scons_flags.append("mips_arch_variant=" + options.mips_arch_variant)
if options.stress_only: if options.stress_only:
VARIANT_FLAGS = [['--stress-opt', '--always-opt']] VARIANT_FLAGS = [['--stress-opt', '--always-opt']]
if options.nostress: if options.nostress:

Loading…
Cancel
Save