Browse Source

Upgrade V8 to 2.5.0

v0.7.4-release
Ryan Dahl 14 years ago
parent
commit
1b2f6f9e29
  1. 1
      deps/v8/AUTHORS
  2. 22
      deps/v8/ChangeLog
  3. 6
      deps/v8/SConstruct
  4. 2
      deps/v8/benchmarks/base.js
  5. 4
      deps/v8/include/v8-profiler.h
  6. 65
      deps/v8/include/v8.h
  7. 2
      deps/v8/src/SConscript
  8. 75
      deps/v8/src/api.cc
  9. 6
      deps/v8/src/api.h
  10. 2
      deps/v8/src/arm/code-stubs-arm.cc
  11. 10
      deps/v8/src/arm/codegen-arm.cc
  12. 7
      deps/v8/src/arm/codegen-arm.h
  13. 7
      deps/v8/src/arm/full-codegen-arm.cc
  14. 4
      deps/v8/src/arm/simulator-arm.cc
  15. 6
      deps/v8/src/arm/simulator-arm.h
  16. 5
      deps/v8/src/ast.h
  17. 197
      deps/v8/src/atomic.h
  18. 152
      deps/v8/src/cached-powers.cc
  19. 84
      deps/v8/src/cached-powers.h
  20. 43
      deps/v8/src/codegen.cc
  21. 1
      deps/v8/src/codegen.h
  22. 442
      deps/v8/src/compiler.cc
  23. 212
      deps/v8/src/compiler.h
  24. 68
      deps/v8/src/conversions.cc
  25. 9
      deps/v8/src/data-flow.cc
  26. 6
      deps/v8/src/data-flow.h
  27. 13
      deps/v8/src/execution.cc
  28. 5
      deps/v8/src/execution.h
  29. 18
      deps/v8/src/fast-dtoa.cc
  30. 34
      deps/v8/src/full-codegen.cc
  31. 11
      deps/v8/src/full-codegen.h
  32. 26
      deps/v8/src/handles.cc
  33. 31
      deps/v8/src/ia32/codegen-ia32.cc
  34. 7
      deps/v8/src/ia32/codegen-ia32.h
  35. 7
      deps/v8/src/ia32/full-codegen-ia32.cc
  36. 3
      deps/v8/src/liveedit-debugger.js
  37. 48
      deps/v8/src/liveedit.cc
  38. 4
      deps/v8/src/mips/simulator-mips.cc
  39. 6
      deps/v8/src/mips/simulator-mips.h
  40. 37
      deps/v8/src/objects.cc
  41. 5
      deps/v8/src/objects.h
  42. 67
      deps/v8/src/parser.cc
  43. 16
      deps/v8/src/parser.h
  44. 2461
      deps/v8/src/powers-ten.h
  45. 115
      deps/v8/src/profile-generator.cc
  46. 19
      deps/v8/src/profile-generator.h
  47. 150
      deps/v8/src/regexp.js
  48. 40
      deps/v8/src/rewriter.cc
  49. 31
      deps/v8/src/rewriter.h
  50. 26
      deps/v8/src/scopes.cc
  51. 10
      deps/v8/src/scopes.h
  52. 5
      deps/v8/src/string.js
  53. 181
      deps/v8/src/strtod.cc
  54. 40
      deps/v8/src/strtod.h
  55. 26
      deps/v8/src/top.cc
  56. 11
      deps/v8/src/v8-counters.h
  57. 2
      deps/v8/src/v8.cc
  58. 4
      deps/v8/src/version.cc
  59. 14
      deps/v8/src/x64/code-stubs-x64.cc
  60. 32
      deps/v8/src/x64/codegen-x64.cc
  61. 7
      deps/v8/src/x64/codegen-x64.h
  62. 6
      deps/v8/src/x64/full-codegen-x64.cc
  63. 1
      deps/v8/test/cctest/SConscript
  64. 148
      deps/v8/test/cctest/test-api.cc
  65. 32
      deps/v8/test/cctest/test-conversions.cc
  66. 80
      deps/v8/test/cctest/test-heap-profiler.cc
  67. 201
      deps/v8/test/cctest/test-strtod.cc
  68. 87
      deps/v8/test/mjsunit/regexp.js
  69. 35
      deps/v8/test/mjsunit/regress/regress-58740.js
  70. 58
      deps/v8/test/mjsunit/regress/regress-create-exception.js
  71. 13
      deps/v8/test/mjsunit/smi-negative-zero.js
  72. 4
      deps/v8/tools/gyp/v8.gyp

1
deps/v8/AUTHORS

@ -6,6 +6,7 @@
Google Inc.
Sigma Designs Inc.
ARM Ltd.
Hewlett-Packard Development Company, LP
Alexander Botero-Lowry <alexbl@FreeBSD.org>
Alexandre Vassalotti <avassalotti@gmail.com>

22
deps/v8/ChangeLog

@ -1,3 +1,25 @@
2010-10-18: Version 2.5.0
Fixed bug in cache handling of lastIndex on global regexps
(issue http://crbug.com/58740).
Added USE_SIMULATOR macro that explicitly indicates that we wish to use
the simulator as the execution engine (by Mark Lam <mark.lam@palm.com>
from Hewlett-Packard Development Company, LP).
Fixed compilation error on ARM with gcc 4.4 (issue 894).
2010-10-13: Version 2.4.9
Fixed a bug in the handling of conditional expressions in test
contexts in compiler for top-level code.
Added "//@ sourceURL" information to the StackTrace API.
Exposed RegExp construction through the API.
2010-10-04: Version 2.4.8
Fixed a bug in ResumeProfilerEx causing it to not always write out the

6
deps/v8/SConstruct

@ -206,7 +206,8 @@ LIBRARY_FLAGS = {
},
'simulator:arm': {
'CCFLAGS': ['-m32'],
'LINKFLAGS': ['-m32']
'LINKFLAGS': ['-m32'],
'CPPDEFINES': ['USE_SIMULATOR']
},
'arch:mips': {
'CPPDEFINES': ['V8_TARGET_ARCH_MIPS'],
@ -217,7 +218,8 @@ LIBRARY_FLAGS = {
},
'simulator:mips': {
'CCFLAGS': ['-m32'],
'LINKFLAGS': ['-m32']
'LINKFLAGS': ['-m32'],
'CPPDEFINES': ['USE_SIMULATOR']
},
'arch:x64': {
'CPPDEFINES': ['V8_TARGET_ARCH_X64'],

2
deps/v8/benchmarks/base.js

@ -78,7 +78,7 @@ BenchmarkSuite.suites = [];
// Scores are not comparable across versions. Bump the version if
// you're making changes that will affect that scores, e.g. if you add
// a new benchmark or change an existing one.
BenchmarkSuite.version = '6 (candidate)';
BenchmarkSuite.version = '6';
// To make the benchmark results predictable, we replace Math.random

4
deps/v8/include/v8-profiler.h

@ -245,7 +245,9 @@ class V8EXPORT HeapGraphNode {
kString = 2, // A string.
kObject = 3, // A JS object (except for arrays and strings).
kCode = 4, // Compiled code.
kClosure = 5 // Function closure.
kClosure = 5, // Function closure.
kRegExp = 6, // RegExp.
kHeapNumber = 7 // Number stored in the heap.
};
/** Returns node type (see HeapGraphNode::Type). */

65
deps/v8/include/v8.h

@ -758,8 +758,9 @@ class V8EXPORT StackTrace {
kFunctionName = 1 << 3,
kIsEval = 1 << 4,
kIsConstructor = 1 << 5,
kScriptNameOrSourceURL = 1 << 6,
kOverview = kLineNumber | kColumnOffset | kScriptName | kFunctionName,
kDetailed = kOverview | kIsEval | kIsConstructor
kDetailed = kOverview | kIsEval | kIsConstructor | kScriptNameOrSourceURL
};
/**
@ -818,6 +819,13 @@ class V8EXPORT StackFrame {
*/
Local<String> GetScriptName() const;
/**
* Returns the name of the resource that contains the script for the
* function for this StackFrame or sourceURL value if the script name
* is undefined and its source ends with //@ sourceURL=... string.
*/
Local<String> GetScriptNameOrSourceURL() const;
/**
* Returns the name of the function associated with this stack frame.
*/
@ -1359,6 +1367,53 @@ class Date : public Value {
};
/**
* An instance of the built-in RegExp constructor (ECMA-262, 15.10).
*/
class RegExp : public Value {
public:
/**
* Regular expression flag bits. They can be or'ed to enable a set
* of flags.
*/
enum Flags {
kNone = 0,
kGlobal = 1,
kIgnoreCase = 2,
kMultiline = 4
};
/**
* Creates a regular expression from the given pattern string and
* the flags bit field. May throw a JavaScript exception as
* described in ECMA-262, 15.10.4.1.
*
* For example,
* RegExp::New(v8::String::New("foo"),
* static_cast<RegExp::Flags>(kGlobal | kMultiline))
* is equivalent to evaluating "/foo/gm".
*/
V8EXPORT static Local<RegExp> New(Handle<String> pattern,
Flags flags);
/**
* Returns the value of the source property: a string representing
* the regular expression.
*/
V8EXPORT Local<String> GetSource() const;
/**
* Returns the flags bit field.
*/
V8EXPORT Flags GetFlags() const;
static inline RegExp* Cast(v8::Value* obj);
private:
V8EXPORT static void CheckCast(v8::Value* obj);
};
enum PropertyAttribute {
None = 0,
ReadOnly = 1 << 0,
@ -3617,6 +3672,14 @@ Date* Date::Cast(v8::Value* value) {
}
RegExp* RegExp::Cast(v8::Value* value) {
#ifdef V8_ENABLE_CHECKS
CheckCast(value);
#endif
return static_cast<RegExp*>(value);
}
Object* Object::Cast(v8::Value* value) {
#ifdef V8_ENABLE_CHECKS
CheckCast(value);

2
deps/v8/src/SConscript

@ -42,6 +42,7 @@ SOURCES = {
ast.cc
bootstrapper.cc
builtins.cc
cached-powers.cc
checks.cc
circular-queue.cc
code-stubs.cc
@ -102,6 +103,7 @@ SOURCES = {
spaces.cc
string-search.cc
string-stream.cc
strtod.cc
stub-cache.cc
token.cc
top.cc

75
deps/v8/src/api.cc

@ -1679,6 +1679,21 @@ Local<String> StackFrame::GetScriptName() const {
}
Local<String> StackFrame::GetScriptNameOrSourceURL() const {
if (IsDeadCheck("v8::StackFrame::GetScriptNameOrSourceURL()")) {
return Local<String>();
}
ENTER_V8;
HandleScope scope;
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
i::Handle<i::Object> name = GetProperty(self, "scriptNameOrSourceURL");
if (!name->IsString()) {
return Local<String>();
}
return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
}
Local<String> StackFrame::GetFunctionName() const {
if (IsDeadCheck("v8::StackFrame::GetFunctionName()")) return Local<String>();
ENTER_V8;
@ -1991,6 +2006,15 @@ void v8::Date::CheckCast(v8::Value* that) {
}
void v8::RegExp::CheckCast(v8::Value* that) {
if (IsDeadCheck("v8::RegExp::Cast()")) return;
i::Handle<i::Object> obj = Utils::OpenHandle(that);
ApiCheck(obj->IsJSRegExp(),
"v8::RegExp::Cast()",
"Could not convert to regular expression");
}
bool Value::BooleanValue() const {
if (IsDeadCheck("v8::Value::BooleanValue()")) return false;
LOG_API("BooleanValue");
@ -3712,6 +3736,57 @@ double v8::Date::NumberValue() const {
}
static i::Handle<i::String> RegExpFlagsToString(RegExp::Flags flags) {
char flags_buf[3];
int num_flags = 0;
if ((flags & RegExp::kGlobal) != 0) flags_buf[num_flags++] = 'g';
if ((flags & RegExp::kMultiline) != 0) flags_buf[num_flags++] = 'm';
if ((flags & RegExp::kIgnoreCase) != 0) flags_buf[num_flags++] = 'i';
ASSERT(num_flags <= static_cast<int>(ARRAY_SIZE(flags_buf)));
return i::Factory::LookupSymbol(
i::Vector<const char>(flags_buf, num_flags));
}
Local<v8::RegExp> v8::RegExp::New(Handle<String> pattern,
Flags flags) {
EnsureInitialized("v8::RegExp::New()");
LOG_API("RegExp::New");
ENTER_V8;
EXCEPTION_PREAMBLE();
i::Handle<i::JSRegExp> obj = i::Execution::NewJSRegExp(
Utils::OpenHandle(*pattern),
RegExpFlagsToString(flags),
&has_pending_exception);
EXCEPTION_BAILOUT_CHECK(Local<v8::RegExp>());
return Utils::ToLocal(i::Handle<i::JSRegExp>::cast(obj));
}
Local<v8::String> v8::RegExp::GetSource() const {
if (IsDeadCheck("v8::RegExp::GetSource()")) return Local<v8::String>();
i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
return Utils::ToLocal(i::Handle<i::String>(obj->Pattern()));
}
// Assert that the static flags cast in GetFlags is valid.
#define REGEXP_FLAG_ASSERT_EQ(api_flag, internal_flag) \
STATIC_ASSERT(static_cast<int>(v8::RegExp::api_flag) == \
static_cast<int>(i::JSRegExp::internal_flag))
REGEXP_FLAG_ASSERT_EQ(kNone, NONE);
REGEXP_FLAG_ASSERT_EQ(kGlobal, GLOBAL);
REGEXP_FLAG_ASSERT_EQ(kIgnoreCase, IGNORE_CASE);
REGEXP_FLAG_ASSERT_EQ(kMultiline, MULTILINE);
#undef REGEXP_FLAG_ASSERT_EQ
v8::RegExp::Flags v8::RegExp::GetFlags() const {
if (IsDeadCheck("v8::RegExp::GetFlags()")) return v8::RegExp::kNone;
i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
return static_cast<RegExp::Flags>(obj->GetFlags().value());
}
Local<v8::Array> v8::Array::New(int length) {
EnsureInitialized("v8::Array::New()");
LOG_API("Array::New");

6
deps/v8/src/api.h

@ -174,6 +174,8 @@ class Utils {
v8::internal::Handle<v8::internal::JSFunction> obj);
static inline Local<String> ToLocal(
v8::internal::Handle<v8::internal::String> obj);
static inline Local<RegExp> ToLocal(
v8::internal::Handle<v8::internal::JSRegExp> obj);
static inline Local<Object> ToLocal(
v8::internal::Handle<v8::internal::JSObject> obj);
static inline Local<Array> ToLocal(
@ -209,6 +211,8 @@ class Utils {
OpenHandle(const ObjectTemplate* that);
static inline v8::internal::Handle<v8::internal::Object>
OpenHandle(const Data* data);
static inline v8::internal::Handle<v8::internal::JSRegExp>
OpenHandle(const RegExp* data);
static inline v8::internal::Handle<v8::internal::JSObject>
OpenHandle(const v8::Object* data);
static inline v8::internal::Handle<v8::internal::JSArray>
@ -265,6 +269,7 @@ MAKE_TO_LOCAL(ToLocal, Context, Context)
MAKE_TO_LOCAL(ToLocal, Object, Value)
MAKE_TO_LOCAL(ToLocal, JSFunction, Function)
MAKE_TO_LOCAL(ToLocal, String, String)
MAKE_TO_LOCAL(ToLocal, JSRegExp, RegExp)
MAKE_TO_LOCAL(ToLocal, JSObject, Object)
MAKE_TO_LOCAL(ToLocal, JSArray, Array)
MAKE_TO_LOCAL(ToLocal, Proxy, External)
@ -297,6 +302,7 @@ MAKE_OPEN_HANDLE(ObjectTemplate, ObjectTemplateInfo)
MAKE_OPEN_HANDLE(Signature, SignatureInfo)
MAKE_OPEN_HANDLE(TypeSwitch, TypeSwitchInfo)
MAKE_OPEN_HANDLE(Data, Object)
MAKE_OPEN_HANDLE(RegExp, JSRegExp)
MAKE_OPEN_HANDLE(Object, JSObject)
MAKE_OPEN_HANDLE(Array, JSArray)
MAKE_OPEN_HANDLE(String, String)

2
deps/v8/src/arm/code-stubs-arm.cc

@ -935,7 +935,7 @@ void CompareStub::Generate(MacroAssembler* masm) {
__ orr(r2, r1, r0);
__ tst(r2, Operand(kSmiTagMask));
__ b(ne, &not_two_smis);
__ sub(r0, r1, r0);
__ sub(r0, r1, r0, SetCC);
__ b(vc, &smi_done);
// Correct the sign in case of overflow.
__ rsb(r0, r0, Operand(0, RelocInfo::NONE));

10
deps/v8/src/arm/codegen-arm.cc

@ -175,7 +175,7 @@ void CodeGenerator::Generate(CompilationInfo* info) {
// Adjust for function-level loop nesting.
ASSERT_EQ(0, loop_nesting_);
loop_nesting_ = info->loop_nesting();
loop_nesting_ = info->is_in_loop() ? 1 : 0;
{
CodeGenState state(this);
@ -339,7 +339,7 @@ void CodeGenerator::Generate(CompilationInfo* info) {
}
// Adjust for function-level loop nesting.
ASSERT(loop_nesting_ == info->loop_nesting());
ASSERT(loop_nesting_ == info->is_in_loop()? 1 : 0);
loop_nesting_ = 0;
// Code generation state must be reset.
@ -3132,9 +3132,9 @@ void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
// Build the function info and instantiate it.
Handle<SharedFunctionInfo> function_info =
Compiler::BuildFunctionInfo(node, script(), this);
// Check for stack-overflow exception.
if (HasStackOverflow()) {
Compiler::BuildFunctionInfo(node, script());
if (function_info.is_null()) {
SetStackOverflow();
ASSERT(frame_->height() == original_height);
return;
}

7
deps/v8/src/arm/codegen-arm.h

@ -207,9 +207,7 @@ enum NopMarkerTypes {
class CodeGenerator: public AstVisitor {
public:
// Takes a function literal, generates code for it. This function should only
// be called by compiler.cc.
static Handle<Code> MakeCode(CompilationInfo* info);
static bool MakeCode(CompilationInfo* info);
// Printing of AST, etc. as requested by flags.
static void MakeCodePrologue(CompilationInfo* info);
@ -449,9 +447,6 @@ class CodeGenerator: public AstVisitor {
void Branch(bool if_true, JumpTarget* target);
void CheckStack();
static InlineFunctionGenerator FindInlineFunctionGenerator(
Runtime::FunctionId function_id);
bool CheckForInlineRuntimeCall(CallRuntime* node);
static Handle<Code> ComputeLazyCompile(int argc);

7
deps/v8/src/arm/full-codegen-arm.cc

@ -62,6 +62,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
SetFunctionPosition(function());
Comment cmnt(masm_, "[ function compiled by full code generator");
#ifdef DEBUG
if (strlen(FLAG_stop_at) > 0 &&
info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
__ stop("stop-at");
}
#endif
int locals_count = scope()->num_stack_slots();
__ Push(lr, fp, cp, r1);

4
deps/v8/src/arm/simulator-arm.cc

@ -37,7 +37,7 @@
#include "arm/constants-arm.h"
#include "arm/simulator-arm.h"
#if !defined(__arm__)
#if !defined(__arm__) || defined(USE_SIMULATOR)
// Only build the simulator if not compiling for real ARM hardware.
namespace assembler {
@ -2840,6 +2840,6 @@ uintptr_t Simulator::PopAddress() {
} } // namespace assembler::arm
#endif // __arm__
#endif // !__arm__ || USE_SIMULATOR
#endif // V8_TARGET_ARCH_ARM

6
deps/v8/src/arm/simulator-arm.h

@ -38,7 +38,7 @@
#include "allocation.h"
#if defined(__arm__)
#if defined(__arm__) && !defined(USE_SIMULATOR)
// When running without a simulator we call the entry directly.
#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
@ -70,7 +70,7 @@ class SimulatorStack : public v8::internal::AllStatic {
reinterpret_cast<TryCatch*>(try_catch_address)
#else // defined(__arm__)
#else // !defined(__arm__) || defined(USE_SIMULATOR)
// When running with the simulator transition into simulated execution at this
// point.
@ -356,6 +356,6 @@ class SimulatorStack : public v8::internal::AllStatic {
};
#endif // defined(__arm__)
#endif // !defined(__arm__) || defined(USE_SIMULATOR)
#endif // V8_ARM_SIMULATOR_ARM_H_

5
deps/v8/src/ast.h

@ -1436,6 +1436,11 @@ class FunctionLiteral: public Expression {
bool AllowsLazyCompilation();
Handle<String> debug_name() const {
if (name_->length() > 0) return name_;
return inferred_name();
}
Handle<String> inferred_name() const { return inferred_name_; }
void set_inferred_name(Handle<String> inferred_name) {
inferred_name_ = inferred_name;

197
deps/v8/src/atomic.h

@ -1,197 +0,0 @@
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// This module wraps compiler specific syncronisation related intrinsics.
#ifndef V8_ATOMIC_H_
#define V8_ATOMIC_H_
// Avoid warning when compiled with /Wp64.
#ifndef _MSC_VER
#define __w64
#endif
typedef __w64 int32_t Atomic32;
#ifdef V8_TARGET_ARCH_X64
// We need to be able to go between Atomic64 and AtomicWord implicitly. This
// means Atomic64 and AtomicWord should be the same type on 64-bit.
typedef intptr_t Atomic64;
#endif
// Use AtomicWord for a machine-sized pointer. It will use the Atomic32 or
// Atomic64 routines below, depending on your architecture.
typedef intptr_t AtomicWord;
inline void AtomicAdd(volatile Atomic32* ptr, Atomic32 value);
inline void AtomicOr(volatile Atomic32* ptr, Atomic32 value);
inline void AtomicAnd(volatile Atomic32* ptr, Atomic32 value);
inline bool AtomicCompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value);
#if defined(V8_TARGET_ARCH_X64)
inline bool AtomicCompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value);
#endif
#if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X64)
// Microsoft Visual C++ specific stuff.
#ifdef _MSC_VER
#if (_MSC_VER >= 1500)
#include <intrin.h>
#else
// For older versions we have to provide intrisic signatures.
long _InterlockedExchangeAdd (long volatile* Addend, long Value);
long _InterlockedOr (long volatile* Value, long Mask);
long _InterlockedAnd (long volatile *Value, long Mask);
long _InterlockedCompareExchange (long volatile* Destination,
long Exchange,
long Comperand);
#pragma intrinsic(_InterlockedExchangeAdd)
#pragma intrinsic(_InterlockedOr)
#pragma intrinsic(_InterlockedAnd)
#pragma intrinsic(_InterlockedCompareExchange)
#endif
inline void AtomicAdd(volatile Atomic32* ptr, Atomic32 value) {
_InterlockedExchangeAdd(reinterpret_cast<long volatile*>(ptr),
static_cast<long>(value));
}
inline void AtomicOr(volatile Atomic32* ptr, Atomic32 value) {
_InterlockedOr(reinterpret_cast<long volatile*>(ptr),
static_cast<long>(value));
}
inline void AtomicAnd(volatile Atomic32* ptr, Atomic32 value) {
_InterlockedAnd(reinterpret_cast<long volatile*>(ptr),
static_cast<long>(value));
}
inline bool AtomicCompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
long result = _InterlockedCompareExchange(
reinterpret_cast<long volatile*>(ptr),
static_cast<long>(new_value),
static_cast<long>(old_value));
return result == static_cast<long>(old_value);
}
#if defined(V8_TARGET_ARCH_X64)
inline bool AtomicCompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value) {
__int64 result = _InterlockedCompareExchange_64(
reinterpret_cast<__int64 volatile*>(ptr),
static_cast<__int64>(new_value),
static_cast<__int64>(old_value));
return result == static_cast<__int64>(old_value);
}
#endif
#define ATOMIC_SUPPORTED 1
#endif // _MSC_VER
// GCC specific stuff
#ifdef __GNUC__
inline void AtomicAdd(volatile Atomic32* ptr, Atomic32 value) {
__sync_fetch_and_add(ptr, value);
}
inline void AtomicOr(volatile Atomic32* ptr, Atomic32 value) {
__sync_fetch_and_or(ptr, value);
}
inline void AtomicAnd(volatile Atomic32* ptr, Atomic32 value) {
__sync_fetch_and_and(ptr, value);
}
inline bool AtomicCompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
return __sync_bool_compare_and_swap(ptr, old_value, new_value);
}
#if defined(V8_TARGET_ARCH_X64)
inline bool AtomicCompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value) {
return __sync_bool_compare_and_swap(ptr, old_value, new_value);
}
#endif
#define ATOMIC_SUPPORTED 1
#endif
#endif // defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X64)
#ifndef ATOMIC_SUPPORTED
inline void AtomicAdd(volatile Atomic32* ptr, Atomic32 value) {
*ptr += value;
}
inline void AtomicOr(volatile Atomic32* ptr, Atomic32 value) {
*ptr |= value;
}
inline void AtomicAnd(volatile Atomic32* ptr, Atomic32 value) {
*ptr &= value;
}
inline bool AtomicCompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
if (*ptr == old_value) {
*ptr = new_value;
return true;
}
return false;
}
#if defined(V8_TARGET_ARCH_X64)
inline bool AtomicCompareAndSwap(volatile Atomic64* ptr,
Atomic64 old_value,
Atomic64 new_value) {
if (*ptr == old_value) {
*ptr = new_value;
return true;
}
return false;
}
#endif
#define ATOMIC_SUPPORTED 0
#endif
#endif

152
deps/v8/src/cached-powers.cc

@ -0,0 +1,152 @@
// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdarg.h>
#include <limits.h>
#include "v8.h"
#include "cached-powers.h"
namespace v8 {
namespace internal {
struct CachedPower {
uint64_t significand;
int16_t binary_exponent;
int16_t decimal_exponent;
};
static const CachedPower kCachedPowers[] = {
{V8_2PART_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
{V8_2PART_UINT64_C(0xab70fe17, c79ac6ca), -1060, -300},
{V8_2PART_UINT64_C(0xff77b1fc, bebcdc4f), -1034, -292},
{V8_2PART_UINT64_C(0xbe5691ef, 416bd60c), -1007, -284},
{V8_2PART_UINT64_C(0x8dd01fad, 907ffc3c), -980, -276},
{V8_2PART_UINT64_C(0xd3515c28, 31559a83), -954, -268},
{V8_2PART_UINT64_C(0x9d71ac8f, ada6c9b5), -927, -260},
{V8_2PART_UINT64_C(0xea9c2277, 23ee8bcb), -901, -252},
{V8_2PART_UINT64_C(0xaecc4991, 4078536d), -874, -244},
{V8_2PART_UINT64_C(0x823c1279, 5db6ce57), -847, -236},
{V8_2PART_UINT64_C(0xc2109436, 4dfb5637), -821, -228},
{V8_2PART_UINT64_C(0x9096ea6f, 3848984f), -794, -220},
{V8_2PART_UINT64_C(0xd77485cb, 25823ac7), -768, -212},
{V8_2PART_UINT64_C(0xa086cfcd, 97bf97f4), -741, -204},
{V8_2PART_UINT64_C(0xef340a98, 172aace5), -715, -196},
{V8_2PART_UINT64_C(0xb23867fb, 2a35b28e), -688, -188},
{V8_2PART_UINT64_C(0x84c8d4df, d2c63f3b), -661, -180},
{V8_2PART_UINT64_C(0xc5dd4427, 1ad3cdba), -635, -172},
{V8_2PART_UINT64_C(0x936b9fce, bb25c996), -608, -164},
{V8_2PART_UINT64_C(0xdbac6c24, 7d62a584), -582, -156},
{V8_2PART_UINT64_C(0xa3ab6658, 0d5fdaf6), -555, -148},
{V8_2PART_UINT64_C(0xf3e2f893, dec3f126), -529, -140},
{V8_2PART_UINT64_C(0xb5b5ada8, aaff80b8), -502, -132},
{V8_2PART_UINT64_C(0x87625f05, 6c7c4a8b), -475, -124},
{V8_2PART_UINT64_C(0xc9bcff60, 34c13053), -449, -116},
{V8_2PART_UINT64_C(0x964e858c, 91ba2655), -422, -108},
{V8_2PART_UINT64_C(0xdff97724, 70297ebd), -396, -100},
{V8_2PART_UINT64_C(0xa6dfbd9f, b8e5b88f), -369, -92},
{V8_2PART_UINT64_C(0xf8a95fcf, 88747d94), -343, -84},
{V8_2PART_UINT64_C(0xb9447093, 8fa89bcf), -316, -76},
{V8_2PART_UINT64_C(0x8a08f0f8, bf0f156b), -289, -68},
{V8_2PART_UINT64_C(0xcdb02555, 653131b6), -263, -60},
{V8_2PART_UINT64_C(0x993fe2c6, d07b7fac), -236, -52},
{V8_2PART_UINT64_C(0xe45c10c4, 2a2b3b06), -210, -44},
{V8_2PART_UINT64_C(0xaa242499, 697392d3), -183, -36},
{V8_2PART_UINT64_C(0xfd87b5f2, 8300ca0e), -157, -28},
{V8_2PART_UINT64_C(0xbce50864, 92111aeb), -130, -20},
{V8_2PART_UINT64_C(0x8cbccc09, 6f5088cc), -103, -12},
{V8_2PART_UINT64_C(0xd1b71758, e219652c), -77, -4},
{V8_2PART_UINT64_C(0x9c400000, 00000000), -50, 4},
{V8_2PART_UINT64_C(0xe8d4a510, 00000000), -24, 12},
{V8_2PART_UINT64_C(0xad78ebc5, ac620000), 3, 20},
{V8_2PART_UINT64_C(0x813f3978, f8940984), 30, 28},
{V8_2PART_UINT64_C(0xc097ce7b, c90715b3), 56, 36},
{V8_2PART_UINT64_C(0x8f7e32ce, 7bea5c70), 83, 44},
{V8_2PART_UINT64_C(0xd5d238a4, abe98068), 109, 52},
{V8_2PART_UINT64_C(0x9f4f2726, 179a2245), 136, 60},
{V8_2PART_UINT64_C(0xed63a231, d4c4fb27), 162, 68},
{V8_2PART_UINT64_C(0xb0de6538, 8cc8ada8), 189, 76},
{V8_2PART_UINT64_C(0x83c7088e, 1aab65db), 216, 84},
{V8_2PART_UINT64_C(0xc45d1df9, 42711d9a), 242, 92},
{V8_2PART_UINT64_C(0x924d692c, a61be758), 269, 100},
{V8_2PART_UINT64_C(0xda01ee64, 1a708dea), 295, 108},
{V8_2PART_UINT64_C(0xa26da399, 9aef774a), 322, 116},
{V8_2PART_UINT64_C(0xf209787b, b47d6b85), 348, 124},
{V8_2PART_UINT64_C(0xb454e4a1, 79dd1877), 375, 132},
{V8_2PART_UINT64_C(0x865b8692, 5b9bc5c2), 402, 140},
{V8_2PART_UINT64_C(0xc83553c5, c8965d3d), 428, 148},
{V8_2PART_UINT64_C(0x952ab45c, fa97a0b3), 455, 156},
{V8_2PART_UINT64_C(0xde469fbd, 99a05fe3), 481, 164},
{V8_2PART_UINT64_C(0xa59bc234, db398c25), 508, 172},
{V8_2PART_UINT64_C(0xf6c69a72, a3989f5c), 534, 180},
{V8_2PART_UINT64_C(0xb7dcbf53, 54e9bece), 561, 188},
{V8_2PART_UINT64_C(0x88fcf317, f22241e2), 588, 196},
{V8_2PART_UINT64_C(0xcc20ce9b, d35c78a5), 614, 204},
{V8_2PART_UINT64_C(0x98165af3, 7b2153df), 641, 212},
{V8_2PART_UINT64_C(0xe2a0b5dc, 971f303a), 667, 220},
{V8_2PART_UINT64_C(0xa8d9d153, 5ce3b396), 694, 228},
{V8_2PART_UINT64_C(0xfb9b7cd9, a4a7443c), 720, 236},
{V8_2PART_UINT64_C(0xbb764c4c, a7a44410), 747, 244},
{V8_2PART_UINT64_C(0x8bab8eef, b6409c1a), 774, 252},
{V8_2PART_UINT64_C(0xd01fef10, a657842c), 800, 260},
{V8_2PART_UINT64_C(0x9b10a4e5, e9913129), 827, 268},
{V8_2PART_UINT64_C(0xe7109bfb, a19c0c9d), 853, 276},
{V8_2PART_UINT64_C(0xac2820d9, 623bf429), 880, 284},
{V8_2PART_UINT64_C(0x80444b5e, 7aa7cf85), 907, 292},
{V8_2PART_UINT64_C(0xbf21e440, 03acdd2d), 933, 300},
{V8_2PART_UINT64_C(0x8e679c2f, 5e44ff8f), 960, 308},
{V8_2PART_UINT64_C(0xd433179d, 9c8cb841), 986, 316},
{V8_2PART_UINT64_C(0x9e19db92, b4e31ba9), 1013, 324},
{V8_2PART_UINT64_C(0xeb96bf6e, badf77d9), 1039, 332},
{V8_2PART_UINT64_C(0xaf87023b, 9bf0ee6b), 1066, 340},
};
static const int kCachedPowersLength = ARRAY_SIZE(kCachedPowers);
static const int kCachedPowersOffset = -kCachedPowers[0].decimal_exponent;
static const double kD_1_LOG2_10 = 0.30102999566398114; // 1 / lg(10)
static const int kCachedPowersDecimalDistance =
kCachedPowers[1].decimal_exponent - kCachedPowers[0].decimal_exponent;
void GetCachedPowerForBinaryExponentRange(int min_exponent,
int max_exponent,
DiyFp* power,
int* decimal_exponent) {
int kQ = DiyFp::kSignificandSize;
double k = ceiling((min_exponent + kQ - 1) * kD_1_LOG2_10);
int foo = kCachedPowersOffset;
int index =
(foo + static_cast<int>(k) - 1) / kCachedPowersDecimalDistance + 1;
ASSERT(0 <= index && index < kCachedPowersLength);
CachedPower cached_power = kCachedPowers[index];
ASSERT(min_exponent <= cached_power.binary_exponent);
ASSERT(cached_power.binary_exponent <= max_exponent);
*decimal_exponent = cached_power.decimal_exponent;
*power = DiyFp(cached_power.significand, cached_power.binary_exponent);
}
} } // namespace v8::internal

84
deps/v8/src/cached-powers.h

@ -33,86 +33,10 @@
namespace v8 {
namespace internal {
struct CachedPower {
uint64_t significand;
int16_t binary_exponent;
int16_t decimal_exponent;
};
// The following defines implement the interface between this file and the
// generated 'powers_ten.h'.
// GRISU_CACHE_NAME(1) contains all possible cached powers.
// GRISU_CACHE_NAME(i) contains GRISU_CACHE_NAME(1) where only every 'i'th
// element is kept. More formally GRISU_CACHE_NAME(i) contains the elements j*i
// with 0 <= j < k with k such that j*k < the size of GRISU_CACHE_NAME(1).
// The higher 'i' is the fewer elements we use.
// Given that there are less elements, the exponent-distance between two
// elements in the cache grows. The variable GRISU_CACHE_MAX_DISTANCE(i) stores
// the maximum distance between two elements.
#define GRISU_CACHE_STRUCT CachedPower
#define GRISU_CACHE_NAME(i) kCachedPowers##i
#define GRISU_CACHE_MAX_DISTANCE(i) kCachedPowersMaxDistance##i
#define GRISU_CACHE_OFFSET kCachedPowerOffset
#define GRISU_UINT64_C V8_2PART_UINT64_C
// The following include imports the precompiled cached powers.
#include "powers-ten.h" // NOLINT
static const double kD_1_LOG2_10 = 0.30102999566398114; // 1 / lg(10)
// We can't use a function since we reference variables depending on the 'i'.
// This way the compiler is able to see at compile time that only one
// cache-array variable is used and thus can remove all the others.
#define COMPUTE_FOR_CACHE(i) \
if (!found && (gamma - alpha + 1 >= GRISU_CACHE_MAX_DISTANCE(i))) { \
int kQ = DiyFp::kSignificandSize; \
double k = ceiling((alpha - e + kQ - 1) * kD_1_LOG2_10); \
int index = (GRISU_CACHE_OFFSET + static_cast<int>(k) - 1) / i + 1; \
cached_power = GRISU_CACHE_NAME(i)[index]; \
found = true; \
} \
static void GetCachedPower(int e, int alpha, int gamma, int* mk, DiyFp* c_mk) {
// The following if statement should be optimized by the compiler so that only
// one array is referenced and the others are not included in the object file.
bool found = false;
CachedPower cached_power;
COMPUTE_FOR_CACHE(20);
COMPUTE_FOR_CACHE(19);
COMPUTE_FOR_CACHE(18);
COMPUTE_FOR_CACHE(17);
COMPUTE_FOR_CACHE(16);
COMPUTE_FOR_CACHE(15);
COMPUTE_FOR_CACHE(14);
COMPUTE_FOR_CACHE(13);
COMPUTE_FOR_CACHE(12);
COMPUTE_FOR_CACHE(11);
COMPUTE_FOR_CACHE(10);
COMPUTE_FOR_CACHE(9);
COMPUTE_FOR_CACHE(8);
COMPUTE_FOR_CACHE(7);
COMPUTE_FOR_CACHE(6);
COMPUTE_FOR_CACHE(5);
COMPUTE_FOR_CACHE(4);
COMPUTE_FOR_CACHE(3);
COMPUTE_FOR_CACHE(2);
COMPUTE_FOR_CACHE(1);
if (!found) {
UNIMPLEMENTED();
// Silence compiler warnings.
cached_power.significand = 0;
cached_power.binary_exponent = 0;
cached_power.decimal_exponent = 0;
}
*c_mk = DiyFp(cached_power.significand, cached_power.binary_exponent);
*mk = cached_power.decimal_exponent;
ASSERT((alpha <= c_mk->e() + e) && (c_mk->e() + e <= gamma));
}
#undef GRISU_REDUCTION
#undef GRISU_CACHE_STRUCT
#undef GRISU_CACHE_NAME
#undef GRISU_CACHE_MAX_DISTANCE
#undef GRISU_CACHE_OFFSET
#undef GRISU_UINT64_C
void GetCachedPowerForBinaryExponentRange(int min_exponent,
int max_exponent,
DiyFp* power,
int* decimal_exponent);
} } // namespace v8::internal

43
deps/v8/src/codegen.cc

@ -206,10 +206,9 @@ Handle<Code> CodeGenerator::MakeCodeEpilogue(MacroAssembler* masm,
}
// Generate the code. Takes a function literal, generates code for it, assemble
// all the pieces into a Code object. This function is only to be called by
// the compiler.cc code.
Handle<Code> CodeGenerator::MakeCode(CompilationInfo* info) {
// Generate the code. Compile the AST and assemble all the pieces into a
// Code object.
bool CodeGenerator::MakeCode(CompilationInfo* info) {
Handle<Script> script = info->script();
if (!script->IsUndefined() && !script->source()->IsUndefined()) {
int len = String::cast(script->source())->length();
@ -224,12 +223,14 @@ Handle<Code> CodeGenerator::MakeCode(CompilationInfo* info) {
cgen.Generate(info);
if (cgen.HasStackOverflow()) {
ASSERT(!Top::has_pending_exception());
return Handle<Code>::null();
return false;
}
InLoopFlag in_loop = (cgen.loop_nesting() != 0) ? IN_LOOP : NOT_IN_LOOP;
InLoopFlag in_loop = info->is_in_loop() ? IN_LOOP : NOT_IN_LOOP;
Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, in_loop);
return MakeCodeEpilogue(cgen.masm(), flags, info);
Handle<Code> code = MakeCodeEpilogue(cgen.masm(), flags, info);
info->SetCode(code); // May be an empty handle.
return !code.is_null();
}
@ -325,9 +326,12 @@ void CodeGenerator::ProcessDeclarations(ZoneList<Declaration*>* declarations) {
}
} else {
Handle<SharedFunctionInfo> function =
Compiler::BuildFunctionInfo(node->fun(), script(), this);
Compiler::BuildFunctionInfo(node->fun(), script());
// Check for stack-overflow exception.
if (HasStackOverflow()) return;
if (function.is_null()) {
SetStackOverflow();
return;
}
array->set(j++, *function);
}
}
@ -357,24 +361,19 @@ const CodeGenerator::InlineFunctionGenerator
#undef INLINE_FUNCTION_GENERATOR_ADDRESS
CodeGenerator::InlineFunctionGenerator
CodeGenerator::FindInlineFunctionGenerator(Runtime::FunctionId id) {
return kInlineFunctionGenerators[
static_cast<int>(id) - static_cast<int>(Runtime::kFirstInlineFunction)];
}
bool CodeGenerator::CheckForInlineRuntimeCall(CallRuntime* node) {
ZoneList<Expression*>* args = node->arguments();
Handle<String> name = node->name();
Runtime::Function* function = node->function();
if (function != NULL && function->intrinsic_type == Runtime::INLINE) {
InlineFunctionGenerator generator =
FindInlineFunctionGenerator(function->function_id);
if (generator != NULL) {
((*this).*(generator))(args);
return true;
}
int lookup_index = static_cast<int>(function->function_id) -
static_cast<int>(Runtime::kFirstInlineFunction);
ASSERT(lookup_index >= 0);
ASSERT(static_cast<size_t>(lookup_index) <
ARRAY_SIZE(kInlineFunctionGenerators));
InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index];
(this->*generator)(args);
return true;
}
return false;
}

1
deps/v8/src/codegen.h

@ -62,7 +62,6 @@
// ComputeCallInitializeInLoop
// ProcessDeclarations
// DeclareGlobals
// FindInlineRuntimeLUT
// CheckForInlineRuntimeCall
// AnalyzeCondition
// CodeForFunctionPosition

442
deps/v8/src/compiler.cc

@ -45,6 +45,40 @@
namespace v8 {
namespace internal {
CompilationInfo::CompilationInfo(Handle<Script> script)
: flags_(0),
function_(NULL),
scope_(NULL),
script_(script),
extension_(NULL),
pre_parse_data_(NULL) {
}
CompilationInfo::CompilationInfo(Handle<SharedFunctionInfo> shared_info)
: flags_(IsLazy::encode(true)),
function_(NULL),
scope_(NULL),
shared_info_(shared_info),
script_(Handle<Script>(Script::cast(shared_info->script()))),
extension_(NULL),
pre_parse_data_(NULL) {
}
CompilationInfo::CompilationInfo(Handle<JSFunction> closure)
: flags_(IsLazy::encode(true)),
function_(NULL),
scope_(NULL),
closure_(closure),
shared_info_(Handle<SharedFunctionInfo>(closure->shared())),
script_(Handle<Script>(Script::cast(shared_info_->script()))),
extension_(NULL),
pre_parse_data_(NULL) {
}
// For normal operation the syntax checker is used to determine whether to
// use the full compiler for top level code or not. However if the flag
// --always-full-compiler is specified or debugging is active the full
@ -58,103 +92,74 @@ static bool AlwaysFullCompiler() {
}
static Handle<Code> MakeCode(Handle<Context> context, CompilationInfo* info) {
FunctionLiteral* function = info->function();
ASSERT(function != NULL);
// Rewrite the AST by introducing .result assignments where needed.
if (!Rewriter::Process(function)) {
// Signal a stack overflow by returning a null handle. The stack
// overflow exception will be thrown by the caller.
return Handle<Code>::null();
}
{
// Compute top scope and allocate variables. For lazy compilation
// the top scope only contains the single lazily compiled function,
// so this doesn't re-allocate variables repeatedly.
HistogramTimerScope timer(&Counters::variable_allocation);
Scope* top = info->scope();
while (top->outer_scope() != NULL) top = top->outer_scope();
top->AllocateVariables(context);
}
#ifdef DEBUG
if (Bootstrapper::IsActive() ?
FLAG_print_builtin_scopes :
FLAG_print_scopes) {
info->scope()->Print();
}
#endif
// Optimize the AST.
if (!Rewriter::Optimize(function)) {
// Signal a stack overflow by returning a null handle. The stack
// overflow exception will be thrown by the caller.
return Handle<Code>::null();
}
// Generate code and return it. Code generator selection is governed by
// which backends are enabled and whether the function is considered
// run-once code or not:
//
// --full-compiler enables the dedicated backend for code we expect to be
// run once
//
// The normal choice of backend can be overridden with the flags
// --always-full-compiler.
Handle<SharedFunctionInfo> shared = info->shared_info();
bool is_run_once = (shared.is_null())
? info->scope()->is_global_scope()
: (shared->is_toplevel() || shared->try_full_codegen());
bool use_full = FLAG_full_compiler && !function->contains_loops();
if (AlwaysFullCompiler() || (use_full && is_run_once)) {
return FullCodeGenerator::MakeCode(info);
static bool MakeCode(CompilationInfo* info) {
// Precondition: code has been parsed. Postcondition: the code field in
// the compilation info is set if compilation succeeded.
ASSERT(info->function() != NULL);
if (Rewriter::Rewrite(info) &&
Scope::Analyze(info) &&
Rewriter::Analyze(info)) {
// Generate code and return it. Code generator selection is governed by
// which backends are enabled and whether the function is considered
// run-once code or not.
//
// --full-compiler enables the dedicated backend for code we expect to
// be run once
//
// The normal choice of backend can be overridden with the flags
// --always-full-compiler.
Handle<SharedFunctionInfo> shared = info->shared_info();
bool is_run_once = (shared.is_null())
? info->scope()->is_global_scope()
: (shared->is_toplevel() || shared->try_full_codegen());
bool can_use_full =
FLAG_full_compiler && !info->function()->contains_loops();
if (AlwaysFullCompiler() || (is_run_once && can_use_full)) {
return FullCodeGenerator::MakeCode(info);
} else {
AssignedVariablesAnalyzer ava;
return ava.Analyze(info) && CodeGenerator::MakeCode(info);
}
}
AssignedVariablesAnalyzer ava(function);
if (!ava.Analyze()) return Handle<Code>::null();
return CodeGenerator::MakeCode(info);
return false;
}
#ifdef ENABLE_DEBUGGER_SUPPORT
Handle<Code> MakeCodeForLiveEdit(CompilationInfo* info) {
Handle<Context> context = Handle<Context>::null();
Handle<Code> code = MakeCode(context, info);
bool Compiler::MakeCodeForLiveEdit(CompilationInfo* info) {
// Precondition: code has been parsed. Postcondition: the code field in
// the compilation info is set if compilation succeeded.
bool succeeded = MakeCode(info);
if (!info->shared_info().is_null()) {
Handle<SerializedScopeInfo> scope_info =
SerializedScopeInfo::Create(info->scope());
info->shared_info()->set_scope_info(*scope_info);
}
return code;
return succeeded;
}
#endif
static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global,
bool is_eval,
Compiler::ValidationState validate,
Handle<Script> script,
Handle<Context> context,
v8::Extension* extension,
ScriptDataImpl* pre_data) {
static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info) {
CompilationZoneScope zone_scope(DELETE_ON_EXIT);
PostponeInterruptsScope postpone;
ASSERT(!i::Top::global_context().is_null());
Handle<Script> script = info->script();
script->set_context_data((*i::Top::global_context())->data());
bool is_json = (validate == Compiler::VALIDATE_JSON);
#ifdef ENABLE_DEBUGGER_SUPPORT
if (is_eval || is_json) {
Script::CompilationType compilation_type = is_json
if (info->is_eval() || info->is_json()) {
Script::CompilationType compilation_type = info->is_json()
? Script::COMPILATION_TYPE_JSON
: Script::COMPILATION_TYPE_EVAL;
script->set_compilation_type(Smi::FromInt(compilation_type));
// For eval scripts add information on the function from which eval was
// called.
if (is_eval) {
if (info->is_eval()) {
StackTraceFrameIterator it;
if (!it.done()) {
script->set_eval_from_shared(
@ -171,54 +176,47 @@ static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global,
#endif
// Only allow non-global compiles for eval.
ASSERT(is_eval || is_global);
// Build AST.
EagerCompilationInfo info(script, is_eval);
FunctionLiteral* lit =
Parser::MakeAST(is_global, script, extension, pre_data, is_json);
ASSERT(info->is_eval() || info->is_global());
// Check for parse errors.
if (lit == NULL) {
ASSERT(Top::has_pending_exception());
return Handle<SharedFunctionInfo>::null();
}
info.set_function(lit);
if (!Parser::Parse(info)) return Handle<SharedFunctionInfo>::null();
// Measure how long it takes to do the compilation; only take the
// rest of the function into account to avoid overlap with the
// parsing statistics.
HistogramTimer* rate = is_eval
HistogramTimer* rate = info->is_eval()
? &Counters::compile_eval
: &Counters::compile;
HistogramTimerScope timer(rate);
// Compile the code.
FunctionLiteral* lit = info->function();
LiveEditFunctionTracker live_edit_tracker(lit);
Handle<Code> code = MakeCode(context, &info);
// Check for stack-overflow exceptions.
if (code.is_null()) {
if (!MakeCode(info)) {
Top::StackOverflow();
return Handle<SharedFunctionInfo>::null();
}
ASSERT(!info->code().is_null());
if (script->name()->IsString()) {
PROFILE(CodeCreateEvent(
is_eval ? Logger::EVAL_TAG :
Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
*code, String::cast(script->name())));
info->is_eval()
? Logger::EVAL_TAG
: Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
*info->code(),
String::cast(script->name())));
OPROFILE(CreateNativeCodeRegion(String::cast(script->name()),
code->instruction_start(),
code->instruction_size()));
info->code()->instruction_start(),
info->code()->instruction_size()));
} else {
PROFILE(CodeCreateEvent(
is_eval ? Logger::EVAL_TAG :
Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
*code, ""));
OPROFILE(CreateNativeCodeRegion(is_eval ? "Eval" : "Script",
code->instruction_start(),
code->instruction_size()));
info->is_eval()
? Logger::EVAL_TAG
: Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
*info->code(),
""));
OPROFILE(CreateNativeCodeRegion(info->is_eval() ? "Eval" : "Script",
info->code()->instruction_start(),
info->code()->instruction_size()));
}
// Allocate function.
@ -226,8 +224,8 @@ static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global,
Factory::NewSharedFunctionInfo(
lit->name(),
lit->materialized_literal_count(),
code,
SerializedScopeInfo::Create(info.scope()));
info->code(),
SerializedScopeInfo::Create(info->scope()));
ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
Compiler::SetFunctionInfo(result, lit, true, script);
@ -303,13 +301,11 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
: *script_data);
// Compile the function and add it to the cache.
result = MakeFunctionInfo(true,
false,
DONT_VALIDATE_JSON,
script,
Handle<Context>::null(),
extension,
pre_data);
CompilationInfo info(script);
info.MarkAsGlobal();
info.SetExtension(extension);
info.SetPreParseData(pre_data);
result = MakeFunctionInfo(&info);
if (extension == NULL && !result.is_null()) {
CompilationCache::PutScript(source, result);
}
@ -329,9 +325,10 @@ Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
Handle<Context> context,
bool is_global,
ValidationState validate) {
// Note that if validation is required then no path through this
// function is allowed to return a value without validating that
// the input is legal json.
// Note that if validation is required then no path through this function
// is allowed to return a value without validating that the input is legal
// json.
bool is_json = (validate == VALIDATE_JSON);
int source_length = source->length();
Counters::total_eval_size.Increment(source_length);
@ -340,27 +337,27 @@ Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
// The VM is in the COMPILER state until exiting this function.
VMState state(COMPILER);
// Do a lookup in the compilation cache; if the entry is not there,
// invoke the compiler and add the result to the cache. If we're
// evaluating json we bypass the cache since we can't be sure a
// potential value in the cache has been validated.
// Do a lookup in the compilation cache; if the entry is not there, invoke
// the compiler and add the result to the cache. If we're evaluating json
// we bypass the cache since we can't be sure a potential value in the
// cache has been validated.
Handle<SharedFunctionInfo> result;
if (validate == DONT_VALIDATE_JSON)
if (!is_json) {
result = CompilationCache::LookupEval(source, context, is_global);
}
if (result.is_null()) {
// Create a script object describing the script to be compiled.
Handle<Script> script = Factory::NewScript(source);
result = MakeFunctionInfo(is_global,
true,
validate,
script,
context,
NULL,
NULL);
if (!result.is_null() && validate != VALIDATE_JSON) {
// For json it's unlikely that we'll ever see exactly the same
// string again so we don't use the compilation cache.
CompilationInfo info(script);
info.MarkAsEval();
if (is_global) info.MarkAsGlobal();
if (is_json) info.MarkAsJson();
info.SetCallingContext(context);
result = MakeFunctionInfo(&info);
if (!result.is_null() && !is_json) {
// For json it's unlikely that we'll ever see exactly the same string
// again so we don't use the compilation cache.
CompilationCache::PutEval(source, context, is_global, result);
}
}
@ -377,133 +374,122 @@ bool Compiler::CompileLazy(CompilationInfo* info) {
PostponeInterruptsScope postpone;
// Compute name, source code and script data.
Handle<SharedFunctionInfo> shared = info->shared_info();
int compiled_size = shared->end_position() - shared->start_position();
Counters::total_compile_size.Increment(compiled_size);
// Generate the AST for the lazily compiled function. The AST may be
// NULL in case of parser stack overflow.
FunctionLiteral* lit = Parser::MakeLazyAST(shared);
// Check for parse errors.
if (lit == NULL) {
ASSERT(Top::has_pending_exception());
return false;
}
info->set_function(lit);
// Measure how long it takes to do the lazy compilation; only take
// the rest of the function into account to avoid overlap with the
// lazy parsing statistics.
HistogramTimerScope timer(&Counters::compile_lazy);
// Generate the AST for the lazily compiled function.
if (Parser::Parse(info)) {
// Measure how long it takes to do the lazy compilation; only take the
// rest of the function into account to avoid overlap with the lazy
// parsing statistics.
HistogramTimerScope timer(&Counters::compile_lazy);
// Compile the code.
Handle<Code> code = MakeCode(Handle<Context>::null(), info);
// Check for stack-overflow exception.
if (code.is_null()) {
Top::StackOverflow();
return false;
}
// Compile the code.
if (!MakeCode(info)) {
Top::StackOverflow();
} else {
ASSERT(!info->code().is_null());
RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG,
Handle<String>(shared->DebugName()),
shared->start_position(),
info);
// Update the shared function info with the compiled code and the
// scope info. Please note, that the order of the sharedfunction
// initialization is important since SerializedScopeInfo::Create might
// trigger a GC, causing the ASSERT below to be invalid if the code
// was flushed. By setting the code object last we avoid this.
Handle<SerializedScopeInfo> scope_info =
SerializedScopeInfo::Create(info->scope());
shared->set_scope_info(*scope_info);
shared->set_code(*info->code());
if (!info->closure().is_null()) {
info->closure()->set_code(*info->code());
}
RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG,
Handle<String>(String::cast(shared->name())),
Handle<String>(shared->inferred_name()),
shared->start_position(),
info->script(),
code);
// Update the shared function info with the compiled code and the scope info.
// Please note, that the order of the sharedfunction initialization is
// important since SerializedScopeInfo::Create might trigger a GC, causing
// the ASSERT below to be invalid if the code was flushed. By setting the code
// object last we avoid this.
Handle<SerializedScopeInfo> scope_info =
SerializedScopeInfo::Create(info->scope());
shared->set_scope_info(*scope_info);
shared->set_code(*code);
if (!info->closure().is_null()) {
info->closure()->set_code(*code);
// Set the expected number of properties for instances.
FunctionLiteral* lit = info->function();
SetExpectedNofPropertiesFromEstimate(shared,
lit->expected_property_count());
// Set the optimization hints after performing lazy compilation, as
// these are not set when the function is set up as a lazily compiled
// function.
shared->SetThisPropertyAssignmentsInfo(
lit->has_only_simple_this_property_assignments(),
*lit->this_property_assignments());
// Check the function has compiled code.
ASSERT(shared->is_compiled());
shared->set_code_age(0);
ASSERT(!info->code().is_null());
return true;
}
}
// Set the expected number of properties for instances.
SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count());
// Set the optimication hints after performing lazy compilation, as these are
// not set when the function is set up as a lazily compiled function.
shared->SetThisPropertyAssignmentsInfo(
lit->has_only_simple_this_property_assignments(),
*lit->this_property_assignments());
// Check the function has compiled code.
ASSERT(shared->is_compiled());
shared->set_code_age(0);
return true;
ASSERT(info->code().is_null());
return false;
}
Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
Handle<Script> script,
AstVisitor* caller) {
LiveEditFunctionTracker live_edit_tracker(literal);
Handle<Script> script) {
#ifdef DEBUG
// We should not try to compile the same function literal more than
// once.
literal->mark_as_compiled();
#endif
// Determine if the function can be lazily compiled. This is
// necessary to allow some of our builtin JS files to be lazily
// compiled. These builtins cannot be handled lazily by the parser,
// since we have to know if a function uses the special natives
// syntax, which is something the parser records.
// Precondition: code has been parsed and scopes have been analyzed.
CompilationInfo info(script);
info.SetFunction(literal);
info.SetScope(literal->scope());
LiveEditFunctionTracker live_edit_tracker(literal);
// Determine if the function can be lazily compiled. This is necessary to
// allow some of our builtin JS files to be lazily compiled. These
// builtins cannot be handled lazily by the parser, since we have to know
// if a function uses the special natives syntax, which is something the
// parser records.
bool allow_lazy = literal->AllowsLazyCompilation() &&
!LiveEditFunctionTracker::IsActive();
Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
// Generate code
Handle<Code> code;
if (FLAG_lazy && allow_lazy) {
code = Handle<Code>(Builtins::builtin(Builtins::LazyCompile));
Handle<Code> code(Builtins::builtin(Builtins::LazyCompile));
info.SetCode(code);
} else {
// The bodies of function literals have not yet been visited by
// the AST optimizer/analyzer.
if (!Rewriter::Optimize(literal)) {
return Handle<SharedFunctionInfo>::null();
}
// Generate code and return it. The way that the compilation mode
// is controlled by the command-line flags is described in
// the static helper function MakeCode.
EagerCompilationInfo info(script, false);
info.set_function(literal);
//
// The bodies of function literals have not yet been visited by
// the AST analyzer.
if (!Rewriter::Analyze(&info)) return Handle<SharedFunctionInfo>::null();
bool is_run_once = literal->try_full_codegen();
bool use_full = FLAG_full_compiler && !literal->contains_loops();
if (AlwaysFullCompiler() || (use_full && is_run_once)) {
code = FullCodeGenerator::MakeCode(&info);
if (!FullCodeGenerator::MakeCode(&info)) {
return Handle<SharedFunctionInfo>::null();
}
} else {
// We fall back to the classic V8 code generator.
AssignedVariablesAnalyzer ava(literal);
if (!ava.Analyze()) return Handle<SharedFunctionInfo>::null();
code = CodeGenerator::MakeCode(&info);
}
// Check for stack-overflow exception.
if (code.is_null()) {
caller->SetStackOverflow();
return Handle<SharedFunctionInfo>::null();
AssignedVariablesAnalyzer ava;
if (!ava.Analyze(&info)) return Handle<SharedFunctionInfo>::null();
if (!CodeGenerator::MakeCode(&info)) {
return Handle<SharedFunctionInfo>::null();
}
}
// Function compilation complete.
RecordFunctionCompilation(Logger::FUNCTION_TAG,
literal->name(),
literal->inferred_name(),
literal->debug_name(),
literal->start_position(),
script,
code);
&info);
scope_info = SerializedScopeInfo::Create(info.scope());
}
@ -511,7 +497,7 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
Handle<SharedFunctionInfo> result =
Factory::NewSharedFunctionInfo(literal->name(),
literal->materialized_literal_count(),
code,
info.code(),
scope_info);
SetFunctionInfo(result, literal, false, script);
@ -551,32 +537,34 @@ void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag,
Handle<String> name,
Handle<String> inferred_name,
int start_position,
Handle<Script> script,
Handle<Code> code) {
// Log the code generation. If source information is available
// include script name and line number. Check explicitly whether
// logging is enabled as finding the line number is not free.
if (Logger::is_logging()
|| OProfileAgent::is_enabled()
|| CpuProfiler::is_profiling()) {
Handle<String> func_name(name->length() > 0 ? *name : *inferred_name);
CompilationInfo* info) {
// Log the code generation. If source information is available include
// script name and line number. Check explicitly whether logging is
// enabled as finding the line number is not free.
if (Logger::is_logging() ||
OProfileAgent::is_enabled() ||
CpuProfiler::is_profiling()) {
Handle<Script> script = info->script();
Handle<Code> code = info->code();
if (script->name()->IsString()) {
int line_num = GetScriptLineNumber(script, start_position) + 1;
USE(line_num);
PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
*code, *func_name,
String::cast(script->name()), line_num));
OPROFILE(CreateNativeCodeRegion(*func_name,
*code,
*name,
String::cast(script->name()),
line_num));
OPROFILE(CreateNativeCodeRegion(*name,
String::cast(script->name()),
line_num,
code->instruction_start(),
code->instruction_size()));
} else {
PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
*code, *func_name));
OPROFILE(CreateNativeCodeRegion(*func_name,
*code,
*name));
OPROFILE(CreateNativeCodeRegion(*name,
code->instruction_start(),
code->instruction_size()));
}

212
deps/v8/src/compiler.h

@ -1,4 +1,4 @@
// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@ -42,109 +42,101 @@ class ScriptDataImpl;
// is constructed based on the resources available at compile-time.
class CompilationInfo BASE_EMBEDDED {
public:
virtual ~CompilationInfo() {}
// Dispatched behavior.
virtual Handle<SharedFunctionInfo> shared_info() const = 0;
virtual Handle<Script> script() const {
return Handle<Script>(Script::cast(shared_info()->script()));
explicit CompilationInfo(Handle<Script> script);
explicit CompilationInfo(Handle<SharedFunctionInfo> shared_info);
explicit CompilationInfo(Handle<JSFunction> closure);
bool is_lazy() const { return (flags_ & IsLazy::mask()) != 0; }
bool is_eval() const { return (flags_ & IsEval::mask()) != 0; }
bool is_global() const { return (flags_ & IsGlobal::mask()) != 0; }
bool is_json() const { return (flags_ & IsJson::mask()) != 0; }
bool is_in_loop() const { return (flags_ & IsInLoop::mask()) != 0; }
FunctionLiteral* function() const { return function_; }
Scope* scope() const { return scope_; }
Handle<Code> code() const { return code_; }
Handle<JSFunction> closure() const { return closure_; }
Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
Handle<Script> script() const { return script_; }
v8::Extension* extension() const { return extension_; }
ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; }
Handle<Context> calling_context() const { return calling_context_; }
void MarkAsEval() {
ASSERT(!is_lazy());
flags_ |= IsEval::encode(true);
}
virtual Handle<JSFunction> closure() const {
return Handle<JSFunction>::null();
void MarkAsGlobal() {
ASSERT(!is_lazy());
flags_ |= IsGlobal::encode(true);
}
virtual bool is_eval() const { return false; }
virtual int loop_nesting() const { return 0; }
virtual bool has_global_object() const { return false; }
virtual GlobalObject* global_object() const { return NULL; }
// There should always be a function literal, but it may be set after
// construction (for lazy compilation).
FunctionLiteral* function() { return function_; }
void set_function(FunctionLiteral* literal) { function_ = literal; }
// Derived accessors.
Scope* scope() { return function()->scope(); }
protected:
CompilationInfo() : function_(NULL) {}
private:
FunctionLiteral* function_;
DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
};
class EagerCompilationInfo: public CompilationInfo {
public:
EagerCompilationInfo(Handle<Script> script, bool is_eval)
: script_(script), is_eval_(is_eval) {
ASSERT(!script.is_null());
void MarkAsJson() {
ASSERT(!is_lazy());
flags_ |= IsJson::encode(true);
}
// Overridden functions from the base class.
virtual Handle<SharedFunctionInfo> shared_info() const {
return Handle<SharedFunctionInfo>::null();
}
virtual Handle<Script> script() const { return script_; }
virtual bool is_eval() const { return is_eval_; }
private:
Handle<Script> script_;
bool is_eval_;
};
class LazySharedCompilationInfo: public CompilationInfo {
public:
explicit LazySharedCompilationInfo(Handle<SharedFunctionInfo> shared_info)
: shared_info_(shared_info) {
ASSERT(!shared_info.is_null());
void MarkAsInLoop() {
ASSERT(is_lazy());
flags_ |= IsInLoop::encode(true);
}
// Overridden functions from the base class.
virtual Handle<SharedFunctionInfo> shared_info() const {
return shared_info_;
void SetFunction(FunctionLiteral* literal) {
ASSERT(function_ == NULL);
function_ = literal;
}
private:
Handle<SharedFunctionInfo> shared_info_;
};
class LazyFunctionCompilationInfo: public CompilationInfo {
public:
LazyFunctionCompilationInfo(Handle<JSFunction> closure,
int loop_nesting)
: closure_(closure), loop_nesting_(loop_nesting) {
ASSERT(!closure.is_null());
void SetScope(Scope* scope) {
ASSERT(scope_ == NULL);
scope_ = scope;
}
// Overridden functions from the base class.
virtual Handle<SharedFunctionInfo> shared_info() const {
return Handle<SharedFunctionInfo>(closure_->shared());
void SetCode(Handle<Code> code) { code_ = code; }
void SetExtension(v8::Extension* extension) {
ASSERT(!is_lazy());
extension_ = extension;
}
virtual int loop_nesting() const { return loop_nesting_; }
virtual bool has_global_object() const {
return closure_->context()->global() != NULL;
void SetPreParseData(ScriptDataImpl* pre_parse_data) {
ASSERT(!is_lazy());
pre_parse_data_ = pre_parse_data;
}
virtual GlobalObject* global_object() const {
return closure_->context()->global();
void SetCallingContext(Handle<Context> context) {
ASSERT(is_eval());
calling_context_ = context;
}
private:
// Flags using template class BitField<type, start, length>. All are
// false by default.
//
// Compilation is either eager or lazy.
class IsLazy: public BitField<bool, 0, 1> {};
// Flags that can be set for eager compilation.
class IsEval: public BitField<bool, 1, 1> {};
class IsGlobal: public BitField<bool, 2, 1> {};
class IsJson: public BitField<bool, 3, 1> {};
// Flags that can be set for lazy compilation.
class IsInLoop: public BitField<bool, 4, 1> {};
unsigned flags_;
// Fields filled in by the compilation pipeline.
// AST filled in by the parser.
FunctionLiteral* function_;
// The scope of the function literal as a convenience. Set to indidicate
// that scopes have been analyzed.
Scope* scope_;
// The compiled code.
Handle<Code> code_;
// Possible initial inputs to the compilation process.
Handle<JSFunction> closure_;
int loop_nesting_;
Handle<SharedFunctionInfo> shared_info_;
Handle<Script> script_;
// Fields possibly needed for eager compilation, NULL by default.
v8::Extension* extension_;
ScriptDataImpl* pre_parse_data_;
// The context of the caller is needed for eval code, and will be a null
// handle otherwise.
Handle<Context> calling_context_;
DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
};
@ -155,13 +147,13 @@ class LazyFunctionCompilationInfo: public CompilationInfo {
// functions, they will be compiled and allocated as part of the compilation
// of the source code.
// Please note this interface returns shared function infos.
// This means you need to call Factory::NewFunctionFromSharedFunctionInfo
// before you have a real function with a context.
// Please note this interface returns shared function infos. This means you
// need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
// real function with a context.
class Compiler : public AllStatic {
public:
enum ValidationState { VALIDATE_JSON, DONT_VALIDATE_JSON };
enum ValidationState { DONT_VALIDATE_JSON, VALIDATE_JSON };
// All routines return a JSFunction.
// If an error occurs an exception is raised and
@ -183,17 +175,14 @@ class Compiler : public AllStatic {
bool is_global,
ValidationState validation);
// Compile from function info (used for lazy compilation). Returns
// true on success and false if the compilation resulted in a stack
// overflow.
// Compile from function info (used for lazy compilation). Returns true on
// success and false if the compilation resulted in a stack overflow.
static bool CompileLazy(CompilationInfo* info);
// Compile a shared function info object (the function is possibly
// lazily compiled). Called recursively from a backend code
// generator 'caller' to build the shared function info.
// Compile a shared function info object (the function is possibly lazily
// compiled).
static Handle<SharedFunctionInfo> BuildFunctionInfo(FunctionLiteral* node,
Handle<Script> script,
AstVisitor* caller);
Handle<Script> script);
// Set the function info for a newly compiled function.
static void SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
@ -201,23 +190,18 @@ class Compiler : public AllStatic {
bool is_toplevel,
Handle<Script> script);
#ifdef ENABLE_DEBUGGER_SUPPORT
static bool MakeCodeForLiveEdit(CompilationInfo* info);
#endif
private:
static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
Handle<String> name,
Handle<String> inferred_name,
int start_position,
Handle<Script> script,
Handle<Code> code);
CompilationInfo* info);
};
#ifdef ENABLE_DEBUGGER_SUPPORT
Handle<Code> MakeCodeForLiveEdit(CompilationInfo* info);
#endif
// During compilation we need a global list of handles to constants
// for frame elements. When the zone gets deleted, we make sure to
// clear this list of handles as well.

68
deps/v8/src/conversions.cc

@ -34,6 +34,7 @@
#include "dtoa.h"
#include "factory.h"
#include "scanner.h"
#include "strtod.h"
namespace v8 {
namespace internal {
@ -103,8 +104,6 @@ static bool SubStringEquals(Iterator* current,
}
extern "C" double gay_strtod(const char* s00, const char** se);
// Maximum number of significant digits in decimal representation.
// The longest possible double in decimal representation is
// (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074
@ -353,8 +352,9 @@ static double InternalStringToInt(Iterator current, EndMark end, int radix) {
}
ASSERT(buffer_pos < kBufferSize);
buffer[buffer_pos++] = '\0';
return sign ? -gay_strtod(buffer, NULL) : gay_strtod(buffer, NULL);
buffer[buffer_pos] = '\0';
Vector<const char> buffer_vector(buffer, buffer_pos);
return sign ? -Strtod(buffer_vector, 0) : Strtod(buffer_vector, 0);
}
// The following code causes accumulating rounding error for numbers greater
@ -462,7 +462,6 @@ static double InternalStringToDouble(Iterator current,
++current;
if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE;
} else if (*current == '-') {
buffer[buffer_pos++] = '-';
++current;
if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE;
sign = true;
@ -478,8 +477,8 @@ static double InternalStringToDouble(Iterator current,
return JUNK_STRING_VALUE;
}
ASSERT(buffer_pos == 0 || buffer[0] == '-');
return buffer_pos > 0 ? -V8_INFINITY : V8_INFINITY;
ASSERT(buffer_pos == 0);
return sign ? -V8_INFINITY : V8_INFINITY;
}
bool leading_zero = false;
@ -496,7 +495,6 @@ static double InternalStringToDouble(Iterator current,
return JUNK_STRING_VALUE; // "0x".
}
bool sign = (buffer_pos > 0 && buffer[0] == '-');
return InternalStringToIntDouble<4>(current,
end,
sign,
@ -533,6 +531,9 @@ static double InternalStringToDouble(Iterator current,
}
if (*current == '.') {
if (octal && !allow_trailing_junk) return JUNK_STRING_VALUE;
if (octal) goto parsing_done;
++current;
if (current == end) {
if (significant_digits == 0 && !leading_zero) {
@ -553,16 +554,16 @@ static double InternalStringToDouble(Iterator current,
}
}
ASSERT(buffer_pos < kBufferSize);
buffer[buffer_pos++] = '.';
// We don't emit a '.', but adjust the exponent instead.
fractional_part = true;
// There is the fractional part.
// There is a fractional part.
while (*current >= '0' && *current <= '9') {
if (significant_digits < kMaxSignificantDigits) {
ASSERT(buffer_pos < kBufferSize);
buffer[buffer_pos++] = static_cast<char>(*current);
significant_digits++;
exponent--;
} else {
// Ignore insignificant digits in the fractional part.
nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
@ -638,60 +639,25 @@ static double InternalStringToDouble(Iterator current,
exponent += insignificant_digits;
if (octal) {
bool sign = buffer[0] == '-';
int start_pos = (sign ? 1 : 0);
return InternalStringToIntDouble<3>(buffer + start_pos,
return InternalStringToIntDouble<3>(buffer,
buffer + buffer_pos,
sign,
allow_trailing_junk);
}
if (nonzero_digit_dropped) {
if (insignificant_digits) buffer[buffer_pos++] = '.';
buffer[buffer_pos++] = '1';
}
// If the number has no more than kMaxDigitsInInt digits and doesn't have
// fractional part it could be parsed faster (without checks for
// spaces, overflow, etc.).
const int kMaxDigitsInInt = 9 * sizeof(int) / 4; // NOLINT
if (exponent != 0) {
ASSERT(buffer_pos < kBufferSize);
buffer[buffer_pos++] = 'e';
if (exponent < 0) {
ASSERT(buffer_pos < kBufferSize);
buffer[buffer_pos++] = '-';
exponent = -exponent;
}
if (exponent > 999) exponent = 999; // Result will be Infinity or 0 or -0.
const int exp_digits = 3;
for (int i = 0; i < exp_digits; i++) {
buffer[buffer_pos + exp_digits - 1 - i] = '0' + exponent % 10;
exponent /= 10;
}
ASSERT(exponent == 0);
buffer_pos += exp_digits;
} else if (!fractional_part && significant_digits <= kMaxDigitsInInt) {
if (significant_digits == 0) return SignedZero(sign);
ASSERT(buffer_pos > 0);
int num = 0;
int start_pos = (buffer[0] == '-' ? 1 : 0);
for (int i = start_pos; i < buffer_pos; i++) {
ASSERT(buffer[i] >= '0' && buffer[i] <= '9');
num = 10 * num + (buffer[i] - '0');
}
return static_cast<double>(start_pos == 0 ? num : -num);
exponent--;
}
ASSERT(buffer_pos < kBufferSize);
buffer[buffer_pos] = '\0';
return gay_strtod(buffer, NULL);
double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
return sign? -converted: converted;
}
double StringToDouble(String* str, int flags, double empty_string_val) {
StringShape shape(str);
if (shape.IsSequentialAscii()) {

9
deps/v8/src/data-flow.cc

@ -50,12 +50,13 @@ void BitVector::Print() {
#endif
bool AssignedVariablesAnalyzer::Analyze() {
Scope* scope = fun_->scope();
bool AssignedVariablesAnalyzer::Analyze(CompilationInfo* info) {
info_ = info;
Scope* scope = info->scope();
int variables = scope->num_parameters() + scope->num_stack_slots();
if (variables == 0) return true;
av_.ExpandTo(variables);
VisitStatements(fun_->body());
VisitStatements(info->function()->body());
return !HasStackOverflow();
}
@ -129,7 +130,7 @@ int AssignedVariablesAnalyzer::BitIndex(Variable* var) {
if (slot->type() == Slot::PARAMETER) {
return slot->index();
} else {
return fun_->scope()->num_parameters() + slot->index();
return info_->scope()->num_parameters() + slot->index();
}
}

6
deps/v8/src/data-flow.h

@ -198,8 +198,8 @@ class WorkList BASE_EMBEDDED {
// is guaranteed to be a smi.
class AssignedVariablesAnalyzer : public AstVisitor {
public:
explicit AssignedVariablesAnalyzer(FunctionLiteral* fun) : fun_(fun) { }
bool Analyze();
explicit AssignedVariablesAnalyzer() : info_(NULL) { }
bool Analyze(CompilationInfo* info);
private:
Variable* FindSmiLoopVariable(ForStatement* stmt);
@ -219,7 +219,7 @@ class AssignedVariablesAnalyzer : public AstVisitor {
AST_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT
FunctionLiteral* fun_;
CompilationInfo* info_;
// Accumulator for assigned variables set.
BitVector av_;

13
deps/v8/src/execution.cc

@ -473,6 +473,19 @@ Handle<Object> Execution::NewDate(double time, bool* exc) {
#undef RETURN_NATIVE_CALL
Handle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
Handle<String> flags,
bool* exc) {
Handle<Object> re_obj = RegExpImpl::CreateRegExpLiteral(
Handle<JSFunction>(Top::global_context()->regexp_function()),
pattern,
flags,
exc);
if (*exc) return Handle<JSRegExp>();
return Handle<JSRegExp>::cast(re_obj);
}
Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) {
int int_index = static_cast<int>(index);
if (int_index < 0 || int_index >= string->length()) {

5
deps/v8/src/execution.h

@ -105,6 +105,11 @@ class Execution : public AllStatic {
// Create a new date object from 'time'.
static Handle<Object> NewDate(double time, bool* exc);
// Create a new regular expression object from 'pattern' and 'flags'.
static Handle<JSRegExp> NewJSRegExp(Handle<String> pattern,
Handle<String> flags,
bool* exc);
// Used to implement [] notation on strings (calls JS code)
static Handle<Object> CharAt(Handle<String> str, uint32_t index);

18
deps/v8/src/fast-dtoa.cc

@ -609,8 +609,13 @@ static bool Grisu3(double v,
ASSERT(boundary_plus.e() == w.e());
DiyFp ten_mk; // Cached power of ten: 10^-k
int mk; // -k
GetCachedPower(w.e() + DiyFp::kSignificandSize, kMinimalTargetExponent,
kMaximalTargetExponent, &mk, &ten_mk);
int ten_mk_minimal_binary_exponent =
kMinimalTargetExponent - (w.e() + DiyFp::kSignificandSize);
int ten_mk_maximal_binary_exponent =
kMaximalTargetExponent - (w.e() + DiyFp::kSignificandSize);
GetCachedPowerForBinaryExponentRange(ten_mk_minimal_binary_exponent,
ten_mk_maximal_binary_exponent,
&ten_mk, &mk);
ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() +
DiyFp::kSignificandSize) &&
(kMaximalTargetExponent >= w.e() + ten_mk.e() +
@ -662,8 +667,13 @@ static bool Grisu3Counted(double v,
DiyFp w = Double(v).AsNormalizedDiyFp();
DiyFp ten_mk; // Cached power of ten: 10^-k
int mk; // -k
GetCachedPower(w.e() + DiyFp::kSignificandSize, kMinimalTargetExponent,
kMaximalTargetExponent, &mk, &ten_mk);
int ten_mk_minimal_binary_exponent =
kMinimalTargetExponent - (w.e() + DiyFp::kSignificandSize);
int ten_mk_maximal_binary_exponent =
kMaximalTargetExponent - (w.e() + DiyFp::kSignificandSize);
GetCachedPowerForBinaryExponentRange(ten_mk_minimal_binary_exponent,
ten_mk_maximal_binary_exponent,
&ten_mk, &mk);
ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() +
DiyFp::kSignificandSize) &&
(kMaximalTargetExponent >= w.e() + ten_mk.e() +

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

@ -277,7 +277,7 @@ void BreakableStatementChecker::VisitThisFunction(ThisFunction* expr) {
#define __ ACCESS_MASM(masm())
Handle<Code> FullCodeGenerator::MakeCode(CompilationInfo* info) {
bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
Handle<Script> script = info->script();
if (!script->IsUndefined() && !script->source()->IsUndefined()) {
int len = String::cast(script->source())->length();
@ -291,10 +291,13 @@ Handle<Code> FullCodeGenerator::MakeCode(CompilationInfo* info) {
cgen.Generate(info);
if (cgen.HasStackOverflow()) {
ASSERT(!Top::has_pending_exception());
return Handle<Code>::null();
return false;
}
Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, NOT_IN_LOOP);
return CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
Handle<Code> code = CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
info->SetCode(code); // may be an empty handle.
return !code.is_null();
}
@ -462,9 +465,12 @@ void FullCodeGenerator::VisitDeclarations(
}
} else {
Handle<SharedFunctionInfo> function =
Compiler::BuildFunctionInfo(decl->fun(), script(), this);
Compiler::BuildFunctionInfo(decl->fun(), script());
// Check for stack-overflow exception.
if (HasStackOverflow()) return;
if (function.is_null()) {
SetStackOverflow();
return;
}
array->set(j++, *function);
}
}
@ -1122,9 +1128,14 @@ void FullCodeGenerator::VisitConditional(Conditional* expr) {
__ bind(&true_case);
SetExpressionPosition(expr->then_expression(),
expr->then_expression_position());
Visit(expr->then_expression());
// If control flow falls through Visit, jump to done.
if (!context()->IsTest()) {
if (context()->IsTest()) {
const TestContext* for_test = TestContext::cast(context());
VisitForControl(expr->then_expression(),
for_test->true_label(),
for_test->false_label(),
NULL);
} else {
Visit(expr->then_expression());
__ jmp(&done);
}
@ -1156,8 +1167,11 @@ void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
// Build the function boilerplate and instantiate it.
Handle<SharedFunctionInfo> function_info =
Compiler::BuildFunctionInfo(expr, script(), this);
if (HasStackOverflow()) return;
Compiler::BuildFunctionInfo(expr, script());
if (function_info.is_null()) {
SetStackOverflow();
return;
}
EmitNewClosure(function_info);
}

11
deps/v8/src/full-codegen.h

@ -74,7 +74,7 @@ class FullCodeGenerator: public AstVisitor {
context_(NULL) {
}
static Handle<Code> MakeCode(CompilationInfo* info);
static bool MakeCode(CompilationInfo* info);
void Generate(CompilationInfo* info);
@ -604,6 +604,15 @@ class FullCodeGenerator: public AstVisitor {
false_label_(false_label),
fall_through_(fall_through) { }
static const TestContext* cast(const ExpressionContext* context) {
ASSERT(context->IsTest());
return reinterpret_cast<const TestContext*>(context);
}
Label* true_label() const { return true_label_; }
Label* false_label() const { return false_label_; }
Label* fall_through() const { return fall_through_; }
virtual void Plug(bool flag) const;
virtual void Plug(Register reg) const;
virtual void Plug(Label* materialize_true, Label* materialize_false) const;

26
deps/v8/src/handles.cc

@ -635,8 +635,19 @@ v8::Handle<v8::Array> GetKeysForIndexedInterceptor(Handle<JSObject> receiver,
}
static bool ContainsOnlyValidKeys(Handle<FixedArray> array) {
int len = array->length();
for (int i = 0; i < len; i++) {
Object* e = array->get(i);
if (!(e->IsString() || e->IsNumber())) return false;
}
return true;
}
Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object,
KeyCollectionType type) {
USE(ContainsOnlyValidKeys);
Handle<FixedArray> content = Factory::empty_fixed_array();
Handle<JSObject> arguments_boilerplate =
Handle<JSObject>(
@ -664,6 +675,7 @@ Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object,
Factory::NewFixedArray(current->NumberOfEnumElements());
current->GetEnumElementKeys(*element_keys);
content = UnionOfKeys(content, element_keys);
ASSERT(ContainsOnlyValidKeys(content));
// Add the element keys from the interceptor.
if (current->HasIndexedInterceptor()) {
@ -671,6 +683,7 @@ Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object,
GetKeysForIndexedInterceptor(object, current);
if (!result.IsEmpty())
content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result));
ASSERT(ContainsOnlyValidKeys(content));
}
// We can cache the computed property keys if access checks are
@ -692,6 +705,7 @@ Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object,
// Compute the property keys and cache them if possible.
content =
UnionOfKeys(content, GetEnumPropertyKeys(current, cache_enum_keys));
ASSERT(ContainsOnlyValidKeys(content));
// Add the property keys from the interceptor.
if (current->HasNamedInterceptor()) {
@ -699,6 +713,7 @@ Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object,
GetKeysForNamedInterceptor(object, current);
if (!result.IsEmpty())
content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result));
ASSERT(ContainsOnlyValidKeys(content));
}
// If we only want local properties we bail out after the first
@ -779,7 +794,7 @@ static bool CompileLazyHelper(CompilationInfo* info,
bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
ClearExceptionFlag flag) {
LazySharedCompilationInfo info(shared);
CompilationInfo info(shared);
return CompileLazyHelper(&info, flag);
}
@ -788,11 +803,13 @@ bool CompileLazy(Handle<JSFunction> function,
ClearExceptionFlag flag) {
if (function->shared()->is_compiled()) {
function->set_code(function->shared()->code());
PROFILE(FunctionCreateEvent(*function));
function->shared()->set_code_age(0);
return true;
} else {
LazyFunctionCompilationInfo info(function, 0);
CompilationInfo info(function);
bool result = CompileLazyHelper(&info, flag);
ASSERT(!result || function->is_compiled());
PROFILE(FunctionCreateEvent(*function));
return result;
}
@ -803,11 +820,14 @@ bool CompileLazyInLoop(Handle<JSFunction> function,
ClearExceptionFlag flag) {
if (function->shared()->is_compiled()) {
function->set_code(function->shared()->code());
PROFILE(FunctionCreateEvent(*function));
function->shared()->set_code_age(0);
return true;
} else {
LazyFunctionCompilationInfo info(function, 1);
CompilationInfo info(function);
info.MarkAsInLoop();
bool result = CompileLazyHelper(&info, flag);
ASSERT(!result || function->is_compiled());
PROFILE(FunctionCreateEvent(*function));
return result;
}

31
deps/v8/src/ia32/codegen-ia32.cc

@ -179,20 +179,11 @@ void CodeGenerator::Generate(CompilationInfo* info) {
// Adjust for function-level loop nesting.
ASSERT_EQ(0, loop_nesting_);
loop_nesting_ = info->loop_nesting();
loop_nesting_ = info->is_in_loop() ? 1 : 0;
JumpTarget::set_compiling_deferred_code(false);
#ifdef DEBUG
if (strlen(FLAG_stop_at) > 0 &&
info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
frame_->SpillAll();
__ int3();
}
#endif
// New scope to get automatic timing calculation.
{ HistogramTimerScope codegen_timer(&Counters::code_generation);
{
CodeGenState state(this);
// Entry:
@ -203,6 +194,14 @@ void CodeGenerator::Generate(CompilationInfo* info) {
// esi: callee's context
allocator_->Initialize();
#ifdef DEBUG
if (strlen(FLAG_stop_at) > 0 &&
info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
frame_->SpillAll();
__ int3();
}
#endif
frame_->Enter();
// Allocate space for locals and initialize them.
@ -358,7 +357,7 @@ void CodeGenerator::Generate(CompilationInfo* info) {
}
// Adjust for function-level loop nesting.
ASSERT_EQ(loop_nesting_, info->loop_nesting());
ASSERT_EQ(loop_nesting_, info->is_in_loop() ? 1 : 0);
loop_nesting_ = 0;
// Code generation state must be reset.
@ -369,7 +368,6 @@ void CodeGenerator::Generate(CompilationInfo* info) {
// Process any deferred code using the register allocator.
if (!HasStackOverflow()) {
HistogramTimerScope deferred_timer(&Counters::deferred_code_generation);
JumpTarget::set_compiling_deferred_code(true);
ProcessDeferred();
JumpTarget::set_compiling_deferred_code(false);
@ -4925,9 +4923,12 @@ void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
ASSERT(!in_safe_int32_mode());
// Build the function info and instantiate it.
Handle<SharedFunctionInfo> function_info =
Compiler::BuildFunctionInfo(node, script(), this);
Compiler::BuildFunctionInfo(node, script());
// Check for stack-overflow exception.
if (HasStackOverflow()) return;
if (function_info.is_null()) {
SetStackOverflow();
return;
}
Result result = InstantiateFunction(function_info);
frame()->Push(&result);
}

7
deps/v8/src/ia32/codegen-ia32.h

@ -300,9 +300,7 @@ enum ArgumentsAllocationMode {
class CodeGenerator: public AstVisitor {
public:
// Takes a function literal, generates code for it. This function should only
// be called by compiler.cc.
static Handle<Code> MakeCode(CompilationInfo* info);
static bool MakeCode(CompilationInfo* info);
// Printing of AST, etc. as requested by flags.
static void MakeCodePrologue(CompilationInfo* info);
@ -626,9 +624,6 @@ class CodeGenerator: public AstVisitor {
void CheckStack();
static InlineFunctionGenerator FindInlineFunctionGenerator(
Runtime::FunctionId function_id);
bool CheckForInlineRuntimeCall(CallRuntime* node);
void ProcessDeclarations(ZoneList<Declaration*>* declarations);

7
deps/v8/src/ia32/full-codegen-ia32.cc

@ -61,6 +61,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
SetFunctionPosition(function());
Comment cmnt(masm_, "[ function compiled by full code generator");
#ifdef DEBUG
if (strlen(FLAG_stop_at) > 0 &&
info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
__ int3();
}
#endif
__ push(ebp); // Caller's frame pointer.
__ mov(ebp, esp);
__ push(esi); // Callee's context.

3
deps/v8/src/liveedit-debugger.js

@ -47,7 +47,6 @@ Debug.LiveEdit = new function() {
// Forward declaration for minifier.
var FunctionStatus;
// Applies the change to the script.
// The change is in form of list of chunks encoded in a single array as
// a series of triplets (pos1_start, pos1_end, pos2_end)
@ -224,7 +223,7 @@ Debug.LiveEdit = new function() {
//
// All functions get compiled linked to script provided as parameter script.
// TODO(LiveEdit): consider not using actual scripts as script, because
// we have to manually erase all links right after compile.
// we have to manually erase all links right after compile.
function GatherCompileInfo(source, script) {
// Get function info, elements are partially sorted (it is a tree of
// nested functions serialized as parent followed by serialized children.

48
deps/v8/src/liveedit.cc

@ -398,46 +398,31 @@ Handle<JSArray> LiveEdit::CompareStringsLinewise(Handle<String> s1,
static void CompileScriptForTracker(Handle<Script> script) {
const bool is_eval = false;
const bool is_global = true;
// TODO(635): support extensions.
Extension* extension = NULL;
PostponeInterruptsScope postpone;
// Only allow non-global compiles for eval.
ASSERT(is_eval || is_global);
// Build AST.
ScriptDataImpl* pre_data = NULL;
EagerCompilationInfo info(script, is_eval);
FunctionLiteral* lit =
Parser::MakeAST(is_global, script, extension, pre_data);
// Check for parse errors.
if (lit == NULL) {
ASSERT(Top::has_pending_exception());
return;
}
info.set_function(lit);
// Compile the code.
LiveEditFunctionTracker tracker(lit);
Handle<Code> code = MakeCodeForLiveEdit(&info);
// Check for stack-overflow exceptions.
if (code.is_null()) {
Top::StackOverflow();
return;
CompilationInfo info(script);
info.MarkAsGlobal();
if (Parser::Parse(&info)) {
// Compile the code.
LiveEditFunctionTracker tracker(info.function());
if (Compiler::MakeCodeForLiveEdit(&info)) {
ASSERT(!info.code().is_null());
tracker.RecordRootFunctionInfo(info.code());
} else {
Top::StackOverflow();
}
}
tracker.RecordRootFunctionInfo(code);
}
// Unwraps JSValue object, returning its field "value"
static Handle<Object> UnwrapJSValue(Handle<JSValue> jsValue) {
return Handle<Object>(jsValue->value());
}
// Wraps any object into a OpaqueReference, that will hide the object
// from JavaScript.
static Handle<JSValue> WrapInJSValue(Object* object) {
@ -448,6 +433,7 @@ static Handle<JSValue> WrapInJSValue(Object* object) {
return result;
}
// Simple helper class that creates more or less typed structures over
// JSArray object. This is an adhoc method of passing structures from C++
// to JavaScript.
@ -468,6 +454,7 @@ class JSArrayBasedStruct {
Handle<JSArray> GetJSArray() {
return array_;
}
protected:
void SetField(int field_position, Handle<Object> value) {
SetElement(array_, field_position, value);
@ -482,6 +469,7 @@ class JSArrayBasedStruct {
Object* res = GetField(field_position);
return Smi::cast(res)->value();
}
private:
Handle<JSArray> array_;
};
@ -554,6 +542,7 @@ class FunctionInfoWrapper : public JSArrayBasedStruct<FunctionInfoWrapper> {
friend class JSArrayBasedStruct<FunctionInfoWrapper>;
};
// Wraps SharedFunctionInfo along with some of its fields for passing it
// back to JavaScript. SharedFunctionInfo object itself is additionally
// wrapped into BlindReference for sanitizing reasons.
@ -594,6 +583,7 @@ class SharedInfoWrapper : public JSArrayBasedStruct<SharedInfoWrapper> {
friend class JSArrayBasedStruct<SharedInfoWrapper>;
};
class FunctionInfoListener {
public:
FunctionInfoListener() {
@ -620,7 +610,6 @@ class FunctionInfoListener {
current_parent_index_ = info.GetParentIndex();
}
public:
// Saves only function code, because for a script function we
// may never create a SharedFunctionInfo object.
void FunctionCode(Handle<Code> function_code) {
@ -708,6 +697,7 @@ class FunctionInfoListener {
int current_parent_index_;
};
static FunctionInfoListener* active_function_info_listener = NULL;
JSArray* LiveEdit::GatherCompileInfo(Handle<Script> script,

4
deps/v8/src/mips/simulator-mips.cc

@ -39,7 +39,7 @@
namespace v8i = v8::internal;
#if !defined(__mips)
#if !defined(__mips) || defined(USE_SIMULATOR)
// Only build the simulator if not compiling for real MIPS hardware.
namespace assembler {
@ -1645,6 +1645,6 @@ uintptr_t Simulator::PopAddress() {
} } // namespace assembler::mips
#endif // __mips
#endif // !__mips || USE_SIMULATOR
#endif // V8_TARGET_ARCH_MIPS

6
deps/v8/src/mips/simulator-mips.h

@ -38,7 +38,7 @@
#include "allocation.h"
#if defined(__mips)
#if defined(__mips) && !defined(USE_SIMULATOR)
// When running without a simulator we call the entry directly.
#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
@ -79,7 +79,7 @@ class SimulatorStack : public v8::internal::AllStatic {
reinterpret_cast<TryCatch*>(try_catch_address)
#else // #if defined(__mips)
#else // #if !defined(__mips) || defined(USE_SIMULATOR)
// When running with the simulator transition into simulated execution at this
// point.
@ -305,7 +305,7 @@ class SimulatorStack : public v8::internal::AllStatic {
}
};
#endif // defined(__mips)
#endif // !defined(__mips) || defined(USE_SIMULATOR)
#endif // V8_MIPS_SIMULATOR_MIPS_H_

37
deps/v8/src/objects.cc

@ -1,4 +1,4 @@
// Copyright 2006-2009 the V8 project authors. All rights reserved.
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@ -1180,7 +1180,11 @@ String* JSObject::constructor_name() {
if (map()->constructor()->IsJSFunction()) {
JSFunction* constructor = JSFunction::cast(map()->constructor());
String* name = String::cast(constructor->shared()->name());
return name->length() > 0 ? name : constructor->shared()->inferred_name();
if (name->length() > 0) return name;
String* inferred_name = constructor->shared()->inferred_name();
if (inferred_name->length() > 0) return inferred_name;
Object* proto = GetPrototype();
if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name();
}
// If the constructor is not present, return "Object".
return Heap::Object_symbol();
@ -3601,9 +3605,17 @@ Object* FixedArray::AddKeysFromJSArray(JSArray* array) {
Object* FixedArray::UnionOfKeys(FixedArray* other) {
int len0 = length();
#ifdef DEBUG
if (FLAG_enable_slow_asserts) {
for (int i = 0; i < len0; i++) {
ASSERT(get(i)->IsString() || get(i)->IsNumber());
}
}
#endif
int len1 = other->length();
// Optimize if either is empty.
if (len0 == 0) return other;
// Optimize if 'other' is empty.
// We cannot optimize if 'this' is empty, as other may have holes
// or non keys.
if (len1 == 0) return this;
// Compute how many elements are not in this.
@ -3623,14 +3635,18 @@ Object* FixedArray::UnionOfKeys(FixedArray* other) {
FixedArray* result = FixedArray::cast(obj);
WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
for (int i = 0; i < len0; i++) {
result->set(i, get(i), mode);
Object* e = get(i);
ASSERT(e->IsString() || e->IsNumber());
result->set(i, e, mode);
}
// Fill in the extra keys.
int index = 0;
for (int y = 0; y < len1; y++) {
Object* value = other->get(y);
if (!value->IsTheHole() && !HasKey(this, value)) {
result->set(len0 + index, other->get(y), mode);
Object* e = other->get(y);
ASSERT(e->IsString() || e->IsNumber());
result->set(len0 + index, e, mode);
index++;
}
}
@ -5227,6 +5243,13 @@ Object* Oddball::Initialize(const char* to_string, Object* to_number) {
}
String* SharedFunctionInfo::DebugName() {
Object* n = name();
if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name();
return String::cast(n);
}
bool SharedFunctionInfo::HasSourceCode() {
return !script()->IsUndefined() &&
!reinterpret_cast<Script*>(script())->source()->IsUndefined();
@ -6454,7 +6477,7 @@ Object* JSObject::SetElementWithoutInterceptor(uint32_t index, Object* value) {
// When we set the is_extensible flag to false we always force
// the element into dictionary mode (and force them to stay there).
if (!map()->is_extensible()) {
Handle<Object> number(Heap::NumberFromUint32(index));
Handle<Object> number(Factory::NewNumberFromUint(index));
Handle<String> index_string(Factory::NumberToString(number));
Handle<Object> args[1] = { index_string };
return Top::Throw(*Factory::NewTypeError("object_not_extensible",

5
deps/v8/src/objects.h

@ -1,4 +1,4 @@
// Copyright 2006-2009 the V8 project authors. All rights reserved.
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@ -3621,6 +3621,9 @@ class SharedFunctionInfo: public HeapObject {
// properties.
DECL_ACCESSORS(inferred_name, String)
// The function's name if it is non-empty, otherwise the inferred name.
String* DebugName();
// Position of the 'function' token in the script source.
inline int function_token_position();
inline void set_function_token_position(int function_token_position);

67
deps/v8/src/parser.cc

@ -5344,43 +5344,42 @@ bool Parser::ParseRegExp(FlatStringReader* input,
}
FunctionLiteral* Parser::MakeAST(bool compile_in_global_context,
Handle<Script> script,
v8::Extension* extension,
ScriptDataImpl* pre_data,
bool is_json) {
bool allow_natives_syntax =
FLAG_allow_natives_syntax || Bootstrapper::IsActive();
AstBuildingParser parser(script, allow_natives_syntax, extension, pre_data);
if (pre_data != NULL && pre_data->has_error()) {
Scanner::Location loc = pre_data->MessageLocation();
const char* message = pre_data->BuildMessage();
Vector<const char*> args = pre_data->BuildArgs();
parser.ReportMessageAt(loc, message, args);
DeleteArray(message);
for (int i = 0; i < args.length(); i++) {
DeleteArray(args[i]);
}
DeleteArray(args.start());
return NULL;
}
Handle<String> source = Handle<String>(String::cast(script->source()));
FunctionLiteral* result;
if (is_json) {
ASSERT(compile_in_global_context);
result = parser.ParseJson(source);
bool Parser::Parse(CompilationInfo* info) {
ASSERT(info->function() == NULL);
FunctionLiteral* result = NULL;
Handle<Script> script = info->script();
if (info->is_lazy()) {
AstBuildingParser parser(script, true, NULL, NULL);
result = parser.ParseLazy(info->shared_info());
} else {
result = parser.ParseProgram(source, compile_in_global_context);
bool allow_natives_syntax =
FLAG_allow_natives_syntax || Bootstrapper::IsActive();
ScriptDataImpl* pre_data = info->pre_parse_data();
AstBuildingParser parser(script, allow_natives_syntax, info->extension(),
pre_data);
if (pre_data != NULL && pre_data->has_error()) {
Scanner::Location loc = pre_data->MessageLocation();
const char* message = pre_data->BuildMessage();
Vector<const char*> args = pre_data->BuildArgs();
parser.ReportMessageAt(loc, message, args);
DeleteArray(message);
for (int i = 0; i < args.length(); i++) {
DeleteArray(args[i]);
}
DeleteArray(args.start());
ASSERT(Top::has_pending_exception());
} else {
Handle<String> source = Handle<String>(String::cast(script->source()));
// JSON is always global.
ASSERT(!info->is_json() || info->is_global());
result = info->is_json()
? parser.ParseJson(source)
: parser.ParseProgram(source, info->is_global());
}
}
return result;
}
FunctionLiteral* Parser::MakeLazyAST(Handle<SharedFunctionInfo> info) {
Handle<Script> script(Script::cast(info->script()));
AstBuildingParser parser(script, true, NULL, NULL);
FunctionLiteral* result = parser.ParseLazy(info);
return result;
info->SetFunction(result);
return (result != NULL);
}
#undef NEW

16
deps/v8/src/parser.h

@ -35,6 +35,7 @@
namespace v8 {
namespace internal {
class CompilationInfo;
class FuncNameInferrer;
class ParserFactory;
class ParserLog;
@ -183,17 +184,10 @@ class Parser {
ParserFactory* factory, ParserLog* log, ScriptDataImpl* pre_data);
virtual ~Parser() { }
// Takes a script and and context information, and builds a
// FunctionLiteral AST node. Returns NULL and deallocates any allocated
// AST nodes if parsing failed.
static FunctionLiteral* MakeAST(bool compile_in_global_context,
Handle<Script> script,
v8::Extension* extension,
ScriptDataImpl* pre_data,
bool is_json = false);
// Support for doing lazy compilation.
static FunctionLiteral* MakeLazyAST(Handle<SharedFunctionInfo> info);
// Parses the source code represented by the compilation info and sets its
// function literal. Returns false (and deallocates any allocated AST
// nodes) if parsing failed.
static bool Parse(CompilationInfo* info);
// Generic preparser generating full preparse data.
static ScriptDataImpl* PreParse(Handle<String> source,

2461
deps/v8/src/powers-ten.h

File diff suppressed because it is too large

115
deps/v8/src/profile-generator.cc

@ -94,12 +94,18 @@ StringsStorage::StringsStorage()
}
static void DeleteIndexName(char** name_ptr) {
DeleteArray(*name_ptr);
}
StringsStorage::~StringsStorage() {
for (HashMap::Entry* p = names_.Start();
p != NULL;
p = names_.Next(p)) {
DeleteArray(reinterpret_cast<const char*>(p->value));
}
index_names_.Iterate(DeleteIndexName);
}
@ -120,6 +126,22 @@ const char* StringsStorage::GetName(String* name) {
}
const char* StringsStorage::GetName(int index) {
ASSERT(index >= 0);
if (index_names_.length() <= index) {
index_names_.AddBlock(
NULL, index - index_names_.length() + 1);
}
if (index_names_[index] == NULL) {
const int kMaximumNameLength = 32;
char* name = NewArray<char>(kMaximumNameLength);
OS::SNPrintF(Vector<char>(name, kMaximumNameLength), "%d", index);
index_names_[index] = name;
}
return index_names_[index];
}
const char* CodeEntry::kEmptyNamePrefix = "";
@ -485,11 +507,6 @@ CpuProfilesCollection::CpuProfilesCollection()
}
static void DeleteArgsCountName(char** name_ptr) {
DeleteArray(*name_ptr);
}
static void DeleteCodeEntry(CodeEntry** entry_ptr) {
delete *entry_ptr;
}
@ -508,7 +525,6 @@ CpuProfilesCollection::~CpuProfilesCollection() {
current_profiles_.Iterate(DeleteCpuProfile);
profiles_by_token_.Iterate(DeleteProfilesList);
code_entries_.Iterate(DeleteCodeEntry);
args_count_names_.Iterate(DeleteArgsCountName);
}
@ -706,22 +722,6 @@ CodeEntry* CpuProfilesCollection::NewCodeEntry(int security_token_id) {
}
const char* CpuProfilesCollection::GetName(int args_count) {
ASSERT(args_count >= 0);
if (args_count_names_.length() <= args_count) {
args_count_names_.AddBlock(
NULL, args_count - args_count_names_.length() + 1);
}
if (args_count_names_[args_count] == NULL) {
const int kMaximumNameLength = 32;
char* name = NewArray<char>(kMaximumNameLength);
OS::SNPrintF(Vector<char>(name, kMaximumNameLength), "%d", args_count);
args_count_names_[args_count] = name;
}
return args_count_names_[args_count];
}
void CpuProfilesCollection::AddPathToCurrentProfiles(
const Vector<CodeEntry*>& path) {
// As starting / stopping profiles is rare relatively to this
@ -1001,6 +1001,8 @@ const char* HeapEntry::TypeAsString() {
case kString: return "/string/";
case kCode: return "/code/";
case kArray: return "/array/";
case kRegExp: return "/regexp/";
case kHeapNumber: return "/number/";
default: return "???";
}
}
@ -1284,11 +1286,16 @@ HeapEntry* HeapSnapshot::AddEntry(HeapObject* object,
} else if (object->IsJSFunction()) {
JSFunction* func = JSFunction::cast(object);
SharedFunctionInfo* shared = func->shared();
String* name = String::cast(shared->name())->length() > 0 ?
String::cast(shared->name()) : shared->inferred_name();
return AddEntry(object,
HeapEntry::kClosure,
collection_->GetFunctionName(name),
collection_->GetName(String::cast(shared->name())),
children_count,
retainers_count);
} else if (object->IsJSRegExp()) {
JSRegExp* re = JSRegExp::cast(object);
return AddEntry(object,
HeapEntry::kRegExp,
collection_->GetName(re->Pattern()),
children_count,
retainers_count);
} else if (object->IsJSObject()) {
@ -1333,6 +1340,12 @@ HeapEntry* HeapSnapshot::AddEntry(HeapObject* object,
"",
children_count,
retainers_count);
} else if (object->IsHeapNumber()) {
return AddEntry(object,
HeapEntry::kHeapNumber,
"number",
children_count,
retainers_count);
}
// No interest in this object.
return NULL;
@ -1342,12 +1355,14 @@ HeapEntry* HeapSnapshot::AddEntry(HeapObject* object,
bool HeapSnapshot::WillAddEntry(HeapObject* object) {
return object == kInternalRootObject
|| object->IsJSFunction()
|| object->IsJSRegExp()
|| object->IsJSObject()
|| object->IsString()
|| object->IsCode()
|| object->IsSharedFunctionInfo()
|| object->IsScript()
|| object->IsFixedArray();
|| object->IsFixedArray()
|| object->IsHeapNumber();
}
@ -1904,13 +1919,21 @@ void HeapSnapshotGenerator::ExtractReferences(HeapObject* obj) {
ExtractClosureReferences(js_obj, entry);
ExtractPropertyReferences(js_obj, entry);
ExtractElementReferences(js_obj, entry);
ExtractInternalReferences(js_obj, entry);
SetPropertyReference(
obj, entry, Heap::prototype_symbol(), js_obj->map()->prototype());
obj, entry, Heap::Proto_symbol(), js_obj->GetPrototype());
if (obj->IsJSFunction()) {
JSFunction* js_fun = JSFunction::cast(obj);
if (js_fun->has_prototype()) {
SetPropertyReference(
obj, entry, Heap::prototype_symbol(), js_fun->prototype());
}
}
} else if (obj->IsString()) {
if (obj->IsConsString()) {
ConsString* cs = ConsString::cast(obj);
SetElementReference(obj, entry, 0, cs->first());
SetElementReference(obj, entry, 1, cs->second());
SetInternalReference(obj, entry, "1", cs->first());
SetInternalReference(obj, entry, "2", cs->second());
}
} else if (obj->IsCode() || obj->IsSharedFunctionInfo() || obj->IsScript()) {
IndexedReferencesExtractor refs_extractor(this, obj, entry);
@ -2005,6 +2028,16 @@ void HeapSnapshotGenerator::ExtractElementReferences(JSObject* js_obj,
}
void HeapSnapshotGenerator::ExtractInternalReferences(JSObject* js_obj,
HeapEntry* entry) {
int length = js_obj->GetInternalFieldCount();
for (int i = 0; i < length; ++i) {
Object* o = js_obj->GetInternalField(i);
SetInternalReference(js_obj, entry, i, o);
}
}
void HeapSnapshotGenerator::SetClosureReference(HeapObject* parent_obj,
HeapEntry* parent_entry,
String* reference_name,
@ -2049,13 +2082,31 @@ void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj,
}
void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj,
HeapEntry* parent_entry,
int index,
Object* child_obj) {
HeapEntry* child_entry = GetEntry(child_obj);
if (child_entry != NULL) {
filler_->SetNamedReference(HeapGraphEdge::kInternal,
parent_obj,
parent_entry,
collection_->GetName(index),
child_obj,
child_entry);
}
}
void HeapSnapshotGenerator::SetPropertyReference(HeapObject* parent_obj,
HeapEntry* parent_entry,
String* reference_name,
Object* child_obj) {
HeapEntry* child_entry = GetEntry(child_obj);
if (child_entry != NULL) {
filler_->SetNamedReference(HeapGraphEdge::kProperty,
HeapGraphEdge::Type type = reference_name->length() > 0 ?
HeapGraphEdge::kProperty : HeapGraphEdge::kInternal;
filler_->SetNamedReference(type,
parent_obj,
parent_entry,
collection_->GetName(reference_name),
@ -2351,7 +2402,9 @@ void HeapSnapshotJSONSerializer::SerializeNodes() {
"," JSON_S("string")
"," JSON_S("object")
"," JSON_S("code")
"," JSON_S("closure"))
"," JSON_S("closure")
"," JSON_S("regexp")
"," JSON_S("number"))
"," JSON_S("string")
"," JSON_S("number")
"," JSON_S("number")

19
deps/v8/src/profile-generator.h

@ -67,6 +67,7 @@ class StringsStorage {
~StringsStorage();
const char* GetName(String* name);
const char* GetName(int index);
inline const char* GetFunctionName(String* name);
inline const char* GetFunctionName(const char* name);
@ -78,6 +79,8 @@ class StringsStorage {
// Mapping of strings by String::Hash to const char* strings.
HashMap names_;
// Mapping from ints to char* strings.
List<char*> index_names_;
DISALLOW_COPY_AND_ASSIGN(StringsStorage);
};
@ -284,6 +287,9 @@ class CpuProfilesCollection {
const char* GetName(String* name) {
return function_and_resource_names_.GetName(name);
}
const char* GetName(int args_count) {
return function_and_resource_names_.GetName(args_count);
}
CpuProfile* GetProfile(int security_token_id, unsigned uid);
bool IsLastProfile(const char* title);
@ -302,7 +308,6 @@ class CpuProfilesCollection {
static const int kMaxSimultaneousProfiles = 100;
private:
const char* GetName(int args_count);
const char* GetFunctionName(String* name) {
return function_and_resource_names_.GetFunctionName(name);
}
@ -317,8 +322,6 @@ class CpuProfilesCollection {
}
StringsStorage function_and_resource_names_;
// Mapping from args_count (int) to char* strings.
List<char*> args_count_names_;
List<CodeEntry*> code_entries_;
List<List<CpuProfile*>* > profiles_by_token_;
// Mapping from profiles' uids to indexes in the second nested list
@ -502,7 +505,9 @@ class HeapEntry BASE_EMBEDDED {
kString = v8::HeapGraphNode::kString,
kObject = v8::HeapGraphNode::kObject,
kCode = v8::HeapGraphNode::kCode,
kClosure = v8::HeapGraphNode::kClosure
kClosure = v8::HeapGraphNode::kClosure,
kRegExp = v8::HeapGraphNode::kRegExp,
kHeapNumber = v8::HeapGraphNode::kHeapNumber
};
HeapEntry() { }
@ -824,6 +829,7 @@ class HeapSnapshotsCollection {
HeapSnapshot* GetSnapshot(unsigned uid);
const char* GetName(String* name) { return names_.GetName(name); }
const char* GetName(int index) { return names_.GetName(index); }
const char* GetFunctionName(String* name) {
return names_.GetFunctionName(name);
}
@ -948,6 +954,7 @@ class HeapSnapshotGenerator {
void ExtractClosureReferences(JSObject* js_obj, HeapEntry* entry);
void ExtractPropertyReferences(JSObject* js_obj, HeapEntry* entry);
void ExtractElementReferences(JSObject* js_obj, HeapEntry* entry);
void ExtractInternalReferences(JSObject* js_obj, HeapEntry* entry);
void SetClosureReference(HeapObject* parent_obj,
HeapEntry* parent,
String* reference_name,
@ -960,6 +967,10 @@ class HeapSnapshotGenerator {
HeapEntry* parent,
const char* reference_name,
Object* child);
void SetInternalReference(HeapObject* parent_obj,
HeapEntry* parent,
int index,
Object* child);
void SetPropertyReference(HeapObject* parent_obj,
HeapEntry* parent,
String* reference_name,

150
deps/v8/src/regexp.js

@ -126,11 +126,11 @@ function RegExpCache() {
this.regExp = 0;
this.subject = 0;
this.replaceString = 0;
this.lastIndex = 0; // Also used for splitLimit when type is "split"
this.answer = 0;
// answerSaved marks whether the contents of answer is valid for a cache
// hit in RegExpExec, StringMatch and StringSplit.
this.answerSaved = false;
this.splitLimit = 0; // Used only when type is "split".
}
@ -181,22 +181,30 @@ function RegExpExec(string) {
var cache = regExpCache;
var saveAnswer = false;
var lastIndex = this.lastIndex;
// Since cache.subject is always a string, a matching input can not
// cause visible side-effects when converted to a string, so we can omit
// the conversion required by the specification.
// Likewise, the regexp.lastIndex and regexp.global properties are value
// properties that are not configurable, so reading them can also not cause
// any side effects (converting lastIndex to a number can, though).
if (%_ObjectEquals(cache.type, 'exec') &&
%_ObjectEquals(cache.lastIndex, this.lastIndex) &&
%_ObjectEquals(0, lastIndex) &&
%_IsRegExpEquivalent(cache.regExp, this) &&
%_ObjectEquals(cache.subject, string)) {
if (cache.answerSaved) {
// If this regexp is not global, cache.lastIndex is zero, so we only get
// here if this.lastIndex is zero, and resulting this.lastIndex
// must be zero too, so no change is necessary.
if (this.global) this.lastIndex = lastMatchInfo[CAPTURE1];
// The regexp.lastIndex value must be 0 for non-global RegExps, and for
// global RegExps we only cache negative results, which gives a lastIndex
// of zero as well.
this.lastIndex = 0;
return %_RegExpCloneResult(cache.answer);
} else {
saveAnswer = true;
}
}
if (%_ArgumentsLength() == 0) {
if (%_ArgumentsLength() === 0) {
var regExpInput = LAST_INPUT(lastMatchInfo);
if (IS_UNDEFINED(regExpInput)) {
throw MakeError('no_input_to_regexp', [this]);
@ -209,41 +217,48 @@ function RegExpExec(string) {
} else {
s = ToString(string);
}
var lastIndex = this.lastIndex;
var i = this.global ? TO_INTEGER(lastIndex) : 0;
var global = this.global;
if (i < 0 || i > s.length) {
this.lastIndex = 0;
return null;
// Conversion is required by the ES5 specification (RegExp.prototype.exec
// algorithm, step 5) even if the value is discarded for non-global RegExps.
var i = TO_INTEGER(lastIndex);
if (global) {
if (i < 0 || i > s.length) {
this.lastIndex = 0;
return null;
}
} else {
i = 0;
}
%_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]);
// matchIndices is either null or the lastMatchInfo array.
var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo);
if (matchIndices == null) {
if (this.global) {
if (matchIndices === null) {
if (global) {
// Cache negative result only if initial lastIndex was zero.
this.lastIndex = 0;
if (lastIndex != 0) return matchIndices;
if (lastIndex !== 0) return matchIndices;
}
cache.lastIndex = lastIndex;
cache.regExp = this;
cache.subject = s;
cache.answer = matchIndices; // Null.
cache.subject = s; // Always a string.
cache.answer = null;
cache.answerSaved = true; // Safe since no cloning is needed.
cache.type = 'exec';
return matchIndices; // No match.
}
// Successful match.
lastMatchInfoOverride = null;
var result = BuildResultFromMatchInfo(matchIndices, s);
if (this.global) {
if (global) {
// Don't cache positive results for global regexps.
this.lastIndex = lastMatchInfo[CAPTURE1];
} else {
cache.regExp = this;
cache.subject = s;
cache.lastIndex = lastIndex;
if (saveAnswer) cache.answer = %_RegExpCloneResult(result);
cache.answerSaved = saveAnswer;
cache.type = 'exec';
@ -273,32 +288,49 @@ function RegExpTest(string) {
}
string = regExpInput;
}
var s;
if (IS_STRING(string)) {
s = string;
} else {
s = ToString(string);
}
var lastIndex = this.lastIndex;
var cache = regExpCache;
if (%_ObjectEquals(cache.type, 'test') &&
%_IsRegExpEquivalent(cache.regExp, this) &&
%_ObjectEquals(cache.subject, string) &&
%_ObjectEquals(cache.lastIndex, lastIndex)) {
// If this regexp is not global, cache.lastIndex is zero, so we only get
// here if this.lastIndex is zero, and resulting this.lastIndex
// must be zero too, so no change is necessary.
if (this.global) this.lastIndex = lastMatchInfo[CAPTURE1];
%_ObjectEquals(0, lastIndex)) {
// The regexp.lastIndex value must be 0 for non-global RegExps, and for
// global RegExps we only cache negative results, which gives a resulting
// lastIndex of zero as well.
if (global) this.lastIndex = 0;
return cache.answer;
}
var s;
if (IS_STRING(string)) {
s = string;
} else {
s = ToString(string);
}
var length = s.length;
// Conversion is required by the ES5 specification (RegExp.prototype.exec
// algorithm, step 5) even if the value is discarded for non-global RegExps.
var i = TO_INTEGER(lastIndex);
if (global) {
if (i < 0 || i > length) {
this.lastIndex = 0;
return false;
}
} else {
i = 0;
}
var global = this.global;
// Remove irrelevant preceeding '.*' in a test regexp. The expression
// checks whether this.source starts with '.*' and that the third
// char is not a '?'
if (%_StringCharCodeAt(this.source,0) == 46 && // '.'
%_StringCharCodeAt(this.source,1) == 42 && // '*'
%_StringCharCodeAt(this.source,2) != 63) { // '?'
if (%_StringCharCodeAt(this.source, 0) == 46 && // '.'
%_StringCharCodeAt(this.source, 1) == 42 && // '*'
%_StringCharCodeAt(this.source, 2) != 63) { // '?'
if (!%_ObjectEquals(regexp_key, this)) {
regexp_key = this;
regexp_val = new $RegExp(this.source.substring(2, this.source.length),
@ -309,33 +341,28 @@ function RegExpTest(string) {
if (!regexp_val.test(s)) return false;
}
var length = s.length;
var i = this.global ? TO_INTEGER(lastIndex) : 0;
cache.type = 'test';
cache.regExp = this;
cache.subject = s;
cache.lastIndex = i;
if (i < 0 || i > length) {
this.lastIndex = 0;
cache.answer = false;
return false;
}
%_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]);
// matchIndices is either null or the lastMatchInfo array.
var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo);
if (matchIndices == null) {
if (this.global) this.lastIndex = 0;
cache.answer = false;
return false;
var result = (matchIndices !== null);
if (result) {
lastMatchInfoOverride = null;
}
lastMatchInfoOverride = null;
if (this.global) this.lastIndex = lastMatchInfo[CAPTURE1];
cache.answer = true;
return true;
if (global) {
if (result) {
this.lastIndex = lastMatchInfo[CAPTURE1];
return true;
} else {
this.lastIndex = 0;
if (lastIndex !== 0) return false;
}
}
cache.type = 'test';
cache.regExp = this;
cache.subject = s;
cache.answer = result;
return result;
}
@ -345,12 +372,9 @@ function RegExpToString() {
// ecma_2/RegExp/properties-001.js.
var src = this.source ? this.source : '(?:)';
var result = '/' + src + '/';
if (this.global)
result += 'g';
if (this.ignoreCase)
result += 'i';
if (this.multiline)
result += 'm';
if (this.global) result += 'g';
if (this.ignoreCase) result += 'i';
if (this.multiline) result += 'm';
return result;
}

40
deps/v8/src/rewriter.cc

@ -1,4 +1,4 @@
// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@ -27,9 +27,11 @@
#include "v8.h"
#include "rewriter.h"
#include "ast.h"
#include "compiler.h"
#include "scopes.h"
#include "rewriter.h"
namespace v8 {
namespace internal {
@ -986,34 +988,40 @@ void Processor::VisitThisFunction(ThisFunction* node) {
}
bool Rewriter::Process(FunctionLiteral* function) {
HistogramTimerScope timer(&Counters::rewriting);
// Assumes code has been parsed and scopes hve been analyzed. Mutates the
// AST, so the AST should not continue to be used in the case of failure.
bool Rewriter::Rewrite(CompilationInfo* info) {
FunctionLiteral* function = info->function();
ASSERT(function != NULL);
Scope* scope = function->scope();
ASSERT(scope != NULL);
if (scope->is_function_scope()) return true;
ZoneList<Statement*>* body = function->body();
if (body->is_empty()) return true;
if (!body->is_empty()) {
VariableProxy* result = scope->NewTemporary(Factory::result_symbol());
Processor processor(result);
processor.Process(body);
if (processor.HasStackOverflow()) return false;
VariableProxy* result = scope->NewTemporary(Factory::result_symbol());
Processor processor(result);
processor.Process(body);
if (processor.HasStackOverflow()) return false;
if (processor.result_assigned()) body->Add(new ReturnStatement(result));
}
if (processor.result_assigned()) body->Add(new ReturnStatement(result));
return true;
}
bool Rewriter::Optimize(FunctionLiteral* function) {
ZoneList<Statement*>* body = function->body();
// Assumes code has been parsed and scopes have been analyzed. Mutates the
// AST, so the AST should not continue to be used in the case of failure.
bool Rewriter::Analyze(CompilationInfo* info) {
FunctionLiteral* function = info->function();
ASSERT(function != NULL && function->scope() != NULL);
ZoneList<Statement*>* body = function->body();
if (FLAG_optimize_ast && !body->is_empty()) {
HistogramTimerScope timer(&Counters::ast_optimization);
AstOptimizer optimizer;
optimizer.Optimize(body);
if (optimizer.HasStackOverflow()) {
return false;
}
if (optimizer.HasStackOverflow()) return false;
}
return true;
}

31
deps/v8/src/rewriter.h

@ -1,4 +1,4 @@
// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@ -31,21 +31,26 @@
namespace v8 {
namespace internal {
// Currently, the rewriter takes function literals (only top-level)
// and rewrites them to return the value of the last expression in
// them.
//
// The rewriter adds a (hidden) variable, called .result, to the
// activation, and tries to figure out where it needs to store into
// this variable. If the variable is ever used, we conclude by adding
// a return statement that returns the variable to the body of the
// given function.
class CompilationInfo;
class Rewriter {
public:
static bool Process(FunctionLiteral* function);
static bool Optimize(FunctionLiteral* function);
// Rewrite top-level code (ECMA 262 "programs") so as to conservatively
// include an assignment of the value of the last statement in the code to
// a compiler-generated temporary variable wherever needed.
//
// Assumes code has been parsed and scopes have been analyzed. Mutates the
// AST, so the AST should not continue to be used in the case of failure.
static bool Rewrite(CompilationInfo* info);
// Perform a suite of simple non-iterative analyses of the AST. Mark
// expressions that are likely smis, expressions without side effects,
// expressions whose value will be converted to Int32, and expressions in a
// context where +0 and -0 are treated the same.
//
// Assumes code has been parsed and scopes have been analyzed. Mutates the
// AST, so the AST should not continue to be used in the case of failure.
static bool Analyze(CompilationInfo* info);
};

26
deps/v8/src/scopes.cc

@ -1,4 +1,4 @@
// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@ -27,9 +27,12 @@
#include "v8.h"
#include "scopes.h"
#include "bootstrapper.h"
#include "compiler.h"
#include "prettyprinter.h"
#include "scopeinfo.h"
#include "scopes.h"
namespace v8 {
namespace internal {
@ -168,6 +171,25 @@ Scope::Scope(Scope* outer_scope, Type type)
}
bool Scope::Analyze(CompilationInfo* info) {
ASSERT(info->function() != NULL);
Scope* top = info->function()->scope();
while (top->outer_scope() != NULL) top = top->outer_scope();
top->AllocateVariables(info->calling_context());
#ifdef DEBUG
if (Bootstrapper::IsActive()
? FLAG_print_builtin_scopes
: FLAG_print_scopes) {
info->function()->scope()->Print();
}
#endif
info->SetScope(info->function()->scope());
return true; // Can not fail.
}
void Scope::Initialize(bool inside_with) {
// Add this scope as a new inner scope of the outer scope.
if (outer_scope_ != NULL) {

10
deps/v8/src/scopes.h

@ -1,4 +1,4 @@
// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@ -34,6 +34,9 @@
namespace v8 {
namespace internal {
class CompilationInfo;
// A hash map to support fast variable declaration and lookup.
class VariableMap: public HashMap {
public:
@ -96,6 +99,11 @@ class Scope: public ZoneObject {
virtual ~Scope() { }
// Compute top scope and allocate variables. For lazy compilation the top
// scope only contains the single lazily compiled function, so this
// doesn't re-allocate variables repeatedly.
static bool Analyze(CompilationInfo* info);
// The scope name is only used for printing/debugging.
void SetScopeName(Handle<String> scope_name) { scope_name_ = scope_name; }

5
deps/v8/src/string.js

@ -611,7 +611,7 @@ function StringSplit(separator, limit) {
if (%_ObjectEquals(cache.type, 'split') &&
%_IsRegExpEquivalent(cache.regExp, separator) &&
%_ObjectEquals(cache.subject, subject) &&
%_ObjectEquals(cache.lastIndex, limit)) {
%_ObjectEquals(cache.splitLimit, limit)) {
if (cache.answerSaved) {
return CloneDenseArray(cache.answer);
} else {
@ -622,8 +622,7 @@ function StringSplit(separator, limit) {
cache.type = 'split';
cache.regExp = separator;
cache.subject = subject;
// Reuse lastIndex field for split limit when type is "split".
cache.lastIndex = limit;
cache.splitLimit = limit;
%_Log('regexp', 'regexp-split,%0S,%1r', [subject, separator]);

181
deps/v8/src/strtod.cc

@ -0,0 +1,181 @@
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdarg.h>
#include <limits.h>
#include "v8.h"
#include "strtod.h"
// #include "cached-powers.h"
namespace v8 {
namespace internal {
// 2^53 = 9007199254740992.
// Any integer with at most 15 decimal digits will hence fit into a double
// (which has a 53bit significand) without loss of precision.
static const int kMaxExactDoubleIntegerDecimalDigits = 15;
// 2^64 = 18446744073709551616
// Any integer with at most 19 digits will hence fit into a 64bit datatype.
static const int kMaxUint64DecimalDigits = 19;
// Max double: 1.7976931348623157 x 10^308
// Min non-zero double: 4.9406564584124654 x 10^-324
// Any x >= 10^309 is interpreted as +infinity.
// Any x <= 10^-324 is interpreted as 0.
// Note that 2.5e-324 (despite being smaller than the min double) will be read
// as non-zero (equal to the min non-zero double).
static const int kMaxDecimalPower = 309;
static const int kMinDecimalPower = -324;
static const double exact_powers_of_ten[] = {
1.0, // 10^0
10.0,
100.0,
1000.0,
10000.0,
100000.0,
1000000.0,
10000000.0,
100000000.0,
1000000000.0,
10000000000.0, // 10^10
100000000000.0,
1000000000000.0,
10000000000000.0,
100000000000000.0,
1000000000000000.0,
10000000000000000.0,
100000000000000000.0,
1000000000000000000.0,
10000000000000000000.0,
100000000000000000000.0, // 10^20
1000000000000000000000.0,
// 10^22 = 0x21e19e0c9bab2400000 = 0x878678326eac9 * 2^22
10000000000000000000000.0
};
static const int kExactPowersOfTenSize = ARRAY_SIZE(exact_powers_of_ten);
extern "C" double gay_strtod(const char* s00, const char** se);
static double old_strtod(Vector<const char> buffer, int exponent) {
char gay_buffer[1024];
Vector<char> gay_buffer_vector(gay_buffer, sizeof(gay_buffer));
int pos = 0;
for (int i = 0; i < buffer.length(); ++i) {
gay_buffer_vector[pos++] = buffer[i];
}
gay_buffer_vector[pos++] = 'e';
if (exponent < 0) {
gay_buffer_vector[pos++] = '-';
exponent = -exponent;
}
const int kNumberOfExponentDigits = 5;
for (int i = kNumberOfExponentDigits - 1; i >= 0; i--) {
gay_buffer_vector[pos + i] = exponent % 10 + '0';
exponent /= 10;
}
pos += kNumberOfExponentDigits;
gay_buffer_vector[pos] = '\0';
return gay_strtod(gay_buffer, NULL);
}
static Vector<const char> TrimLeadingZeros(Vector<const char> buffer) {
for (int i = 0; i < buffer.length(); i++) {
if (buffer[i] != '0') {
return Vector<const char>(buffer.start() + i, buffer.length() - i);
}
}
return Vector<const char>(buffer.start(), 0);
}
static Vector<const char> TrimTrailingZeros(Vector<const char> buffer) {
for (int i = buffer.length() - 1; i >= 0; --i) {
if (buffer[i] != '0') {
return Vector<const char>(buffer.start(), i + 1);
}
}
return Vector<const char>(buffer.start(), 0);
}
uint64_t ReadUint64(Vector<const char> buffer) {
ASSERT(buffer.length() <= kMaxUint64DecimalDigits);
uint64_t result = 0;
for (int i = 0; i < buffer.length(); ++i) {
int digit = buffer[i] - '0';
ASSERT(0 <= digit && digit <= 9);
result = 10 * result + digit;
}
return result;
}
double Strtod(Vector<const char> buffer, int exponent) {
Vector<const char> left_trimmed = TrimLeadingZeros(buffer);
Vector<const char> trimmed = TrimTrailingZeros(left_trimmed);
exponent += left_trimmed.length() - trimmed.length();
if (trimmed.length() == 0) return 0.0;
if (exponent + trimmed.length() - 1 >= kMaxDecimalPower) return V8_INFINITY;
if (exponent + trimmed.length() <= kMinDecimalPower) return 0.0;
if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) {
// The trimmed input fits into a double.
// If the 10^exponent (resp. 10^-exponent) fits into a double too then we
// can compute the result-double simply by multiplying (resp. dividing) the
// two numbers.
// This is possible because IEEE guarantees that floating-point operations
// return the best possible approximation.
if (exponent < 0 && -exponent < kExactPowersOfTenSize) {
// 10^-exponent fits into a double.
double buffer_d = static_cast<double>(ReadUint64(trimmed));
return buffer_d / exact_powers_of_ten[-exponent];
}
if (0 <= exponent && exponent < kExactPowersOfTenSize) {
// 10^exponent fits into a double.
double buffer_d = static_cast<double>(ReadUint64(trimmed));
return buffer_d * exact_powers_of_ten[exponent];
}
int remaining_digits =
kMaxExactDoubleIntegerDecimalDigits - trimmed.length();
if ((0 <= exponent) &&
(exponent - remaining_digits < kExactPowersOfTenSize)) {
// The trimmed string was short and we can multiply it with
// 10^remaining_digits. As a result the remaining exponent now fits
// into a double too.
double buffer_d = static_cast<double>(ReadUint64(trimmed));
buffer_d *= exact_powers_of_ten[remaining_digits];
return buffer_d * exact_powers_of_ten[exponent - remaining_digits];
}
}
return old_strtod(trimmed, exponent);
}
} } // namespace v8::internal

40
deps/v8/src/strtod.h

@ -0,0 +1,40 @@
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef V8_STRTOD_H_
#define V8_STRTOD_H_
namespace v8 {
namespace internal {
// The buffer must only contain digits in the range [0-9]. It must not
// contain a dot or a sign. It must not start with '0', and must not be empty.
double Strtod(Vector<const char> buffer, int exponent);
} } // namespace v8::internal
#endif // V8_STRTOD_H_

26
deps/v8/src/top.cc

@ -344,6 +344,10 @@ Handle<JSArray> Top::CaptureCurrentStackTrace(
Handle<String> column_key = Factory::LookupAsciiSymbol("column");
Handle<String> line_key = Factory::LookupAsciiSymbol("lineNumber");
Handle<String> script_key = Factory::LookupAsciiSymbol("scriptName");
Handle<String> name_or_source_url_key =
Factory::LookupAsciiSymbol("nameOrSourceURL");
Handle<String> script_name_or_source_url_key =
Factory::LookupAsciiSymbol("scriptNameOrSourceURL");
Handle<String> function_key = Factory::LookupAsciiSymbol("functionName");
Handle<String> eval_key = Factory::LookupAsciiSymbol("isEval");
Handle<String> constructor_key = Factory::LookupAsciiSymbol("isConstructor");
@ -355,13 +359,13 @@ Handle<JSArray> Top::CaptureCurrentStackTrace(
Handle<JSObject> stackFrame = Factory::NewJSObject(object_function());
JavaScriptFrame* frame = it.frame();
JSFunction* fun(JSFunction::cast(frame->function()));
Script* script = Script::cast(fun->shared()->script());
Handle<JSFunction> fun(JSFunction::cast(frame->function()));
Handle<Script> script(Script::cast(fun->shared()->script()));
if (options & StackTrace::kLineNumber) {
int script_line_offset = script->line_offset()->value();
int position = frame->code()->SourcePosition(frame->pc());
int line_number = GetScriptLineNumber(Handle<Script>(script), position);
int line_number = GetScriptLineNumber(script, position);
// line_number is already shifted by the script_line_offset.
int relative_line_number = line_number - script_line_offset;
if (options & StackTrace::kColumnOffset && relative_line_number >= 0) {
@ -385,6 +389,22 @@ Handle<JSArray> Top::CaptureCurrentStackTrace(
SetProperty(stackFrame, script_key, script_name, NONE);
}
if (options & StackTrace::kScriptNameOrSourceURL) {
Handle<Object> script_name(script->name());
Handle<JSValue> script_wrapper = GetScriptWrapper(script);
Handle<Object> property = GetProperty(script_wrapper,
name_or_source_url_key);
ASSERT(property->IsJSFunction());
Handle<JSFunction> method = Handle<JSFunction>::cast(property);
bool caught_exception;
Handle<Object> result = Execution::TryCall(method, script_wrapper, 0,
NULL, &caught_exception);
if (caught_exception) {
result = Factory::undefined_value();
}
SetProperty(stackFrame, script_name_or_source_url_key, result, NONE);
}
if (options & StackTrace::kFunctionName) {
Handle<Object> fun_name(fun->shared()->name());
if (fun_name->ToBoolean()->IsFalse()) {

11
deps/v8/src/v8-counters.h

@ -1,4 +1,4 @@
// Copyright 2007-2008 the V8 project authors. All rights reserved.
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@ -45,14 +45,7 @@ namespace internal {
/* Total compilation times. */ \
HT(compile, V8.Compile) \
HT(compile_eval, V8.CompileEval) \
HT(compile_lazy, V8.CompileLazy) \
/* Individual compiler passes. */ \
HT(rewriting, V8.Rewriting) \
HT(usage_analysis, V8.UsageAnalysis) \
HT(variable_allocation, V8.VariableAllocation) \
HT(ast_optimization, V8.ASTOptimization) \
HT(code_generation, V8.CodeGeneration) \
HT(deferred_code_generation, V8.DeferredCodeGeneration)
HT(compile_lazy, V8.CompileLazy)
// WARNING: STATS_COUNTER_LIST_* is a very large macro that is causing MSVC

2
deps/v8/src/v8.cc

@ -68,7 +68,7 @@ bool V8::Initialize(Deserializer* des) {
OS::Setup();
// Initialize other runtime facilities
#if !V8_HOST_ARCH_ARM && V8_TARGET_ARCH_ARM
#if (defined(USE_SIMULATOR) || !V8_HOST_ARCH_ARM) && V8_TARGET_ARCH_ARM
::assembler::arm::Simulator::Initialize();
#endif

4
deps/v8/src/version.cc

@ -33,8 +33,8 @@
// NOTE these macros are used by the SCons build script so their names
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 2
#define MINOR_VERSION 4
#define BUILD_NUMBER 8
#define MINOR_VERSION 5
#define BUILD_NUMBER 0
#define PATCH_LEVEL 0
#define CANDIDATE_VERSION false

14
deps/v8/src/x64/code-stubs-x64.cc

@ -1413,20 +1413,8 @@ void GenericUnaryOpStub::Generate(MacroAssembler* masm) {
__ j(equal, &done);
}
__ SmiNeg(rax, rax, &done);
__ jmp(&slow); // zero, if not handled above, and Smi::kMinValue.
// Either zero or Smi::kMinValue, neither of which become a smi when
// negated. We handle negative zero here if required. We always enter
// the runtime system if we have Smi::kMinValue.
if (negative_zero_ == kStrictNegativeZero) {
__ SmiCompare(rax, Smi::FromInt(0));
__ j(not_equal, &slow);
__ Move(rax, Factory::minus_zero_value());
__ jmp(&done);
} else {
__ SmiCompare(rax, Smi::FromInt(Smi::kMinValue));
__ j(equal, &slow);
__ jmp(&done);
}
// Try floating point case.
__ bind(&try_float);
} else if (FLAG_debug_code) {

32
deps/v8/src/x64/codegen-x64.cc

@ -178,22 +178,12 @@ void CodeGenerator::Generate(CompilationInfo* info) {
// Adjust for function-level loop nesting.
ASSERT_EQ(0, loop_nesting_);
loop_nesting_ = info->loop_nesting();
loop_nesting_ = info->is_in_loop() ? 1 : 0;
JumpTarget::set_compiling_deferred_code(false);
#ifdef DEBUG
if (strlen(FLAG_stop_at) > 0 &&
info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
frame_->SpillAll();
__ int3();
}
#endif
// New scope to get automatic timing calculation.
{ HistogramTimerScope codegen_timer(&Counters::code_generation);
{
CodeGenState state(this);
// Entry:
// Stack: receiver, arguments, return address.
// rbp: caller's frame pointer
@ -202,6 +192,14 @@ void CodeGenerator::Generate(CompilationInfo* info) {
// rsi: callee's context
allocator_->Initialize();
#ifdef DEBUG
if (strlen(FLAG_stop_at) > 0 &&
info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
frame_->SpillAll();
__ int3();
}
#endif
frame_->Enter();
// Allocate space for locals and initialize them.
@ -356,7 +354,7 @@ void CodeGenerator::Generate(CompilationInfo* info) {
}
// Adjust for function-level loop nesting.
ASSERT_EQ(loop_nesting_, info->loop_nesting());
ASSERT_EQ(loop_nesting_, info->is_in_loop() ? 1 : 0);
loop_nesting_ = 0;
// Code generation state must be reset.
@ -367,7 +365,6 @@ void CodeGenerator::Generate(CompilationInfo* info) {
// Process any deferred code using the register allocator.
if (!HasStackOverflow()) {
HistogramTimerScope deferred_timer(&Counters::deferred_code_generation);
JumpTarget::set_compiling_deferred_code(true);
ProcessDeferred();
JumpTarget::set_compiling_deferred_code(false);
@ -4276,9 +4273,12 @@ void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
// Build the function info and instantiate it.
Handle<SharedFunctionInfo> function_info =
Compiler::BuildFunctionInfo(node, script(), this);
Compiler::BuildFunctionInfo(node, script());
// Check for stack-overflow exception.
if (HasStackOverflow()) return;
if (function_info.is_null()) {
SetStackOverflow();
return;
}
InstantiateFunction(function_info);
}

7
deps/v8/src/x64/codegen-x64.h

@ -298,9 +298,7 @@ enum ArgumentsAllocationMode {
class CodeGenerator: public AstVisitor {
public:
// Takes a function literal, generates code for it. This function should only
// be called by compiler.cc.
static Handle<Code> MakeCode(CompilationInfo* info);
static bool MakeCode(CompilationInfo* info);
// Printing of AST, etc. as requested by flags.
static void MakeCodePrologue(CompilationInfo* info);
@ -586,9 +584,6 @@ class CodeGenerator: public AstVisitor {
void CheckStack();
static InlineFunctionGenerator FindInlineFunctionGenerator(
Runtime::FunctionId function_id);
bool CheckForInlineRuntimeCall(CallRuntime* node);
void ProcessDeclarations(ZoneList<Declaration*>* declarations);

6
deps/v8/src/x64/full-codegen-x64.cc

@ -61,6 +61,12 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
SetFunctionPosition(function());
Comment cmnt(masm_, "[ function compiled by full code generator");
#ifdef DEBUG
if (strlen(FLAG_stop_at) > 0 &&
info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
__ int3();
}
#endif
__ push(rbp); // Caller's frame pointer.
__ movq(rbp, rsp);
__ push(rsi); // Callee's context.

1
deps/v8/test/cctest/SConscript

@ -70,6 +70,7 @@ SOURCES = {
'test-sockets.cc',
'test-spaces.cc',
'test-strings.cc',
'test-strtod.cc',
'test-thread-termination.cc',
'test-threads.cc',
'test-type-info.cc',

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

@ -766,6 +766,12 @@ static v8::Handle<Value> construct_call(const v8::Arguments& args) {
return args.This();
}
static v8::Handle<Value> Return239(Local<String> name, const AccessorInfo&) {
ApiTestFuzzer::Fuzz();
return v8_num(239);
}
THREADED_TEST(FunctionTemplate) {
v8::HandleScope scope;
LocalContext env;
@ -792,6 +798,7 @@ THREADED_TEST(FunctionTemplate) {
Local<v8::FunctionTemplate> fun_templ =
v8::FunctionTemplate::New(construct_call);
fun_templ->SetClassName(v8_str("funky"));
fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), Return239);
Local<Function> fun = fun_templ->GetFunction();
env->Global()->Set(v8_str("obj"), fun);
Local<Script> script = v8_compile("var s = new obj(); s.x");
@ -799,6 +806,9 @@ THREADED_TEST(FunctionTemplate) {
Local<Value> result = v8_compile("(new obj()).toString()")->Run();
CHECK_EQ(v8_str("[object funky]"), result);
result = v8_compile("(new obj()).m")->Run();
CHECK_EQ(239, result->Int32Value());
}
}
@ -6509,12 +6519,6 @@ THREADED_TEST(InterceptorLoadICInvalidatedFieldViaGlobal) {
}
static v8::Handle<Value> Return239(Local<String> name, const AccessorInfo&) {
ApiTestFuzzer::Fuzz();
return v8_num(239);
}
static void SetOnThis(Local<String> name,
Local<Value> value,
const AccessorInfo& info) {
@ -10555,6 +10559,45 @@ TEST(CaptureStackTraceForUncaughtException) {
}
v8::Handle<Value> AnalyzeStackOfEvalWithSourceURL(const v8::Arguments& args) {
v8::HandleScope scope;
v8::Handle<v8::StackTrace> stackTrace =
v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kDetailed);
CHECK_EQ(5, stackTrace->GetFrameCount());
v8::Handle<v8::String> url = v8_str("eval_url");
for (int i = 0; i < 3; i++) {
v8::Handle<v8::String> name =
stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
CHECK(!name.IsEmpty());
CHECK_EQ(url, name);
}
return v8::Undefined();
}
TEST(SourceURLInStackTrace) {
v8::HandleScope scope;
Local<ObjectTemplate> templ = ObjectTemplate::New();
templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
v8::FunctionTemplate::New(AnalyzeStackOfEvalWithSourceURL));
LocalContext context(0, templ);
const char *source =
"function outer() {\n"
"function bar() {\n"
" AnalyzeStackOfEvalWithSourceURL();\n"
"}\n"
"function foo() {\n"
"\n"
" bar();\n"
"}\n"
"foo();\n"
"}\n"
"eval('(' + outer +')()//@ sourceURL=eval_url');";
CHECK(CompileRun(source)->IsUndefined());
}
// Test that idle notification can be handled and eventually returns true.
THREADED_TEST(IdleNotification) {
bool rv = false;
@ -11619,3 +11662,96 @@ TEST(GlobalLoadICGC) {
CheckSurvivingGlobalObjectsCount(1);
}
}
TEST(RegExp) {
v8::HandleScope scope;
LocalContext context;
v8::Handle<v8::RegExp> re = v8::RegExp::New(v8_str("foo"), v8::RegExp::kNone);
CHECK(re->IsRegExp());
CHECK(re->GetSource()->Equals(v8_str("foo")));
CHECK_EQ(re->GetFlags(), v8::RegExp::kNone);
re = v8::RegExp::New(v8_str("bar"),
static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
v8::RegExp::kGlobal));
CHECK(re->IsRegExp());
CHECK(re->GetSource()->Equals(v8_str("bar")));
CHECK_EQ(static_cast<int>(re->GetFlags()),
v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal);
re = v8::RegExp::New(v8_str("baz"),
static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
v8::RegExp::kMultiline));
CHECK(re->IsRegExp());
CHECK(re->GetSource()->Equals(v8_str("baz")));
CHECK_EQ(static_cast<int>(re->GetFlags()),
v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline);
re = CompileRun("/quux/").As<v8::RegExp>();
CHECK(re->IsRegExp());
CHECK(re->GetSource()->Equals(v8_str("quux")));
CHECK_EQ(re->GetFlags(), v8::RegExp::kNone);
re = CompileRun("/quux/gm").As<v8::RegExp>();
CHECK(re->IsRegExp());
CHECK(re->GetSource()->Equals(v8_str("quux")));
CHECK_EQ(static_cast<int>(re->GetFlags()),
v8::RegExp::kGlobal | v8::RegExp::kMultiline);
// Override the RegExp constructor and check the API constructor
// still works.
CompileRun("RegExp = function() {}");
re = v8::RegExp::New(v8_str("foobar"), v8::RegExp::kNone);
CHECK(re->IsRegExp());
CHECK(re->GetSource()->Equals(v8_str("foobar")));
CHECK_EQ(re->GetFlags(), v8::RegExp::kNone);
re = v8::RegExp::New(v8_str("foobarbaz"),
static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
v8::RegExp::kMultiline));
CHECK(re->IsRegExp());
CHECK(re->GetSource()->Equals(v8_str("foobarbaz")));
CHECK_EQ(static_cast<int>(re->GetFlags()),
v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline);
context->Global()->Set(v8_str("re"), re);
ExpectTrue("re.test('FoobarbaZ')");
v8::TryCatch try_catch;
re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone);
CHECK(re.IsEmpty());
CHECK(try_catch.HasCaught());
context->Global()->Set(v8_str("ex"), try_catch.Exception());
ExpectTrue("ex instanceof SyntaxError");
}
static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property,
const v8::AccessorInfo& info ) {
return v8_str("42!");
}
static v8::Handle<v8::Array> Enumerator(const v8::AccessorInfo& info) {
v8::Handle<v8::Array> result = v8::Array::New();
result->Set(0, v8_str("universalAnswer"));
return result;
}
TEST(NamedEnumeratorAndForIn) {
v8::HandleScope handle_scope;
LocalContext context;
v8::Context::Scope context_scope(context.local());
v8::Handle<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New();
tmpl->SetNamedPropertyHandler(Getter, NULL, NULL, NULL, Enumerator);
context->Global()->Set(v8_str("o"), tmpl->NewInstance());
v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
"var result = []; for (var k in o) result.push(k); result"));
CHECK_EQ(1, result->Length());
CHECK_EQ(v8_str("universalAnswer"), result->Get(0));
}

32
deps/v8/test/cctest/test-conversions.cc

@ -168,6 +168,38 @@ TEST(MaximumSignificantDigits) {
CHECK_EQ(gay_strtod(num, NULL), StringToDouble(num, NO_FLAGS));
}
TEST(MinimumExponent) {
// Same test but with different point-position.
char num[] =
"445014771701440202508199667279499186358524265859260511351695091"
"228726223124931264069530541271189424317838013700808305231545782"
"515453032382772695923684574304409936197089118747150815050941806"
"048037511737832041185193533879641611520514874130831632725201246"
"060231058690536206311752656217652146466431814205051640436322226"
"680064743260560117135282915796422274554896821334728738317548403"
"413978098469341510556195293821919814730032341053661708792231510"
"873354131880491105553390278848567812190177545006298062245710295"
"816371174594568773301103242116891776567137054973871082078224775"
"842509670618916870627821633352993761380751142008862499795052791"
"018709663463944015644907297315659352441231715398102212132212018"
"470035807616260163568645811358486831521563686919762403704226016"
"998291015625000000000000000000000000000000000e-1108";
CHECK_EQ(gay_strtod(num, NULL), StringToDouble(num, NO_FLAGS));
// Changes the result of strtod (at least in glibc implementation).
num[sizeof(num) - 8] = '1';
CHECK_EQ(gay_strtod(num, NULL), StringToDouble(num, NO_FLAGS));
}
TEST(MaximumExponent) {
char num[] = "0.16e309";
CHECK_EQ(gay_strtod(num, NULL), StringToDouble(num, NO_FLAGS));
}
TEST(ExponentNumberStr) {
CHECK_EQ(1e1, StringToDouble("1e1", NO_FLAGS));

80
deps/v8/test/cctest/test-heap-profiler.cc

@ -20,11 +20,6 @@ using i::JSObjectsClusterTree;
using i::RetainerHeapProfile;
static void CompileAndRunScript(const char *src) {
v8::Script::Compile(v8::String::New(src))->Run();
}
namespace {
class ConstructorHeapProfileTestHelper : public i::ConstructorHeapProfile {
@ -58,7 +53,7 @@ TEST(ConstructorProfile) {
v8::HandleScope scope;
LocalContext env;
CompileAndRunScript(
CompileRun(
"function F() {} // A constructor\n"
"var f1 = new F();\n"
"var f2 = new F();\n");
@ -359,7 +354,7 @@ TEST(RetainerProfile) {
v8::HandleScope scope;
LocalContext env;
CompileAndRunScript(
CompileRun(
"function A() {}\n"
"function B(x) { this.x = x; }\n"
"function C(x) { this.x1 = x; this.x2 = x; }\n"
@ -473,7 +468,7 @@ TEST(HeapSnapshot) {
LocalContext env1;
env1->SetSecurityToken(token1);
CompileAndRunScript(
CompileRun(
"function A1() {}\n"
"function B1(x) { this.x = x; }\n"
"function C1(x) { this.x1 = x; this.x2 = x; }\n"
@ -485,7 +480,7 @@ TEST(HeapSnapshot) {
LocalContext env2;
env2->SetSecurityToken(token2);
CompileAndRunScript(
CompileRun(
"function A2() {}\n"
"function B2(x) { return function() { return typeof x; }; }\n"
"function C2(x) { this.x1 = x; this.x2 = x; this[1] = x; }\n"
@ -583,7 +578,7 @@ TEST(HeapSnapshotObjectSizes) {
// -a-> X1 --a
// x -b-> X2 <-|
CompileAndRunScript(
CompileRun(
"function X(a, b) { this.a = a; this.b = b; }\n"
"x = new X(new X(), new X());\n"
"x.a.a = x.b;");
@ -594,7 +589,7 @@ TEST(HeapSnapshotObjectSizes) {
GetProperty(global, v8::HeapGraphEdge::kProperty, "x");
CHECK_NE(NULL, x);
const v8::HeapGraphNode* x_prototype =
GetProperty(x, v8::HeapGraphEdge::kProperty, "prototype");
GetProperty(x, v8::HeapGraphEdge::kProperty, "__proto__");
CHECK_NE(NULL, x_prototype);
const v8::HeapGraphNode* x1 =
GetProperty(x, v8::HeapGraphEdge::kProperty, "a");
@ -606,7 +601,7 @@ TEST(HeapSnapshotObjectSizes) {
x->GetSelfSize() * 3,
x->GetReachableSize() - x_prototype->GetReachableSize());
CHECK_EQ(
x->GetSelfSize() * 3 + x_prototype->GetSelfSize(), x->GetRetainedSize());
x->GetSelfSize() * 3, x->GetRetainedSize());
CHECK_EQ(
x1->GetSelfSize() * 2,
x1->GetReachableSize() - x_prototype->GetReachableSize());
@ -624,7 +619,7 @@ TEST(HeapSnapshotEntryChildren) {
v8::HandleScope scope;
LocalContext env;
CompileAndRunScript(
CompileRun(
"function A() { }\n"
"a = new A;");
const v8::HeapSnapshot* snapshot =
@ -648,10 +643,9 @@ TEST(HeapSnapshotCodeObjects) {
v8::HandleScope scope;
LocalContext env;
CompileAndRunScript(
CompileRun(
"function lazy(x) { return x - 1; }\n"
"function compiled(x) { return x + 1; }\n"
"var inferred = function(x) { return x; }\n"
"var anonymous = (function() { return function() { return 0; } })();\n"
"compiled(1)");
const v8::HeapSnapshot* snapshot =
@ -666,18 +660,12 @@ TEST(HeapSnapshotCodeObjects) {
GetProperty(global, v8::HeapGraphEdge::kProperty, "lazy");
CHECK_NE(NULL, lazy);
CHECK_EQ(v8::HeapGraphNode::kClosure, lazy->GetType());
const v8::HeapGraphNode* inferred =
GetProperty(global, v8::HeapGraphEdge::kProperty, "inferred");
CHECK_NE(NULL, inferred);
CHECK_EQ(v8::HeapGraphNode::kClosure, inferred->GetType());
v8::String::AsciiValue inferred_name(inferred->GetName());
CHECK_EQ("inferred", *inferred_name);
const v8::HeapGraphNode* anonymous =
GetProperty(global, v8::HeapGraphEdge::kProperty, "anonymous");
CHECK_NE(NULL, anonymous);
CHECK_EQ(v8::HeapGraphNode::kClosure, anonymous->GetType());
v8::String::AsciiValue anonymous_name(anonymous->GetName());
CHECK_EQ("(anonymous function)", *anonymous_name);
CHECK_EQ("", *anonymous_name);
// Find references to code.
const v8::HeapGraphNode* compiled_code =
@ -716,6 +704,44 @@ TEST(HeapSnapshotCodeObjects) {
}
TEST(HeapSnapshotHeapNumbers) {
v8::HandleScope scope;
LocalContext env;
CompileRun(
"a = 1; // a is Smi\n"
"b = 2.5; // b is HeapNumber");
const v8::HeapSnapshot* snapshot =
v8::HeapProfiler::TakeSnapshot(v8::String::New("numbers"));
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
CHECK_EQ(NULL, GetProperty(global, v8::HeapGraphEdge::kProperty, "a"));
const v8::HeapGraphNode* b =
GetProperty(global, v8::HeapGraphEdge::kProperty, "b");
CHECK_NE(NULL, b);
CHECK_EQ(v8::HeapGraphNode::kHeapNumber, b->GetType());
}
TEST(HeapSnapshotInternalReferences) {
v8::HandleScope scope;
v8::Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
global_template->SetInternalFieldCount(2);
LocalContext env(NULL, global_template);
v8::Handle<v8::Object> global_proxy = env->Global();
v8::Handle<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
CHECK_EQ(2, global->InternalFieldCount());
v8::Local<v8::Object> obj = v8::Object::New();
global->SetInternalField(0, v8_num(17));
global->SetInternalField(1, obj);
const v8::HeapSnapshot* snapshot =
v8::HeapProfiler::TakeSnapshot(v8::String::New("internals"));
const v8::HeapGraphNode* global_node = GetGlobalObject(snapshot);
// The first reference will not present, because it's a Smi.
CHECK_EQ(NULL, GetProperty(global_node, v8::HeapGraphEdge::kInternal, "0"));
// The second reference is to an object.
CHECK_NE(NULL, GetProperty(global_node, v8::HeapGraphEdge::kInternal, "1"));
}
// Trying to introduce a check helper for uint64_t causes many
// overloading ambiguities, so it seems easier just to cast
// them to a signed type.
@ -728,7 +754,7 @@ TEST(HeapEntryIdsAndGC) {
v8::HandleScope scope;
LocalContext env;
CompileAndRunScript(
CompileRun(
"function A() {}\n"
"function B(x) { this.x = x; }\n"
"var a = new A();\n"
@ -784,7 +810,7 @@ TEST(HeapSnapshotsDiff) {
v8::HandleScope scope;
LocalContext env;
CompileAndRunScript(
CompileRun(
"function A() {}\n"
"function B(x) { this.x = x; }\n"
"function A2(a) { for (var i = 0; i < a; ++i) this[i] = i; }\n"
@ -793,7 +819,7 @@ TEST(HeapSnapshotsDiff) {
const v8::HeapSnapshot* snapshot1 =
v8::HeapProfiler::TakeSnapshot(v8::String::New("s1"));
CompileAndRunScript(
CompileRun(
"delete a;\n"
"b.x = null;\n"
"var a = new A2(20);\n"
@ -928,7 +954,7 @@ TEST(AggregatedHeapSnapshot) {
v8::HandleScope scope;
LocalContext env;
CompileAndRunScript(
CompileRun(
"function A() {}\n"
"function B(x) { this.x = x; }\n"
"var a = new A();\n"
@ -1049,7 +1075,7 @@ TEST(HeapSnapshotJSONSerialization) {
#define STRING_LITERAL_FOR_TEST \
"\"String \\n\\r\\u0008\\u0081\\u0101\\u0801\\u8001\""
CompileAndRunScript(
CompileRun(
"function A(s) { this.s = s; }\n"
"function B(x) { this.x = x; }\n"
"var a = new A(" STRING_LITERAL_FOR_TEST ");\n"

201
deps/v8/test/cctest/test-strtod.cc

@ -0,0 +1,201 @@
// Copyright 2006-2008 the V8 project authors. All rights reserved.
#include <stdlib.h>
#include "v8.h"
#include "cctest.h"
#include "strtod.h"
using namespace v8::internal;
static Vector<const char> StringToVector(const char* str) {
return Vector<const char>(str, StrLength(str));
}
static double StrtodChar(const char* str, int exponent) {
return Strtod(StringToVector(str), exponent);
}
TEST(Strtod) {
Vector<const char> vector;
vector = StringToVector("0");
CHECK_EQ(0.0, Strtod(vector, 1));
CHECK_EQ(0.0, Strtod(vector, 2));
CHECK_EQ(0.0, Strtod(vector, -2));
CHECK_EQ(0.0, Strtod(vector, -999));
CHECK_EQ(0.0, Strtod(vector, +999));
vector = StringToVector("1");
CHECK_EQ(1.0, Strtod(vector, 0));
CHECK_EQ(10.0, Strtod(vector, 1));
CHECK_EQ(100.0, Strtod(vector, 2));
CHECK_EQ(1e20, Strtod(vector, 20));
CHECK_EQ(1e22, Strtod(vector, 22));
CHECK_EQ(1e23, Strtod(vector, 23));
CHECK_EQ(1e35, Strtod(vector, 35));
CHECK_EQ(1e36, Strtod(vector, 36));
CHECK_EQ(1e37, Strtod(vector, 37));
CHECK_EQ(1e-1, Strtod(vector, -1));
CHECK_EQ(1e-2, Strtod(vector, -2));
CHECK_EQ(1e-5, Strtod(vector, -5));
CHECK_EQ(1e-20, Strtod(vector, -20));
CHECK_EQ(1e-22, Strtod(vector, -22));
CHECK_EQ(1e-23, Strtod(vector, -23));
CHECK_EQ(1e-25, Strtod(vector, -25));
CHECK_EQ(1e-39, Strtod(vector, -39));
vector = StringToVector("2");
CHECK_EQ(2.0, Strtod(vector, 0));
CHECK_EQ(20.0, Strtod(vector, 1));
CHECK_EQ(200.0, Strtod(vector, 2));
CHECK_EQ(2e20, Strtod(vector, 20));
CHECK_EQ(2e22, Strtod(vector, 22));
CHECK_EQ(2e23, Strtod(vector, 23));
CHECK_EQ(2e35, Strtod(vector, 35));
CHECK_EQ(2e36, Strtod(vector, 36));
CHECK_EQ(2e37, Strtod(vector, 37));
CHECK_EQ(2e-1, Strtod(vector, -1));
CHECK_EQ(2e-2, Strtod(vector, -2));
CHECK_EQ(2e-5, Strtod(vector, -5));
CHECK_EQ(2e-20, Strtod(vector, -20));
CHECK_EQ(2e-22, Strtod(vector, -22));
CHECK_EQ(2e-23, Strtod(vector, -23));
CHECK_EQ(2e-25, Strtod(vector, -25));
CHECK_EQ(2e-39, Strtod(vector, -39));
vector = StringToVector("9");
CHECK_EQ(9.0, Strtod(vector, 0));
CHECK_EQ(90.0, Strtod(vector, 1));
CHECK_EQ(900.0, Strtod(vector, 2));
CHECK_EQ(9e20, Strtod(vector, 20));
CHECK_EQ(9e22, Strtod(vector, 22));
CHECK_EQ(9e23, Strtod(vector, 23));
CHECK_EQ(9e35, Strtod(vector, 35));
CHECK_EQ(9e36, Strtod(vector, 36));
CHECK_EQ(9e37, Strtod(vector, 37));
CHECK_EQ(9e-1, Strtod(vector, -1));
CHECK_EQ(9e-2, Strtod(vector, -2));
CHECK_EQ(9e-5, Strtod(vector, -5));
CHECK_EQ(9e-20, Strtod(vector, -20));
CHECK_EQ(9e-22, Strtod(vector, -22));
CHECK_EQ(9e-23, Strtod(vector, -23));
CHECK_EQ(9e-25, Strtod(vector, -25));
CHECK_EQ(9e-39, Strtod(vector, -39));
vector = StringToVector("12345");
CHECK_EQ(12345.0, Strtod(vector, 0));
CHECK_EQ(123450.0, Strtod(vector, 1));
CHECK_EQ(1234500.0, Strtod(vector, 2));
CHECK_EQ(12345e20, Strtod(vector, 20));
CHECK_EQ(12345e22, Strtod(vector, 22));
CHECK_EQ(12345e23, Strtod(vector, 23));
CHECK_EQ(12345e30, Strtod(vector, 30));
CHECK_EQ(12345e31, Strtod(vector, 31));
CHECK_EQ(12345e32, Strtod(vector, 32));
CHECK_EQ(12345e35, Strtod(vector, 35));
CHECK_EQ(12345e36, Strtod(vector, 36));
CHECK_EQ(12345e37, Strtod(vector, 37));
CHECK_EQ(12345e-1, Strtod(vector, -1));
CHECK_EQ(12345e-2, Strtod(vector, -2));
CHECK_EQ(12345e-5, Strtod(vector, -5));
CHECK_EQ(12345e-20, Strtod(vector, -20));
CHECK_EQ(12345e-22, Strtod(vector, -22));
CHECK_EQ(12345e-23, Strtod(vector, -23));
CHECK_EQ(12345e-25, Strtod(vector, -25));
CHECK_EQ(12345e-39, Strtod(vector, -39));
vector = StringToVector("12345678901234");
CHECK_EQ(12345678901234.0, Strtod(vector, 0));
CHECK_EQ(123456789012340.0, Strtod(vector, 1));
CHECK_EQ(1234567890123400.0, Strtod(vector, 2));
CHECK_EQ(12345678901234e20, Strtod(vector, 20));
CHECK_EQ(12345678901234e22, Strtod(vector, 22));
CHECK_EQ(12345678901234e23, Strtod(vector, 23));
CHECK_EQ(12345678901234e30, Strtod(vector, 30));
CHECK_EQ(12345678901234e31, Strtod(vector, 31));
CHECK_EQ(12345678901234e32, Strtod(vector, 32));
CHECK_EQ(12345678901234e35, Strtod(vector, 35));
CHECK_EQ(12345678901234e36, Strtod(vector, 36));
CHECK_EQ(12345678901234e37, Strtod(vector, 37));
CHECK_EQ(12345678901234e-1, Strtod(vector, -1));
CHECK_EQ(12345678901234e-2, Strtod(vector, -2));
CHECK_EQ(12345678901234e-5, Strtod(vector, -5));
CHECK_EQ(12345678901234e-20, Strtod(vector, -20));
CHECK_EQ(12345678901234e-22, Strtod(vector, -22));
CHECK_EQ(12345678901234e-23, Strtod(vector, -23));
CHECK_EQ(12345678901234e-25, Strtod(vector, -25));
CHECK_EQ(12345678901234e-39, Strtod(vector, -39));
vector = StringToVector("123456789012345");
CHECK_EQ(123456789012345.0, Strtod(vector, 0));
CHECK_EQ(1234567890123450.0, Strtod(vector, 1));
CHECK_EQ(12345678901234500.0, Strtod(vector, 2));
CHECK_EQ(123456789012345e20, Strtod(vector, 20));
CHECK_EQ(123456789012345e22, Strtod(vector, 22));
CHECK_EQ(123456789012345e23, Strtod(vector, 23));
CHECK_EQ(123456789012345e35, Strtod(vector, 35));
CHECK_EQ(123456789012345e36, Strtod(vector, 36));
CHECK_EQ(123456789012345e37, Strtod(vector, 37));
CHECK_EQ(123456789012345e39, Strtod(vector, 39));
CHECK_EQ(123456789012345e-1, Strtod(vector, -1));
CHECK_EQ(123456789012345e-2, Strtod(vector, -2));
CHECK_EQ(123456789012345e-5, Strtod(vector, -5));
CHECK_EQ(123456789012345e-20, Strtod(vector, -20));
CHECK_EQ(123456789012345e-22, Strtod(vector, -22));
CHECK_EQ(123456789012345e-23, Strtod(vector, -23));
CHECK_EQ(123456789012345e-25, Strtod(vector, -25));
CHECK_EQ(123456789012345e-39, Strtod(vector, -39));
CHECK_EQ(0.0, StrtodChar("0", 12345));
CHECK_EQ(0.0, StrtodChar("", 1324));
CHECK_EQ(0.0, StrtodChar("000000000", 123));
CHECK_EQ(0.0, StrtodChar("2", -324));
CHECK_EQ(4e-324, StrtodChar("3", -324));
// It would be more readable to put non-zero literals on the left side (i.e.
// CHECK_EQ(1e-325, StrtodChar("1", -325))), but then Gcc complains that
// they are truncated to zero.
CHECK_EQ(0.0, StrtodChar("1", -325));
CHECK_EQ(0.0, StrtodChar("1", -325));
CHECK_EQ(0.0, StrtodChar("20000", -328));
CHECK_EQ(40000e-328, StrtodChar("30000", -328));
CHECK_EQ(0.0, StrtodChar("10000", -329));
CHECK_EQ(0.0, StrtodChar("90000", -329));
CHECK_EQ(0.0, StrtodChar("000000001", -325));
CHECK_EQ(0.0, StrtodChar("000000001", -325));
CHECK_EQ(0.0, StrtodChar("0000000020000", -328));
CHECK_EQ(40000e-328, StrtodChar("00000030000", -328));
CHECK_EQ(0.0, StrtodChar("0000000010000", -329));
CHECK_EQ(0.0, StrtodChar("0000000090000", -329));
// It would be more readable to put the literals (and not V8_INFINITY) on the
// left side (i.e. CHECK_EQ(1e309, StrtodChar("1", 309))), but then Gcc
// complains that the floating constant exceeds range of 'double'.
CHECK_EQ(V8_INFINITY, StrtodChar("1", 309));
CHECK_EQ(1e308, StrtodChar("1", 308));
CHECK_EQ(1234e305, StrtodChar("1234", 305));
CHECK_EQ(1234e304, StrtodChar("1234", 304));
CHECK_EQ(V8_INFINITY, StrtodChar("18", 307));
CHECK_EQ(17e307, StrtodChar("17", 307));
CHECK_EQ(V8_INFINITY, StrtodChar("0000001", 309));
CHECK_EQ(1e308, StrtodChar("00000001", 308));
CHECK_EQ(1234e305, StrtodChar("00000001234", 305));
CHECK_EQ(1234e304, StrtodChar("000000001234", 304));
CHECK_EQ(V8_INFINITY, StrtodChar("0000000018", 307));
CHECK_EQ(17e307, StrtodChar("0000000017", 307));
CHECK_EQ(V8_INFINITY, StrtodChar("1000000", 303));
CHECK_EQ(1e308, StrtodChar("100000", 303));
CHECK_EQ(1234e305, StrtodChar("123400000", 300));
CHECK_EQ(1234e304, StrtodChar("123400000", 299));
CHECK_EQ(V8_INFINITY, StrtodChar("180000000", 300));
CHECK_EQ(17e307, StrtodChar("170000000", 300));
CHECK_EQ(V8_INFINITY, StrtodChar("00000001000000", 303));
CHECK_EQ(1e308, StrtodChar("000000000000100000", 303));
CHECK_EQ(1234e305, StrtodChar("00000000123400000", 300));
CHECK_EQ(1234e304, StrtodChar("0000000123400000", 299));
CHECK_EQ(V8_INFINITY, StrtodChar("00000000180000000", 300));
CHECK_EQ(17e307, StrtodChar("00000000170000000", 300));
}

87
deps/v8/test/mjsunit/regexp.js

@ -502,3 +502,90 @@ for (var i = 0; i < 100; i++) {
res[3] = "Glopglyf";
assertEquals("Arglebargle", res.foobar);
}
// Test that we perform the spec required conversions in the correct order.
var log;
var string = "the string";
var fakeLastIndex = {
valueOf: function() {
log.push("li");
return 0;
}
};
var fakeString = {
toString: function() {
log.push("ts");
return string;
},
length: 0
};
var re = /str/;
log = [];
re.lastIndex = fakeLastIndex;
var result = re.exec(fakeString);
assertEquals(["str"], result);
assertEquals(["ts", "li"], log);
// Again, to check if caching interferes.
log = [];
re.lastIndex = fakeLastIndex;
result = re.exec(fakeString);
assertEquals(["str"], result);
assertEquals(["ts", "li"], log);
// And one more time, just to be certain.
log = [];
re.lastIndex = fakeLastIndex;
result = re.exec(fakeString);
assertEquals(["str"], result);
assertEquals(["ts", "li"], log);
// Now with a global regexp, where lastIndex is actually used.
re = /str/g;
log = [];
re.lastIndex = fakeLastIndex;
var result = re.exec(fakeString);
assertEquals(["str"], result);
assertEquals(["ts", "li"], log);
// Again, to check if caching interferes.
log = [];
re.lastIndex = fakeLastIndex;
result = re.exec(fakeString);
assertEquals(["str"], result);
assertEquals(["ts", "li"], log);
// And one more time, just to be certain.
log = [];
re.lastIndex = fakeLastIndex;
result = re.exec(fakeString);
assertEquals(["str"], result);
assertEquals(["ts", "li"], log);
// Check that properties of RegExp have the correct permissions.
var re = /x/g;
var desc = Object.getOwnPropertyDescriptor(re, "global");
assertEquals(true, desc.value);
assertEquals(false, desc.configurable);
assertEquals(false, desc.enumerable);
assertEquals(false, desc.writable);
desc = Object.getOwnPropertyDescriptor(re, "multiline");
assertEquals(false, desc.value);
assertEquals(false, desc.configurable);
assertEquals(false, desc.enumerable);
assertEquals(false, desc.writable);
desc = Object.getOwnPropertyDescriptor(re, "ignoreCase");
assertEquals(false, desc.value);
assertEquals(false, desc.configurable);
assertEquals(false, desc.enumerable);
assertEquals(false, desc.writable);
desc = Object.getOwnPropertyDescriptor(re, "lastIndex");
assertEquals(0, desc.value);
assertEquals(false, desc.configurable);
assertEquals(false, desc.enumerable);
assertEquals(true, desc.writable);

35
deps/v8/test/mjsunit/regress/regress-58740.js

@ -0,0 +1,35 @@
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// See: http://code.google.com/p/chromium/issues/detail?id=58740
var re = /.+/g;
re.exec("");
re.exec("anystring");
re=/.+/g;
re.exec("");
assertEquals(0, re.lastIndex);

58
deps/v8/test/mjsunit/regress/regress-create-exception.js

@ -0,0 +1,58 @@
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --max-new-space-size=256
// Check for GC bug constructing exceptions.
var v = [1, 2, 3, 4]
Object.preventExtensions(v);
function foo() {
var re = /2147483647/; // Equal to 0x7fffffff.
for (var i = 0; i < 10000; i++) {
var ok = false;
try {
var j = 1;
// Allocate some heap numbers in order to randomize the behaviour of the
// garbage collector. 93 is chosen to be a prime number to avoid the
// allocation settling into a too neat pattern.
for (var j = 0; j < i % 93; j++) {
j *= 1.123567; // An arbitrary floating point number.
}
v[0x7fffffff] = 0; // Trigger exception.
assertTrue(false);
return j; // Make sure that future optimizations don't eliminate j.
} catch(e) {
ok = true;
assertTrue(re.test(e));
}
assertTrue(ok);
}
}
foo();

13
deps/v8/test/mjsunit/smi-negative-zero.js

@ -98,3 +98,16 @@ assertEquals(-Infinity, one / (-4 % 2), "fiskhest1");
assertEquals(-Infinity, one / (-4 % -2), "fiskhest2");
assertEquals(Infinity, one / (4 % 2), "fiskhest3");
assertEquals(Infinity, one / (4 % -2), "fiskhest4");
// This tests against a singleton -0.0 object being overwritten.gc
x = 0;
z = 3044;
function foo(x) {
var y = -x + z;
return -x;
}
assertEquals(0, foo(x));
assertEquals(0, foo(x));

4
deps/v8/tools/gyp/v8.gyp

@ -285,6 +285,7 @@
'../../src/builtins.cc',
'../../src/builtins.h',
'../../src/bytecodes-irregexp.h',
'../../src/cached-powers.cc',
'../../src/cached-powers.h',
'../../src/char-predicates-inl.h',
'../../src/char-predicates.h',
@ -402,7 +403,6 @@
'../../src/parser.cc',
'../../src/parser.h',
'../../src/platform.h',
'../../src/powers-ten.h',
'../../src/prettyprinter.cc',
'../../src/prettyprinter.h',
'../../src/property.cc',
@ -445,6 +445,8 @@
'../../src/string-search.h',
'../../src/string-stream.cc',
'../../src/string-stream.h',
'../../src/strtod.cc',
'../../src/strtod.h',
'../../src/stub-cache.cc',
'../../src/stub-cache.h',
'../../src/token.cc',

Loading…
Cancel
Save