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. 41
      deps/v8/src/codegen.cc
  21. 1
      deps/v8/src/codegen.h
  22. 380
      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. 32
      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. 1
      deps/v8/src/liveedit-debugger.js
  37. 44
      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. 43
      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. 142
      deps/v8/src/regexp.js
  48. 32
      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. Google Inc.
Sigma Designs Inc. Sigma Designs Inc.
ARM Ltd. ARM Ltd.
Hewlett-Packard Development Company, LP
Alexander Botero-Lowry <alexbl@FreeBSD.org> Alexander Botero-Lowry <alexbl@FreeBSD.org>
Alexandre Vassalotti <avassalotti@gmail.com> 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 2010-10-04: Version 2.4.8
Fixed a bug in ResumeProfilerEx causing it to not always write out the 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': { 'simulator:arm': {
'CCFLAGS': ['-m32'], 'CCFLAGS': ['-m32'],
'LINKFLAGS': ['-m32'] 'LINKFLAGS': ['-m32'],
'CPPDEFINES': ['USE_SIMULATOR']
}, },
'arch:mips': { 'arch:mips': {
'CPPDEFINES': ['V8_TARGET_ARCH_MIPS'], 'CPPDEFINES': ['V8_TARGET_ARCH_MIPS'],
@ -217,7 +218,8 @@ LIBRARY_FLAGS = {
}, },
'simulator:mips': { 'simulator:mips': {
'CCFLAGS': ['-m32'], 'CCFLAGS': ['-m32'],
'LINKFLAGS': ['-m32'] 'LINKFLAGS': ['-m32'],
'CPPDEFINES': ['USE_SIMULATOR']
}, },
'arch:x64': { 'arch:x64': {
'CPPDEFINES': ['V8_TARGET_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 // Scores are not comparable across versions. Bump the version if
// you're making changes that will affect that scores, e.g. if you add // you're making changes that will affect that scores, e.g. if you add
// a new benchmark or change an existing one. // 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 // 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. kString = 2, // A string.
kObject = 3, // A JS object (except for arrays and strings). kObject = 3, // A JS object (except for arrays and strings).
kCode = 4, // Compiled code. 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). */ /** Returns node type (see HeapGraphNode::Type). */

65
deps/v8/include/v8.h

@ -758,8 +758,9 @@ class V8EXPORT StackTrace {
kFunctionName = 1 << 3, kFunctionName = 1 << 3,
kIsEval = 1 << 4, kIsEval = 1 << 4,
kIsConstructor = 1 << 5, kIsConstructor = 1 << 5,
kScriptNameOrSourceURL = 1 << 6,
kOverview = kLineNumber | kColumnOffset | kScriptName | kFunctionName, 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; 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. * 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 { enum PropertyAttribute {
None = 0, None = 0,
ReadOnly = 1 << 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) { Object* Object::Cast(v8::Value* value) {
#ifdef V8_ENABLE_CHECKS #ifdef V8_ENABLE_CHECKS
CheckCast(value); CheckCast(value);

2
deps/v8/src/SConscript

@ -42,6 +42,7 @@ SOURCES = {
ast.cc ast.cc
bootstrapper.cc bootstrapper.cc
builtins.cc builtins.cc
cached-powers.cc
checks.cc checks.cc
circular-queue.cc circular-queue.cc
code-stubs.cc code-stubs.cc
@ -102,6 +103,7 @@ SOURCES = {
spaces.cc spaces.cc
string-search.cc string-search.cc
string-stream.cc string-stream.cc
strtod.cc
stub-cache.cc stub-cache.cc
token.cc token.cc
top.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 { Local<String> StackFrame::GetFunctionName() const {
if (IsDeadCheck("v8::StackFrame::GetFunctionName()")) return Local<String>(); if (IsDeadCheck("v8::StackFrame::GetFunctionName()")) return Local<String>();
ENTER_V8; 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 { bool Value::BooleanValue() const {
if (IsDeadCheck("v8::Value::BooleanValue()")) return false; if (IsDeadCheck("v8::Value::BooleanValue()")) return false;
LOG_API("BooleanValue"); 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) { Local<v8::Array> v8::Array::New(int length) {
EnsureInitialized("v8::Array::New()"); EnsureInitialized("v8::Array::New()");
LOG_API("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); v8::internal::Handle<v8::internal::JSFunction> obj);
static inline Local<String> ToLocal( static inline Local<String> ToLocal(
v8::internal::Handle<v8::internal::String> obj); v8::internal::Handle<v8::internal::String> obj);
static inline Local<RegExp> ToLocal(
v8::internal::Handle<v8::internal::JSRegExp> obj);
static inline Local<Object> ToLocal( static inline Local<Object> ToLocal(
v8::internal::Handle<v8::internal::JSObject> obj); v8::internal::Handle<v8::internal::JSObject> obj);
static inline Local<Array> ToLocal( static inline Local<Array> ToLocal(
@ -209,6 +211,8 @@ class Utils {
OpenHandle(const ObjectTemplate* that); OpenHandle(const ObjectTemplate* that);
static inline v8::internal::Handle<v8::internal::Object> static inline v8::internal::Handle<v8::internal::Object>
OpenHandle(const Data* data); OpenHandle(const Data* data);
static inline v8::internal::Handle<v8::internal::JSRegExp>
OpenHandle(const RegExp* data);
static inline v8::internal::Handle<v8::internal::JSObject> static inline v8::internal::Handle<v8::internal::JSObject>
OpenHandle(const v8::Object* data); OpenHandle(const v8::Object* data);
static inline v8::internal::Handle<v8::internal::JSArray> 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, Object, Value)
MAKE_TO_LOCAL(ToLocal, JSFunction, Function) MAKE_TO_LOCAL(ToLocal, JSFunction, Function)
MAKE_TO_LOCAL(ToLocal, String, String) MAKE_TO_LOCAL(ToLocal, String, String)
MAKE_TO_LOCAL(ToLocal, JSRegExp, RegExp)
MAKE_TO_LOCAL(ToLocal, JSObject, Object) MAKE_TO_LOCAL(ToLocal, JSObject, Object)
MAKE_TO_LOCAL(ToLocal, JSArray, Array) MAKE_TO_LOCAL(ToLocal, JSArray, Array)
MAKE_TO_LOCAL(ToLocal, Proxy, External) MAKE_TO_LOCAL(ToLocal, Proxy, External)
@ -297,6 +302,7 @@ MAKE_OPEN_HANDLE(ObjectTemplate, ObjectTemplateInfo)
MAKE_OPEN_HANDLE(Signature, SignatureInfo) MAKE_OPEN_HANDLE(Signature, SignatureInfo)
MAKE_OPEN_HANDLE(TypeSwitch, TypeSwitchInfo) MAKE_OPEN_HANDLE(TypeSwitch, TypeSwitchInfo)
MAKE_OPEN_HANDLE(Data, Object) MAKE_OPEN_HANDLE(Data, Object)
MAKE_OPEN_HANDLE(RegExp, JSRegExp)
MAKE_OPEN_HANDLE(Object, JSObject) MAKE_OPEN_HANDLE(Object, JSObject)
MAKE_OPEN_HANDLE(Array, JSArray) MAKE_OPEN_HANDLE(Array, JSArray)
MAKE_OPEN_HANDLE(String, String) 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); __ orr(r2, r1, r0);
__ tst(r2, Operand(kSmiTagMask)); __ tst(r2, Operand(kSmiTagMask));
__ b(ne, &not_two_smis); __ b(ne, &not_two_smis);
__ sub(r0, r1, r0); __ sub(r0, r1, r0, SetCC);
__ b(vc, &smi_done); __ b(vc, &smi_done);
// Correct the sign in case of overflow. // Correct the sign in case of overflow.
__ rsb(r0, r0, Operand(0, RelocInfo::NONE)); __ 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. // Adjust for function-level loop nesting.
ASSERT_EQ(0, loop_nesting_); ASSERT_EQ(0, loop_nesting_);
loop_nesting_ = info->loop_nesting(); loop_nesting_ = info->is_in_loop() ? 1 : 0;
{ {
CodeGenState state(this); CodeGenState state(this);
@ -339,7 +339,7 @@ void CodeGenerator::Generate(CompilationInfo* info) {
} }
// Adjust for function-level loop nesting. // Adjust for function-level loop nesting.
ASSERT(loop_nesting_ == info->loop_nesting()); ASSERT(loop_nesting_ == info->is_in_loop()? 1 : 0);
loop_nesting_ = 0; loop_nesting_ = 0;
// Code generation state must be reset. // Code generation state must be reset.
@ -3132,9 +3132,9 @@ void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
// Build the function info and instantiate it. // Build the function info and instantiate it.
Handle<SharedFunctionInfo> function_info = Handle<SharedFunctionInfo> function_info =
Compiler::BuildFunctionInfo(node, script(), this); Compiler::BuildFunctionInfo(node, script());
// Check for stack-overflow exception. if (function_info.is_null()) {
if (HasStackOverflow()) { SetStackOverflow();
ASSERT(frame_->height() == original_height); ASSERT(frame_->height() == original_height);
return; return;
} }

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

@ -207,9 +207,7 @@ enum NopMarkerTypes {
class CodeGenerator: public AstVisitor { class CodeGenerator: public AstVisitor {
public: public:
// Takes a function literal, generates code for it. This function should only static bool MakeCode(CompilationInfo* info);
// be called by compiler.cc.
static Handle<Code> MakeCode(CompilationInfo* info);
// Printing of AST, etc. as requested by flags. // Printing of AST, etc. as requested by flags.
static void MakeCodePrologue(CompilationInfo* info); static void MakeCodePrologue(CompilationInfo* info);
@ -449,9 +447,6 @@ class CodeGenerator: public AstVisitor {
void Branch(bool if_true, JumpTarget* target); void Branch(bool if_true, JumpTarget* target);
void CheckStack(); void CheckStack();
static InlineFunctionGenerator FindInlineFunctionGenerator(
Runtime::FunctionId function_id);
bool CheckForInlineRuntimeCall(CallRuntime* node); bool CheckForInlineRuntimeCall(CallRuntime* node);
static Handle<Code> ComputeLazyCompile(int argc); 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()); SetFunctionPosition(function());
Comment cmnt(masm_, "[ function compiled by full code generator"); 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(); int locals_count = scope()->num_stack_slots();
__ Push(lr, fp, cp, r1); __ Push(lr, fp, cp, r1);

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

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

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

@ -38,7 +38,7 @@
#include "allocation.h" #include "allocation.h"
#if defined(__arm__) #if defined(__arm__) && !defined(USE_SIMULATOR)
// When running without a simulator we call the entry directly. // When running without a simulator we call the entry directly.
#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \ #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) 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 // When running with the simulator transition into simulated execution at this
// point. // 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_ #endif // V8_ARM_SIMULATOR_ARM_H_

5
deps/v8/src/ast.h

@ -1436,6 +1436,11 @@ class FunctionLiteral: public Expression {
bool AllowsLazyCompilation(); bool AllowsLazyCompilation();
Handle<String> debug_name() const {
if (name_->length() > 0) return name_;
return inferred_name();
}
Handle<String> inferred_name() const { return inferred_name_; } Handle<String> inferred_name() const { return inferred_name_; }
void set_inferred_name(Handle<String> inferred_name) { void set_inferred_name(Handle<String> inferred_name) {
inferred_name_ = 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 v8 {
namespace internal { namespace internal {
struct CachedPower { void GetCachedPowerForBinaryExponentRange(int min_exponent,
uint64_t significand; int max_exponent,
int16_t binary_exponent; DiyFp* power,
int16_t decimal_exponent; int* 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
} } // namespace v8::internal } } // namespace v8::internal

41
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 // Generate the code. Compile the AST and assemble all the pieces into a
// all the pieces into a Code object. This function is only to be called by // Code object.
// the compiler.cc code. bool CodeGenerator::MakeCode(CompilationInfo* info) {
Handle<Code> CodeGenerator::MakeCode(CompilationInfo* info) {
Handle<Script> script = info->script(); Handle<Script> script = info->script();
if (!script->IsUndefined() && !script->source()->IsUndefined()) { if (!script->IsUndefined() && !script->source()->IsUndefined()) {
int len = String::cast(script->source())->length(); int len = String::cast(script->source())->length();
@ -224,12 +223,14 @@ Handle<Code> CodeGenerator::MakeCode(CompilationInfo* info) {
cgen.Generate(info); cgen.Generate(info);
if (cgen.HasStackOverflow()) { if (cgen.HasStackOverflow()) {
ASSERT(!Top::has_pending_exception()); 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); 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 { } else {
Handle<SharedFunctionInfo> function = Handle<SharedFunctionInfo> function =
Compiler::BuildFunctionInfo(node->fun(), script(), this); Compiler::BuildFunctionInfo(node->fun(), script());
// Check for stack-overflow exception. // Check for stack-overflow exception.
if (HasStackOverflow()) return; if (function.is_null()) {
SetStackOverflow();
return;
}
array->set(j++, *function); array->set(j++, *function);
} }
} }
@ -357,25 +361,20 @@ const CodeGenerator::InlineFunctionGenerator
#undef INLINE_FUNCTION_GENERATOR_ADDRESS #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) { bool CodeGenerator::CheckForInlineRuntimeCall(CallRuntime* node) {
ZoneList<Expression*>* args = node->arguments(); ZoneList<Expression*>* args = node->arguments();
Handle<String> name = node->name(); Handle<String> name = node->name();
Runtime::Function* function = node->function(); Runtime::Function* function = node->function();
if (function != NULL && function->intrinsic_type == Runtime::INLINE) { if (function != NULL && function->intrinsic_type == Runtime::INLINE) {
InlineFunctionGenerator generator = int lookup_index = static_cast<int>(function->function_id) -
FindInlineFunctionGenerator(function->function_id); static_cast<int>(Runtime::kFirstInlineFunction);
if (generator != NULL) { ASSERT(lookup_index >= 0);
((*this).*(generator))(args); ASSERT(static_cast<size_t>(lookup_index) <
ARRAY_SIZE(kInlineFunctionGenerators));
InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index];
(this->*generator)(args);
return true; return true;
} }
}
return false; return false;
} }

1
deps/v8/src/codegen.h

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

380
deps/v8/src/compiler.cc

@ -45,6 +45,40 @@
namespace v8 { namespace v8 {
namespace internal { 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 // 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 // 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 // --always-full-compiler is specified or debugging is active the full
@ -58,47 +92,20 @@ static bool AlwaysFullCompiler() {
} }
static Handle<Code> MakeCode(Handle<Context> context, CompilationInfo* info) { static bool MakeCode(CompilationInfo* info) {
FunctionLiteral* function = info->function(); // Precondition: code has been parsed. Postcondition: the code field in
ASSERT(function != NULL); // the compilation info is set if compilation succeeded.
// Rewrite the AST by introducing .result assignments where needed. ASSERT(info->function() != NULL);
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();
}
if (Rewriter::Rewrite(info) &&
Scope::Analyze(info) &&
Rewriter::Analyze(info)) {
// Generate code and return it. Code generator selection is governed by // Generate code and return it. Code generator selection is governed by
// which backends are enabled and whether the function is considered // which backends are enabled and whether the function is considered
// run-once code or not: // run-once code or not.
// //
// --full-compiler enables the dedicated backend for code we expect to be // --full-compiler enables the dedicated backend for code we expect to
// run once // be run once
// //
// The normal choice of backend can be overridden with the flags // The normal choice of backend can be overridden with the flags
// --always-full-compiler. // --always-full-compiler.
@ -106,55 +113,53 @@ static Handle<Code> MakeCode(Handle<Context> context, CompilationInfo* info) {
bool is_run_once = (shared.is_null()) bool is_run_once = (shared.is_null())
? info->scope()->is_global_scope() ? info->scope()->is_global_scope()
: (shared->is_toplevel() || shared->try_full_codegen()); : (shared->is_toplevel() || shared->try_full_codegen());
bool use_full = FLAG_full_compiler && !function->contains_loops(); bool can_use_full =
if (AlwaysFullCompiler() || (use_full && is_run_once)) { FLAG_full_compiler && !info->function()->contains_loops();
if (AlwaysFullCompiler() || (is_run_once && can_use_full)) {
return FullCodeGenerator::MakeCode(info); return FullCodeGenerator::MakeCode(info);
} else {
AssignedVariablesAnalyzer ava;
return ava.Analyze(info) && CodeGenerator::MakeCode(info);
}
} }
AssignedVariablesAnalyzer ava(function); return false;
if (!ava.Analyze()) return Handle<Code>::null();
return CodeGenerator::MakeCode(info);
} }
#ifdef ENABLE_DEBUGGER_SUPPORT #ifdef ENABLE_DEBUGGER_SUPPORT
Handle<Code> MakeCodeForLiveEdit(CompilationInfo* info) { bool Compiler::MakeCodeForLiveEdit(CompilationInfo* info) {
Handle<Context> context = Handle<Context>::null(); // Precondition: code has been parsed. Postcondition: the code field in
Handle<Code> code = MakeCode(context, info); // the compilation info is set if compilation succeeded.
bool succeeded = MakeCode(info);
if (!info->shared_info().is_null()) { if (!info->shared_info().is_null()) {
Handle<SerializedScopeInfo> scope_info = Handle<SerializedScopeInfo> scope_info =
SerializedScopeInfo::Create(info->scope()); SerializedScopeInfo::Create(info->scope());
info->shared_info()->set_scope_info(*scope_info); info->shared_info()->set_scope_info(*scope_info);
} }
return code; return succeeded;
} }
#endif #endif
static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global, static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info) {
bool is_eval,
Compiler::ValidationState validate,
Handle<Script> script,
Handle<Context> context,
v8::Extension* extension,
ScriptDataImpl* pre_data) {
CompilationZoneScope zone_scope(DELETE_ON_EXIT); CompilationZoneScope zone_scope(DELETE_ON_EXIT);
PostponeInterruptsScope postpone; PostponeInterruptsScope postpone;
ASSERT(!i::Top::global_context().is_null()); ASSERT(!i::Top::global_context().is_null());
Handle<Script> script = info->script();
script->set_context_data((*i::Top::global_context())->data()); script->set_context_data((*i::Top::global_context())->data());
bool is_json = (validate == Compiler::VALIDATE_JSON);
#ifdef ENABLE_DEBUGGER_SUPPORT #ifdef ENABLE_DEBUGGER_SUPPORT
if (is_eval || is_json) { if (info->is_eval() || info->is_json()) {
Script::CompilationType compilation_type = is_json Script::CompilationType compilation_type = info->is_json()
? Script::COMPILATION_TYPE_JSON ? Script::COMPILATION_TYPE_JSON
: Script::COMPILATION_TYPE_EVAL; : Script::COMPILATION_TYPE_EVAL;
script->set_compilation_type(Smi::FromInt(compilation_type)); script->set_compilation_type(Smi::FromInt(compilation_type));
// For eval scripts add information on the function from which eval was // For eval scripts add information on the function from which eval was
// called. // called.
if (is_eval) { if (info->is_eval()) {
StackTraceFrameIterator it; StackTraceFrameIterator it;
if (!it.done()) { if (!it.done()) {
script->set_eval_from_shared( script->set_eval_from_shared(
@ -171,54 +176,47 @@ static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global,
#endif #endif
// Only allow non-global compiles for eval. // Only allow non-global compiles for eval.
ASSERT(is_eval || is_global); ASSERT(info->is_eval() || info->is_global());
// Build AST. if (!Parser::Parse(info)) return Handle<SharedFunctionInfo>::null();
EagerCompilationInfo info(script, is_eval);
FunctionLiteral* lit =
Parser::MakeAST(is_global, script, extension, pre_data, is_json);
// Check for parse errors.
if (lit == NULL) {
ASSERT(Top::has_pending_exception());
return Handle<SharedFunctionInfo>::null();
}
info.set_function(lit);
// Measure how long it takes to do the compilation; only take the // Measure how long it takes to do the compilation; only take the
// rest of the function into account to avoid overlap with the // rest of the function into account to avoid overlap with the
// parsing statistics. // parsing statistics.
HistogramTimer* rate = is_eval HistogramTimer* rate = info->is_eval()
? &Counters::compile_eval ? &Counters::compile_eval
: &Counters::compile; : &Counters::compile;
HistogramTimerScope timer(rate); HistogramTimerScope timer(rate);
// Compile the code. // Compile the code.
FunctionLiteral* lit = info->function();
LiveEditFunctionTracker live_edit_tracker(lit); LiveEditFunctionTracker live_edit_tracker(lit);
Handle<Code> code = MakeCode(context, &info); if (!MakeCode(info)) {
// Check for stack-overflow exceptions.
if (code.is_null()) {
Top::StackOverflow(); Top::StackOverflow();
return Handle<SharedFunctionInfo>::null(); return Handle<SharedFunctionInfo>::null();
} }
ASSERT(!info->code().is_null());
if (script->name()->IsString()) { if (script->name()->IsString()) {
PROFILE(CodeCreateEvent( PROFILE(CodeCreateEvent(
is_eval ? Logger::EVAL_TAG : info->is_eval()
Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script), ? Logger::EVAL_TAG
*code, String::cast(script->name()))); : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
*info->code(),
String::cast(script->name())));
OPROFILE(CreateNativeCodeRegion(String::cast(script->name()), OPROFILE(CreateNativeCodeRegion(String::cast(script->name()),
code->instruction_start(), info->code()->instruction_start(),
code->instruction_size())); info->code()->instruction_size()));
} else { } else {
PROFILE(CodeCreateEvent( PROFILE(CodeCreateEvent(
is_eval ? Logger::EVAL_TAG : info->is_eval()
Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script), ? Logger::EVAL_TAG
*code, "")); : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
OPROFILE(CreateNativeCodeRegion(is_eval ? "Eval" : "Script", *info->code(),
code->instruction_start(), ""));
code->instruction_size())); OPROFILE(CreateNativeCodeRegion(info->is_eval() ? "Eval" : "Script",
info->code()->instruction_start(),
info->code()->instruction_size()));
} }
// Allocate function. // Allocate function.
@ -226,8 +224,8 @@ static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global,
Factory::NewSharedFunctionInfo( Factory::NewSharedFunctionInfo(
lit->name(), lit->name(),
lit->materialized_literal_count(), lit->materialized_literal_count(),
code, info->code(),
SerializedScopeInfo::Create(info.scope())); SerializedScopeInfo::Create(info->scope()));
ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position()); ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
Compiler::SetFunctionInfo(result, lit, true, script); Compiler::SetFunctionInfo(result, lit, true, script);
@ -303,13 +301,11 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
: *script_data); : *script_data);
// Compile the function and add it to the cache. // Compile the function and add it to the cache.
result = MakeFunctionInfo(true, CompilationInfo info(script);
false, info.MarkAsGlobal();
DONT_VALIDATE_JSON, info.SetExtension(extension);
script, info.SetPreParseData(pre_data);
Handle<Context>::null(), result = MakeFunctionInfo(&info);
extension,
pre_data);
if (extension == NULL && !result.is_null()) { if (extension == NULL && !result.is_null()) {
CompilationCache::PutScript(source, result); CompilationCache::PutScript(source, result);
} }
@ -329,9 +325,10 @@ Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
Handle<Context> context, Handle<Context> context,
bool is_global, bool is_global,
ValidationState validate) { ValidationState validate) {
// Note that if validation is required then no path through this // Note that if validation is required then no path through this function
// function is allowed to return a value without validating that // is allowed to return a value without validating that the input is legal
// the input is legal json. // json.
bool is_json = (validate == VALIDATE_JSON);
int source_length = source->length(); int source_length = source->length();
Counters::total_eval_size.Increment(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. // The VM is in the COMPILER state until exiting this function.
VMState state(COMPILER); VMState state(COMPILER);
// Do a lookup in the compilation cache; if the entry is not there, // Do a lookup in the compilation cache; if the entry is not there, invoke
// invoke the compiler and add the result to the cache. If we're // the compiler and add the result to the cache. If we're evaluating json
// evaluating json we bypass the cache since we can't be sure a // we bypass the cache since we can't be sure a potential value in the
// potential value in the cache has been validated. // cache has been validated.
Handle<SharedFunctionInfo> result; Handle<SharedFunctionInfo> result;
if (validate == DONT_VALIDATE_JSON) if (!is_json) {
result = CompilationCache::LookupEval(source, context, is_global); result = CompilationCache::LookupEval(source, context, is_global);
}
if (result.is_null()) { if (result.is_null()) {
// Create a script object describing the script to be compiled. // Create a script object describing the script to be compiled.
Handle<Script> script = Factory::NewScript(source); Handle<Script> script = Factory::NewScript(source);
result = MakeFunctionInfo(is_global, CompilationInfo info(script);
true, info.MarkAsEval();
validate, if (is_global) info.MarkAsGlobal();
script, if (is_json) info.MarkAsJson();
context, info.SetCallingContext(context);
NULL, result = MakeFunctionInfo(&info);
NULL); if (!result.is_null() && !is_json) {
if (!result.is_null() && validate != VALIDATE_JSON) { // For json it's unlikely that we'll ever see exactly the same string
// For json it's unlikely that we'll ever see exactly the same // again so we don't use the compilation cache.
// string again so we don't use the compilation cache.
CompilationCache::PutEval(source, context, is_global, result); CompilationCache::PutEval(source, context, is_global, result);
} }
} }
@ -377,61 +374,48 @@ bool Compiler::CompileLazy(CompilationInfo* info) {
PostponeInterruptsScope postpone; PostponeInterruptsScope postpone;
// Compute name, source code and script data.
Handle<SharedFunctionInfo> shared = info->shared_info(); Handle<SharedFunctionInfo> shared = info->shared_info();
int compiled_size = shared->end_position() - shared->start_position(); int compiled_size = shared->end_position() - shared->start_position();
Counters::total_compile_size.Increment(compiled_size); Counters::total_compile_size.Increment(compiled_size);
// Generate the AST for the lazily compiled function. The AST may be // Generate the AST for the lazily compiled function.
// NULL in case of parser stack overflow. if (Parser::Parse(info)) {
FunctionLiteral* lit = Parser::MakeLazyAST(shared); // 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
// Check for parse errors. // parsing statistics.
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); HistogramTimerScope timer(&Counters::compile_lazy);
// Compile the code. // Compile the code.
Handle<Code> code = MakeCode(Handle<Context>::null(), info); if (!MakeCode(info)) {
// Check for stack-overflow exception.
if (code.is_null()) {
Top::StackOverflow(); Top::StackOverflow();
return false; } else {
} ASSERT(!info->code().is_null());
RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG,
Handle<String>(String::cast(shared->name())), Handle<String>(shared->DebugName()),
Handle<String>(shared->inferred_name()),
shared->start_position(), shared->start_position(),
info->script(), info);
code);
// Update the shared function info with the compiled code and the
// Update the shared function info with the compiled code and the scope info. // scope info. Please note, that the order of the sharedfunction
// Please note, that the order of the sharedfunction initialization is // initialization is important since SerializedScopeInfo::Create might
// important since SerializedScopeInfo::Create might trigger a GC, causing // trigger a GC, causing the ASSERT below to be invalid if the code
// the ASSERT below to be invalid if the code was flushed. By setting the code // was flushed. By setting the code object last we avoid this.
// object last we avoid this.
Handle<SerializedScopeInfo> scope_info = Handle<SerializedScopeInfo> scope_info =
SerializedScopeInfo::Create(info->scope()); SerializedScopeInfo::Create(info->scope());
shared->set_scope_info(*scope_info); shared->set_scope_info(*scope_info);
shared->set_code(*code); shared->set_code(*info->code());
if (!info->closure().is_null()) { if (!info->closure().is_null()) {
info->closure()->set_code(*code); info->closure()->set_code(*info->code());
} }
// Set the expected number of properties for instances. // Set the expected number of properties for instances.
SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count()); FunctionLiteral* lit = info->function();
SetExpectedNofPropertiesFromEstimate(shared,
lit->expected_property_count());
// Set the optimication hints after performing lazy compilation, as these are // Set the optimization hints after performing lazy compilation, as
// not set when the function is set up as a lazily compiled function. // these are not set when the function is set up as a lazily compiled
// function.
shared->SetThisPropertyAssignmentsInfo( shared->SetThisPropertyAssignmentsInfo(
lit->has_only_simple_this_property_assignments(), lit->has_only_simple_this_property_assignments(),
*lit->this_property_assignments()); *lit->this_property_assignments());
@ -439,71 +423,73 @@ bool Compiler::CompileLazy(CompilationInfo* info) {
// Check the function has compiled code. // Check the function has compiled code.
ASSERT(shared->is_compiled()); ASSERT(shared->is_compiled());
shared->set_code_age(0); shared->set_code_age(0);
ASSERT(!info->code().is_null());
return true; return true;
}
}
ASSERT(info->code().is_null());
return false;
} }
Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal, Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
Handle<Script> script, Handle<Script> script) {
AstVisitor* caller) {
LiveEditFunctionTracker live_edit_tracker(literal);
#ifdef DEBUG #ifdef DEBUG
// We should not try to compile the same function literal more than // We should not try to compile the same function literal more than
// once. // once.
literal->mark_as_compiled(); literal->mark_as_compiled();
#endif #endif
// Determine if the function can be lazily compiled. This is // Precondition: code has been parsed and scopes have been analyzed.
// necessary to allow some of our builtin JS files to be lazily CompilationInfo info(script);
// compiled. These builtins cannot be handled lazily by the parser, info.SetFunction(literal);
// since we have to know if a function uses the special natives info.SetScope(literal->scope());
// syntax, which is something the parser records.
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() && bool allow_lazy = literal->AllowsLazyCompilation() &&
!LiveEditFunctionTracker::IsActive(); !LiveEditFunctionTracker::IsActive();
Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty()); Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
// Generate code // Generate code
Handle<Code> code;
if (FLAG_lazy && allow_lazy) { if (FLAG_lazy && allow_lazy) {
code = Handle<Code>(Builtins::builtin(Builtins::LazyCompile)); Handle<Code> code(Builtins::builtin(Builtins::LazyCompile));
info.SetCode(code);
} else { } 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 // Generate code and return it. The way that the compilation mode
// is controlled by the command-line flags is described in // is controlled by the command-line flags is described in
// the static helper function MakeCode. // 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 is_run_once = literal->try_full_codegen();
bool use_full = FLAG_full_compiler && !literal->contains_loops(); bool use_full = FLAG_full_compiler && !literal->contains_loops();
if (AlwaysFullCompiler() || (use_full && is_run_once)) { if (AlwaysFullCompiler() || (use_full && is_run_once)) {
code = FullCodeGenerator::MakeCode(&info); if (!FullCodeGenerator::MakeCode(&info)) {
return Handle<SharedFunctionInfo>::null();
}
} else { } else {
// We fall back to the classic V8 code generator. // We fall back to the classic V8 code generator.
AssignedVariablesAnalyzer ava(literal); AssignedVariablesAnalyzer ava;
if (!ava.Analyze()) return Handle<SharedFunctionInfo>::null(); if (!ava.Analyze(&info)) return Handle<SharedFunctionInfo>::null();
code = CodeGenerator::MakeCode(&info); if (!CodeGenerator::MakeCode(&info)) {
}
// Check for stack-overflow exception.
if (code.is_null()) {
caller->SetStackOverflow();
return Handle<SharedFunctionInfo>::null(); return Handle<SharedFunctionInfo>::null();
} }
}
// Function compilation complete. // Function compilation complete.
RecordFunctionCompilation(Logger::FUNCTION_TAG, RecordFunctionCompilation(Logger::FUNCTION_TAG,
literal->name(), literal->debug_name(),
literal->inferred_name(),
literal->start_position(), literal->start_position(),
script, &info);
code);
scope_info = SerializedScopeInfo::Create(info.scope()); scope_info = SerializedScopeInfo::Create(info.scope());
} }
@ -511,7 +497,7 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
Handle<SharedFunctionInfo> result = Handle<SharedFunctionInfo> result =
Factory::NewSharedFunctionInfo(literal->name(), Factory::NewSharedFunctionInfo(literal->name(),
literal->materialized_literal_count(), literal->materialized_literal_count(),
code, info.code(),
scope_info); scope_info);
SetFunctionInfo(result, literal, false, script); SetFunctionInfo(result, literal, false, script);
@ -551,32 +537,34 @@ void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag, void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag,
Handle<String> name, Handle<String> name,
Handle<String> inferred_name,
int start_position, int start_position,
Handle<Script> script, CompilationInfo* info) {
Handle<Code> code) { // Log the code generation. If source information is available include
// Log the code generation. If source information is available // script name and line number. Check explicitly whether logging is
// include script name and line number. Check explicitly whether // enabled as finding the line number is not free.
// logging is enabled as finding the line number is not free. if (Logger::is_logging() ||
if (Logger::is_logging() OProfileAgent::is_enabled() ||
|| OProfileAgent::is_enabled() CpuProfiler::is_profiling()) {
|| CpuProfiler::is_profiling()) { Handle<Script> script = info->script();
Handle<String> func_name(name->length() > 0 ? *name : *inferred_name); Handle<Code> code = info->code();
if (script->name()->IsString()) { if (script->name()->IsString()) {
int line_num = GetScriptLineNumber(script, start_position) + 1; int line_num = GetScriptLineNumber(script, start_position) + 1;
USE(line_num); USE(line_num);
PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script), PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
*code, *func_name, *code,
String::cast(script->name()), line_num)); *name,
OPROFILE(CreateNativeCodeRegion(*func_name, String::cast(script->name()),
line_num));
OPROFILE(CreateNativeCodeRegion(*name,
String::cast(script->name()), String::cast(script->name()),
line_num, line_num,
code->instruction_start(), code->instruction_start(),
code->instruction_size())); code->instruction_size()));
} else { } else {
PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script), PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
*code, *func_name)); *code,
OPROFILE(CreateNativeCodeRegion(*func_name, *name));
OPROFILE(CreateNativeCodeRegion(*name,
code->instruction_start(), code->instruction_start(),
code->instruction_size())); 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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -42,109 +42,101 @@ class ScriptDataImpl;
// is constructed based on the resources available at compile-time. // is constructed based on the resources available at compile-time.
class CompilationInfo BASE_EMBEDDED { class CompilationInfo BASE_EMBEDDED {
public: public:
virtual ~CompilationInfo() {} explicit CompilationInfo(Handle<Script> script);
explicit CompilationInfo(Handle<SharedFunctionInfo> shared_info);
// Dispatched behavior. explicit CompilationInfo(Handle<JSFunction> closure);
virtual Handle<SharedFunctionInfo> shared_info() const = 0;
bool is_lazy() const { return (flags_ & IsLazy::mask()) != 0; }
virtual Handle<Script> script() const { bool is_eval() const { return (flags_ & IsEval::mask()) != 0; }
return Handle<Script>(Script::cast(shared_info()->script())); 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);
} }
void MarkAsGlobal() {
virtual Handle<JSFunction> closure() const { ASSERT(!is_lazy());
return Handle<JSFunction>::null(); flags_ |= IsGlobal::encode(true);
} }
void MarkAsJson() {
virtual bool is_eval() const { return false; } ASSERT(!is_lazy());
flags_ |= IsJson::encode(true);
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 MarkAsInLoop() {
// Overridden functions from the base class. ASSERT(is_lazy());
virtual Handle<SharedFunctionInfo> shared_info() const { flags_ |= IsInLoop::encode(true);
return Handle<SharedFunctionInfo>::null();
} }
void SetFunction(FunctionLiteral* literal) {
virtual Handle<Script> script() const { return script_; } ASSERT(function_ == NULL);
function_ = literal;
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 SetScope(Scope* scope) {
// Overridden functions from the base class. ASSERT(scope_ == NULL);
virtual Handle<SharedFunctionInfo> shared_info() const { scope_ = scope;
return shared_info_;
} }
void SetCode(Handle<Code> code) { code_ = code; }
private: void SetExtension(v8::Extension* extension) {
Handle<SharedFunctionInfo> shared_info_; ASSERT(!is_lazy());
}; extension_ = extension;
class LazyFunctionCompilationInfo: public CompilationInfo {
public:
LazyFunctionCompilationInfo(Handle<JSFunction> closure,
int loop_nesting)
: closure_(closure), loop_nesting_(loop_nesting) {
ASSERT(!closure.is_null());
} }
void SetPreParseData(ScriptDataImpl* pre_parse_data) {
// Overridden functions from the base class. ASSERT(!is_lazy());
virtual Handle<SharedFunctionInfo> shared_info() const { pre_parse_data_ = pre_parse_data;
return Handle<SharedFunctionInfo>(closure_->shared());
} }
void SetCallingContext(Handle<Context> context) {
virtual int loop_nesting() const { return loop_nesting_; } ASSERT(is_eval());
calling_context_ = context;
virtual bool has_global_object() const {
return closure_->context()->global() != NULL;
}
virtual GlobalObject* global_object() const {
return closure_->context()->global();
} }
private: 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_; 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 // functions, they will be compiled and allocated as part of the compilation
// of the source code. // of the source code.
// Please note this interface returns shared function infos. // Please note this interface returns shared function infos. This means you
// This means you need to call Factory::NewFunctionFromSharedFunctionInfo // need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
// before you have a real function with a context. // real function with a context.
class Compiler : public AllStatic { class Compiler : public AllStatic {
public: public:
enum ValidationState { VALIDATE_JSON, DONT_VALIDATE_JSON }; enum ValidationState { DONT_VALIDATE_JSON, VALIDATE_JSON };
// All routines return a JSFunction. // All routines return a JSFunction.
// If an error occurs an exception is raised and // If an error occurs an exception is raised and
@ -183,17 +175,14 @@ class Compiler : public AllStatic {
bool is_global, bool is_global,
ValidationState validation); ValidationState validation);
// Compile from function info (used for lazy compilation). Returns // Compile from function info (used for lazy compilation). Returns true on
// true on success and false if the compilation resulted in a stack // success and false if the compilation resulted in a stack overflow.
// overflow.
static bool CompileLazy(CompilationInfo* info); static bool CompileLazy(CompilationInfo* info);
// Compile a shared function info object (the function is possibly // Compile a shared function info object (the function is possibly lazily
// lazily compiled). Called recursively from a backend code // compiled).
// generator 'caller' to build the shared function info.
static Handle<SharedFunctionInfo> BuildFunctionInfo(FunctionLiteral* node, static Handle<SharedFunctionInfo> BuildFunctionInfo(FunctionLiteral* node,
Handle<Script> script, Handle<Script> script);
AstVisitor* caller);
// Set the function info for a newly compiled function. // Set the function info for a newly compiled function.
static void SetFunctionInfo(Handle<SharedFunctionInfo> function_info, static void SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
@ -201,23 +190,18 @@ class Compiler : public AllStatic {
bool is_toplevel, bool is_toplevel,
Handle<Script> script); Handle<Script> script);
#ifdef ENABLE_DEBUGGER_SUPPORT
static bool MakeCodeForLiveEdit(CompilationInfo* info);
#endif
private: private:
static void RecordFunctionCompilation(Logger::LogEventsAndTags tag, static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
Handle<String> name, Handle<String> name,
Handle<String> inferred_name,
int start_position, int start_position,
Handle<Script> script, CompilationInfo* info);
Handle<Code> code);
}; };
#ifdef ENABLE_DEBUGGER_SUPPORT
Handle<Code> MakeCodeForLiveEdit(CompilationInfo* info);
#endif
// During compilation we need a global list of handles to constants // During compilation we need a global list of handles to constants
// for frame elements. When the zone gets deleted, we make sure to // for frame elements. When the zone gets deleted, we make sure to
// clear this list of handles as well. // clear this list of handles as well.

68
deps/v8/src/conversions.cc

@ -34,6 +34,7 @@
#include "dtoa.h" #include "dtoa.h"
#include "factory.h" #include "factory.h"
#include "scanner.h" #include "scanner.h"
#include "strtod.h"
namespace v8 { namespace v8 {
namespace internal { 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. // Maximum number of significant digits in decimal representation.
// The longest possible double in decimal representation is // The longest possible double in decimal representation is
// (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074 // (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); ASSERT(buffer_pos < kBufferSize);
buffer[buffer_pos++] = '\0'; buffer[buffer_pos] = '\0';
return sign ? -gay_strtod(buffer, NULL) : gay_strtod(buffer, NULL); 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 // The following code causes accumulating rounding error for numbers greater
@ -462,7 +462,6 @@ static double InternalStringToDouble(Iterator current,
++current; ++current;
if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE; if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE;
} else if (*current == '-') { } else if (*current == '-') {
buffer[buffer_pos++] = '-';
++current; ++current;
if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE; if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE;
sign = true; sign = true;
@ -478,8 +477,8 @@ static double InternalStringToDouble(Iterator current,
return JUNK_STRING_VALUE; return JUNK_STRING_VALUE;
} }
ASSERT(buffer_pos == 0 || buffer[0] == '-'); ASSERT(buffer_pos == 0);
return buffer_pos > 0 ? -V8_INFINITY : V8_INFINITY; return sign ? -V8_INFINITY : V8_INFINITY;
} }
bool leading_zero = false; bool leading_zero = false;
@ -496,7 +495,6 @@ static double InternalStringToDouble(Iterator current,
return JUNK_STRING_VALUE; // "0x". return JUNK_STRING_VALUE; // "0x".
} }
bool sign = (buffer_pos > 0 && buffer[0] == '-');
return InternalStringToIntDouble<4>(current, return InternalStringToIntDouble<4>(current,
end, end,
sign, sign,
@ -533,6 +531,9 @@ static double InternalStringToDouble(Iterator current,
} }
if (*current == '.') { if (*current == '.') {
if (octal && !allow_trailing_junk) return JUNK_STRING_VALUE;
if (octal) goto parsing_done;
++current; ++current;
if (current == end) { if (current == end) {
if (significant_digits == 0 && !leading_zero) { if (significant_digits == 0 && !leading_zero) {
@ -553,16 +554,16 @@ static double InternalStringToDouble(Iterator current,
} }
} }
ASSERT(buffer_pos < kBufferSize); // We don't emit a '.', but adjust the exponent instead.
buffer[buffer_pos++] = '.';
fractional_part = true; fractional_part = true;
// There is the fractional part. // There is a fractional part.
while (*current >= '0' && *current <= '9') { while (*current >= '0' && *current <= '9') {
if (significant_digits < kMaxSignificantDigits) { if (significant_digits < kMaxSignificantDigits) {
ASSERT(buffer_pos < kBufferSize); ASSERT(buffer_pos < kBufferSize);
buffer[buffer_pos++] = static_cast<char>(*current); buffer[buffer_pos++] = static_cast<char>(*current);
significant_digits++; significant_digits++;
exponent--;
} else { } else {
// Ignore insignificant digits in the fractional part. // Ignore insignificant digits in the fractional part.
nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'; nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
@ -638,60 +639,25 @@ static double InternalStringToDouble(Iterator current,
exponent += insignificant_digits; exponent += insignificant_digits;
if (octal) { if (octal) {
bool sign = buffer[0] == '-'; return InternalStringToIntDouble<3>(buffer,
int start_pos = (sign ? 1 : 0);
return InternalStringToIntDouble<3>(buffer + start_pos,
buffer + buffer_pos, buffer + buffer_pos,
sign, sign,
allow_trailing_junk); allow_trailing_junk);
} }
if (nonzero_digit_dropped) { if (nonzero_digit_dropped) {
if (insignificant_digits) buffer[buffer_pos++] = '.';
buffer[buffer_pos++] = '1'; buffer[buffer_pos++] = '1';
} exponent--;
// 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);
} }
ASSERT(buffer_pos < kBufferSize); ASSERT(buffer_pos < kBufferSize);
buffer[buffer_pos] = '\0'; 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) { double StringToDouble(String* str, int flags, double empty_string_val) {
StringShape shape(str); StringShape shape(str);
if (shape.IsSequentialAscii()) { if (shape.IsSequentialAscii()) {

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

@ -50,12 +50,13 @@ void BitVector::Print() {
#endif #endif
bool AssignedVariablesAnalyzer::Analyze() { bool AssignedVariablesAnalyzer::Analyze(CompilationInfo* info) {
Scope* scope = fun_->scope(); info_ = info;
Scope* scope = info->scope();
int variables = scope->num_parameters() + scope->num_stack_slots(); int variables = scope->num_parameters() + scope->num_stack_slots();
if (variables == 0) return true; if (variables == 0) return true;
av_.ExpandTo(variables); av_.ExpandTo(variables);
VisitStatements(fun_->body()); VisitStatements(info->function()->body());
return !HasStackOverflow(); return !HasStackOverflow();
} }
@ -129,7 +130,7 @@ int AssignedVariablesAnalyzer::BitIndex(Variable* var) {
if (slot->type() == Slot::PARAMETER) { if (slot->type() == Slot::PARAMETER) {
return slot->index(); return slot->index();
} else { } 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. // is guaranteed to be a smi.
class AssignedVariablesAnalyzer : public AstVisitor { class AssignedVariablesAnalyzer : public AstVisitor {
public: public:
explicit AssignedVariablesAnalyzer(FunctionLiteral* fun) : fun_(fun) { } explicit AssignedVariablesAnalyzer() : info_(NULL) { }
bool Analyze(); bool Analyze(CompilationInfo* info);
private: private:
Variable* FindSmiLoopVariable(ForStatement* stmt); Variable* FindSmiLoopVariable(ForStatement* stmt);
@ -219,7 +219,7 @@ class AssignedVariablesAnalyzer : public AstVisitor {
AST_NODE_LIST(DECLARE_VISIT) AST_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT #undef DECLARE_VISIT
FunctionLiteral* fun_; CompilationInfo* info_;
// Accumulator for assigned variables set. // Accumulator for assigned variables set.
BitVector av_; BitVector av_;

13
deps/v8/src/execution.cc

@ -473,6 +473,19 @@ Handle<Object> Execution::NewDate(double time, bool* exc) {
#undef RETURN_NATIVE_CALL #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) { Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) {
int int_index = static_cast<int>(index); int int_index = static_cast<int>(index);
if (int_index < 0 || int_index >= string->length()) { 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'. // Create a new date object from 'time'.
static Handle<Object> NewDate(double time, bool* exc); 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) // Used to implement [] notation on strings (calls JS code)
static Handle<Object> CharAt(Handle<String> str, uint32_t index); 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()); ASSERT(boundary_plus.e() == w.e());
DiyFp ten_mk; // Cached power of ten: 10^-k DiyFp ten_mk; // Cached power of ten: 10^-k
int mk; // -k int mk; // -k
GetCachedPower(w.e() + DiyFp::kSignificandSize, kMinimalTargetExponent, int ten_mk_minimal_binary_exponent =
kMaximalTargetExponent, &mk, &ten_mk); 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() + ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() +
DiyFp::kSignificandSize) && DiyFp::kSignificandSize) &&
(kMaximalTargetExponent >= w.e() + ten_mk.e() + (kMaximalTargetExponent >= w.e() + ten_mk.e() +
@ -662,8 +667,13 @@ static bool Grisu3Counted(double v,
DiyFp w = Double(v).AsNormalizedDiyFp(); DiyFp w = Double(v).AsNormalizedDiyFp();
DiyFp ten_mk; // Cached power of ten: 10^-k DiyFp ten_mk; // Cached power of ten: 10^-k
int mk; // -k int mk; // -k
GetCachedPower(w.e() + DiyFp::kSignificandSize, kMinimalTargetExponent, int ten_mk_minimal_binary_exponent =
kMaximalTargetExponent, &mk, &ten_mk); 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() + ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() +
DiyFp::kSignificandSize) && DiyFp::kSignificandSize) &&
(kMaximalTargetExponent >= w.e() + ten_mk.e() + (kMaximalTargetExponent >= w.e() + ten_mk.e() +

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

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

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

@ -74,7 +74,7 @@ class FullCodeGenerator: public AstVisitor {
context_(NULL) { context_(NULL) {
} }
static Handle<Code> MakeCode(CompilationInfo* info); static bool MakeCode(CompilationInfo* info);
void Generate(CompilationInfo* info); void Generate(CompilationInfo* info);
@ -604,6 +604,15 @@ class FullCodeGenerator: public AstVisitor {
false_label_(false_label), false_label_(false_label),
fall_through_(fall_through) { } 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(bool flag) const;
virtual void Plug(Register reg) const; virtual void Plug(Register reg) const;
virtual void Plug(Label* materialize_true, Label* materialize_false) 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, Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object,
KeyCollectionType type) { KeyCollectionType type) {
USE(ContainsOnlyValidKeys);
Handle<FixedArray> content = Factory::empty_fixed_array(); Handle<FixedArray> content = Factory::empty_fixed_array();
Handle<JSObject> arguments_boilerplate = Handle<JSObject> arguments_boilerplate =
Handle<JSObject>( Handle<JSObject>(
@ -664,6 +675,7 @@ Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object,
Factory::NewFixedArray(current->NumberOfEnumElements()); Factory::NewFixedArray(current->NumberOfEnumElements());
current->GetEnumElementKeys(*element_keys); current->GetEnumElementKeys(*element_keys);
content = UnionOfKeys(content, element_keys); content = UnionOfKeys(content, element_keys);
ASSERT(ContainsOnlyValidKeys(content));
// Add the element keys from the interceptor. // Add the element keys from the interceptor.
if (current->HasIndexedInterceptor()) { if (current->HasIndexedInterceptor()) {
@ -671,6 +683,7 @@ Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object,
GetKeysForIndexedInterceptor(object, current); GetKeysForIndexedInterceptor(object, current);
if (!result.IsEmpty()) if (!result.IsEmpty())
content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result)); content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result));
ASSERT(ContainsOnlyValidKeys(content));
} }
// We can cache the computed property keys if access checks are // 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. // Compute the property keys and cache them if possible.
content = content =
UnionOfKeys(content, GetEnumPropertyKeys(current, cache_enum_keys)); UnionOfKeys(content, GetEnumPropertyKeys(current, cache_enum_keys));
ASSERT(ContainsOnlyValidKeys(content));
// Add the property keys from the interceptor. // Add the property keys from the interceptor.
if (current->HasNamedInterceptor()) { if (current->HasNamedInterceptor()) {
@ -699,6 +713,7 @@ Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object,
GetKeysForNamedInterceptor(object, current); GetKeysForNamedInterceptor(object, current);
if (!result.IsEmpty()) if (!result.IsEmpty())
content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result)); content = AddKeysFromJSArray(content, v8::Utils::OpenHandle(*result));
ASSERT(ContainsOnlyValidKeys(content));
} }
// If we only want local properties we bail out after the first // 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, bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
ClearExceptionFlag flag) { ClearExceptionFlag flag) {
LazySharedCompilationInfo info(shared); CompilationInfo info(shared);
return CompileLazyHelper(&info, flag); return CompileLazyHelper(&info, flag);
} }
@ -788,11 +803,13 @@ bool CompileLazy(Handle<JSFunction> function,
ClearExceptionFlag flag) { ClearExceptionFlag flag) {
if (function->shared()->is_compiled()) { if (function->shared()->is_compiled()) {
function->set_code(function->shared()->code()); function->set_code(function->shared()->code());
PROFILE(FunctionCreateEvent(*function));
function->shared()->set_code_age(0); function->shared()->set_code_age(0);
return true; return true;
} else { } else {
LazyFunctionCompilationInfo info(function, 0); CompilationInfo info(function);
bool result = CompileLazyHelper(&info, flag); bool result = CompileLazyHelper(&info, flag);
ASSERT(!result || function->is_compiled());
PROFILE(FunctionCreateEvent(*function)); PROFILE(FunctionCreateEvent(*function));
return result; return result;
} }
@ -803,11 +820,14 @@ bool CompileLazyInLoop(Handle<JSFunction> function,
ClearExceptionFlag flag) { ClearExceptionFlag flag) {
if (function->shared()->is_compiled()) { if (function->shared()->is_compiled()) {
function->set_code(function->shared()->code()); function->set_code(function->shared()->code());
PROFILE(FunctionCreateEvent(*function));
function->shared()->set_code_age(0); function->shared()->set_code_age(0);
return true; return true;
} else { } else {
LazyFunctionCompilationInfo info(function, 1); CompilationInfo info(function);
info.MarkAsInLoop();
bool result = CompileLazyHelper(&info, flag); bool result = CompileLazyHelper(&info, flag);
ASSERT(!result || function->is_compiled());
PROFILE(FunctionCreateEvent(*function)); PROFILE(FunctionCreateEvent(*function));
return result; 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. // Adjust for function-level loop nesting.
ASSERT_EQ(0, 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); 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); CodeGenState state(this);
// Entry: // Entry:
@ -203,6 +194,14 @@ void CodeGenerator::Generate(CompilationInfo* info) {
// esi: callee's context // esi: callee's context
allocator_->Initialize(); allocator_->Initialize();
#ifdef DEBUG
if (strlen(FLAG_stop_at) > 0 &&
info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
frame_->SpillAll();
__ int3();
}
#endif
frame_->Enter(); frame_->Enter();
// Allocate space for locals and initialize them. // Allocate space for locals and initialize them.
@ -358,7 +357,7 @@ void CodeGenerator::Generate(CompilationInfo* info) {
} }
// Adjust for function-level loop nesting. // 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; loop_nesting_ = 0;
// Code generation state must be reset. // Code generation state must be reset.
@ -369,7 +368,6 @@ void CodeGenerator::Generate(CompilationInfo* info) {
// Process any deferred code using the register allocator. // Process any deferred code using the register allocator.
if (!HasStackOverflow()) { if (!HasStackOverflow()) {
HistogramTimerScope deferred_timer(&Counters::deferred_code_generation);
JumpTarget::set_compiling_deferred_code(true); JumpTarget::set_compiling_deferred_code(true);
ProcessDeferred(); ProcessDeferred();
JumpTarget::set_compiling_deferred_code(false); JumpTarget::set_compiling_deferred_code(false);
@ -4925,9 +4923,12 @@ void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
ASSERT(!in_safe_int32_mode()); ASSERT(!in_safe_int32_mode());
// Build the function info and instantiate it. // Build the function info and instantiate it.
Handle<SharedFunctionInfo> function_info = Handle<SharedFunctionInfo> function_info =
Compiler::BuildFunctionInfo(node, script(), this); Compiler::BuildFunctionInfo(node, script());
// Check for stack-overflow exception. // Check for stack-overflow exception.
if (HasStackOverflow()) return; if (function_info.is_null()) {
SetStackOverflow();
return;
}
Result result = InstantiateFunction(function_info); Result result = InstantiateFunction(function_info);
frame()->Push(&result); frame()->Push(&result);
} }

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

@ -300,9 +300,7 @@ enum ArgumentsAllocationMode {
class CodeGenerator: public AstVisitor { class CodeGenerator: public AstVisitor {
public: public:
// Takes a function literal, generates code for it. This function should only static bool MakeCode(CompilationInfo* info);
// be called by compiler.cc.
static Handle<Code> MakeCode(CompilationInfo* info);
// Printing of AST, etc. as requested by flags. // Printing of AST, etc. as requested by flags.
static void MakeCodePrologue(CompilationInfo* info); static void MakeCodePrologue(CompilationInfo* info);
@ -626,9 +624,6 @@ class CodeGenerator: public AstVisitor {
void CheckStack(); void CheckStack();
static InlineFunctionGenerator FindInlineFunctionGenerator(
Runtime::FunctionId function_id);
bool CheckForInlineRuntimeCall(CallRuntime* node); bool CheckForInlineRuntimeCall(CallRuntime* node);
void ProcessDeclarations(ZoneList<Declaration*>* declarations); 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()); SetFunctionPosition(function());
Comment cmnt(masm_, "[ function compiled by full code generator"); 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. __ push(ebp); // Caller's frame pointer.
__ mov(ebp, esp); __ mov(ebp, esp);
__ push(esi); // Callee's context. __ push(esi); // Callee's context.

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

@ -47,7 +47,6 @@ Debug.LiveEdit = new function() {
// Forward declaration for minifier. // Forward declaration for minifier.
var FunctionStatus; var FunctionStatus;
// Applies the change to the script. // Applies the change to the script.
// The change is in form of list of chunks encoded in a single array as // 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) // a series of triplets (pos1_start, pos1_end, pos2_end)

44
deps/v8/src/liveedit.cc

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

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

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

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

@ -38,7 +38,7 @@
#include "allocation.h" #include "allocation.h"
#if defined(__mips) #if defined(__mips) && !defined(USE_SIMULATOR)
// When running without a simulator we call the entry directly. // When running without a simulator we call the entry directly.
#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \ #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) 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 // When running with the simulator transition into simulated execution at this
// point. // 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_ #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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -1180,7 +1180,11 @@ String* JSObject::constructor_name() {
if (map()->constructor()->IsJSFunction()) { if (map()->constructor()->IsJSFunction()) {
JSFunction* constructor = JSFunction::cast(map()->constructor()); JSFunction* constructor = JSFunction::cast(map()->constructor());
String* name = String::cast(constructor->shared()->name()); 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". // If the constructor is not present, return "Object".
return Heap::Object_symbol(); return Heap::Object_symbol();
@ -3601,9 +3605,17 @@ Object* FixedArray::AddKeysFromJSArray(JSArray* array) {
Object* FixedArray::UnionOfKeys(FixedArray* other) { Object* FixedArray::UnionOfKeys(FixedArray* other) {
int len0 = length(); 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(); int len1 = other->length();
// Optimize if either is empty. // Optimize if 'other' is empty.
if (len0 == 0) return other; // We cannot optimize if 'this' is empty, as other may have holes
// or non keys.
if (len1 == 0) return this; if (len1 == 0) return this;
// Compute how many elements are not in this. // Compute how many elements are not in this.
@ -3623,14 +3635,18 @@ Object* FixedArray::UnionOfKeys(FixedArray* other) {
FixedArray* result = FixedArray::cast(obj); FixedArray* result = FixedArray::cast(obj);
WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
for (int i = 0; i < len0; i++) { 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. // Fill in the extra keys.
int index = 0; int index = 0;
for (int y = 0; y < len1; y++) { for (int y = 0; y < len1; y++) {
Object* value = other->get(y); Object* value = other->get(y);
if (!value->IsTheHole() && !HasKey(this, value)) { 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++; 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() { bool SharedFunctionInfo::HasSourceCode() {
return !script()->IsUndefined() && return !script()->IsUndefined() &&
!reinterpret_cast<Script*>(script())->source()->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 // When we set the is_extensible flag to false we always force
// the element into dictionary mode (and force them to stay there). // the element into dictionary mode (and force them to stay there).
if (!map()->is_extensible()) { if (!map()->is_extensible()) {
Handle<Object> number(Heap::NumberFromUint32(index)); Handle<Object> number(Factory::NewNumberFromUint(index));
Handle<String> index_string(Factory::NumberToString(number)); Handle<String> index_string(Factory::NumberToString(number));
Handle<Object> args[1] = { index_string }; Handle<Object> args[1] = { index_string };
return Top::Throw(*Factory::NewTypeError("object_not_extensible", 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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -3621,6 +3621,9 @@ class SharedFunctionInfo: public HeapObject {
// properties. // properties.
DECL_ACCESSORS(inferred_name, String) 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. // Position of the 'function' token in the script source.
inline int function_token_position(); inline int function_token_position();
inline void set_function_token_position(int function_token_position); inline void set_function_token_position(int function_token_position);

43
deps/v8/src/parser.cc

@ -5344,14 +5344,19 @@ bool Parser::ParseRegExp(FlatStringReader* input,
} }
FunctionLiteral* Parser::MakeAST(bool compile_in_global_context, bool Parser::Parse(CompilationInfo* info) {
Handle<Script> script, ASSERT(info->function() == NULL);
v8::Extension* extension, FunctionLiteral* result = NULL;
ScriptDataImpl* pre_data, Handle<Script> script = info->script();
bool is_json) { if (info->is_lazy()) {
AstBuildingParser parser(script, true, NULL, NULL);
result = parser.ParseLazy(info->shared_info());
} else {
bool allow_natives_syntax = bool allow_natives_syntax =
FLAG_allow_natives_syntax || Bootstrapper::IsActive(); FLAG_allow_natives_syntax || Bootstrapper::IsActive();
AstBuildingParser parser(script, allow_natives_syntax, extension, pre_data); 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()) { if (pre_data != NULL && pre_data->has_error()) {
Scanner::Location loc = pre_data->MessageLocation(); Scanner::Location loc = pre_data->MessageLocation();
const char* message = pre_data->BuildMessage(); const char* message = pre_data->BuildMessage();
@ -5362,25 +5367,19 @@ FunctionLiteral* Parser::MakeAST(bool compile_in_global_context,
DeleteArray(args[i]); DeleteArray(args[i]);
} }
DeleteArray(args.start()); DeleteArray(args.start());
return NULL; ASSERT(Top::has_pending_exception());
}
Handle<String> source = Handle<String>(String::cast(script->source()));
FunctionLiteral* result;
if (is_json) {
ASSERT(compile_in_global_context);
result = parser.ParseJson(source);
} else { } else {
result = parser.ParseProgram(source, compile_in_global_context); 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) { info->SetFunction(result);
Handle<Script> script(Script::cast(info->script())); return (result != NULL);
AstBuildingParser parser(script, true, NULL, NULL);
FunctionLiteral* result = parser.ParseLazy(info);
return result;
} }
#undef NEW #undef NEW

16
deps/v8/src/parser.h

@ -35,6 +35,7 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
class CompilationInfo;
class FuncNameInferrer; class FuncNameInferrer;
class ParserFactory; class ParserFactory;
class ParserLog; class ParserLog;
@ -183,17 +184,10 @@ class Parser {
ParserFactory* factory, ParserLog* log, ScriptDataImpl* pre_data); ParserFactory* factory, ParserLog* log, ScriptDataImpl* pre_data);
virtual ~Parser() { } virtual ~Parser() { }
// Takes a script and and context information, and builds a // Parses the source code represented by the compilation info and sets its
// FunctionLiteral AST node. Returns NULL and deallocates any allocated // function literal. Returns false (and deallocates any allocated AST
// AST nodes if parsing failed. // nodes) if parsing failed.
static FunctionLiteral* MakeAST(bool compile_in_global_context, static bool Parse(CompilationInfo* info);
Handle<Script> script,
v8::Extension* extension,
ScriptDataImpl* pre_data,
bool is_json = false);
// Support for doing lazy compilation.
static FunctionLiteral* MakeLazyAST(Handle<SharedFunctionInfo> info);
// Generic preparser generating full preparse data. // Generic preparser generating full preparse data.
static ScriptDataImpl* PreParse(Handle<String> source, 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() { StringsStorage::~StringsStorage() {
for (HashMap::Entry* p = names_.Start(); for (HashMap::Entry* p = names_.Start();
p != NULL; p != NULL;
p = names_.Next(p)) { p = names_.Next(p)) {
DeleteArray(reinterpret_cast<const char*>(p->value)); 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 = ""; 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) { static void DeleteCodeEntry(CodeEntry** entry_ptr) {
delete *entry_ptr; delete *entry_ptr;
} }
@ -508,7 +525,6 @@ CpuProfilesCollection::~CpuProfilesCollection() {
current_profiles_.Iterate(DeleteCpuProfile); current_profiles_.Iterate(DeleteCpuProfile);
profiles_by_token_.Iterate(DeleteProfilesList); profiles_by_token_.Iterate(DeleteProfilesList);
code_entries_.Iterate(DeleteCodeEntry); 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( void CpuProfilesCollection::AddPathToCurrentProfiles(
const Vector<CodeEntry*>& path) { const Vector<CodeEntry*>& path) {
// As starting / stopping profiles is rare relatively to this // As starting / stopping profiles is rare relatively to this
@ -1001,6 +1001,8 @@ const char* HeapEntry::TypeAsString() {
case kString: return "/string/"; case kString: return "/string/";
case kCode: return "/code/"; case kCode: return "/code/";
case kArray: return "/array/"; case kArray: return "/array/";
case kRegExp: return "/regexp/";
case kHeapNumber: return "/number/";
default: return "???"; default: return "???";
} }
} }
@ -1284,11 +1286,16 @@ HeapEntry* HeapSnapshot::AddEntry(HeapObject* object,
} else if (object->IsJSFunction()) { } else if (object->IsJSFunction()) {
JSFunction* func = JSFunction::cast(object); JSFunction* func = JSFunction::cast(object);
SharedFunctionInfo* shared = func->shared(); SharedFunctionInfo* shared = func->shared();
String* name = String::cast(shared->name())->length() > 0 ?
String::cast(shared->name()) : shared->inferred_name();
return AddEntry(object, return AddEntry(object,
HeapEntry::kClosure, 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, children_count,
retainers_count); retainers_count);
} else if (object->IsJSObject()) { } else if (object->IsJSObject()) {
@ -1333,6 +1340,12 @@ HeapEntry* HeapSnapshot::AddEntry(HeapObject* object,
"", "",
children_count, children_count,
retainers_count); retainers_count);
} else if (object->IsHeapNumber()) {
return AddEntry(object,
HeapEntry::kHeapNumber,
"number",
children_count,
retainers_count);
} }
// No interest in this object. // No interest in this object.
return NULL; return NULL;
@ -1342,12 +1355,14 @@ HeapEntry* HeapSnapshot::AddEntry(HeapObject* object,
bool HeapSnapshot::WillAddEntry(HeapObject* object) { bool HeapSnapshot::WillAddEntry(HeapObject* object) {
return object == kInternalRootObject return object == kInternalRootObject
|| object->IsJSFunction() || object->IsJSFunction()
|| object->IsJSRegExp()
|| object->IsJSObject() || object->IsJSObject()
|| object->IsString() || object->IsString()
|| object->IsCode() || object->IsCode()
|| object->IsSharedFunctionInfo() || object->IsSharedFunctionInfo()
|| object->IsScript() || object->IsScript()
|| object->IsFixedArray(); || object->IsFixedArray()
|| object->IsHeapNumber();
} }
@ -1904,13 +1919,21 @@ void HeapSnapshotGenerator::ExtractReferences(HeapObject* obj) {
ExtractClosureReferences(js_obj, entry); ExtractClosureReferences(js_obj, entry);
ExtractPropertyReferences(js_obj, entry); ExtractPropertyReferences(js_obj, entry);
ExtractElementReferences(js_obj, entry); ExtractElementReferences(js_obj, entry);
ExtractInternalReferences(js_obj, entry);
SetPropertyReference( 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()) { } else if (obj->IsString()) {
if (obj->IsConsString()) { if (obj->IsConsString()) {
ConsString* cs = ConsString::cast(obj); ConsString* cs = ConsString::cast(obj);
SetElementReference(obj, entry, 0, cs->first()); SetInternalReference(obj, entry, "1", cs->first());
SetElementReference(obj, entry, 1, cs->second()); SetInternalReference(obj, entry, "2", cs->second());
} }
} else if (obj->IsCode() || obj->IsSharedFunctionInfo() || obj->IsScript()) { } else if (obj->IsCode() || obj->IsSharedFunctionInfo() || obj->IsScript()) {
IndexedReferencesExtractor refs_extractor(this, obj, entry); 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, void HeapSnapshotGenerator::SetClosureReference(HeapObject* parent_obj,
HeapEntry* parent_entry, HeapEntry* parent_entry,
String* reference_name, 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, void HeapSnapshotGenerator::SetPropertyReference(HeapObject* parent_obj,
HeapEntry* parent_entry, HeapEntry* parent_entry,
String* reference_name, String* reference_name,
Object* child_obj) { Object* child_obj) {
HeapEntry* child_entry = GetEntry(child_obj); HeapEntry* child_entry = GetEntry(child_obj);
if (child_entry != NULL) { 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_obj,
parent_entry, parent_entry,
collection_->GetName(reference_name), collection_->GetName(reference_name),
@ -2351,7 +2402,9 @@ void HeapSnapshotJSONSerializer::SerializeNodes() {
"," JSON_S("string") "," JSON_S("string")
"," JSON_S("object") "," JSON_S("object")
"," JSON_S("code") "," JSON_S("code")
"," JSON_S("closure")) "," JSON_S("closure")
"," JSON_S("regexp")
"," JSON_S("number"))
"," JSON_S("string") "," JSON_S("string")
"," JSON_S("number") "," JSON_S("number")
"," JSON_S("number") "," JSON_S("number")

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

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

142
deps/v8/src/regexp.js

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

32
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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -27,9 +27,11 @@
#include "v8.h" #include "v8.h"
#include "rewriter.h"
#include "ast.h" #include "ast.h"
#include "compiler.h"
#include "scopes.h" #include "scopes.h"
#include "rewriter.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
@ -986,34 +988,40 @@ void Processor::VisitThisFunction(ThisFunction* node) {
} }
bool Rewriter::Process(FunctionLiteral* function) { // Assumes code has been parsed and scopes hve been analyzed. Mutates the
HistogramTimerScope timer(&Counters::rewriting); // 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(); Scope* scope = function->scope();
ASSERT(scope != NULL);
if (scope->is_function_scope()) return true; if (scope->is_function_scope()) return true;
ZoneList<Statement*>* body = function->body(); ZoneList<Statement*>* body = function->body();
if (body->is_empty()) return true; if (!body->is_empty()) {
VariableProxy* result = scope->NewTemporary(Factory::result_symbol()); VariableProxy* result = scope->NewTemporary(Factory::result_symbol());
Processor processor(result); Processor processor(result);
processor.Process(body); processor.Process(body);
if (processor.HasStackOverflow()) return false; 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; return true;
} }
bool Rewriter::Optimize(FunctionLiteral* function) { // Assumes code has been parsed and scopes have been analyzed. Mutates the
ZoneList<Statement*>* body = function->body(); // 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()) { if (FLAG_optimize_ast && !body->is_empty()) {
HistogramTimerScope timer(&Counters::ast_optimization);
AstOptimizer optimizer; AstOptimizer optimizer;
optimizer.Optimize(body); optimizer.Optimize(body);
if (optimizer.HasStackOverflow()) { if (optimizer.HasStackOverflow()) return false;
return false;
}
} }
return true; 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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -31,21 +31,26 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
class CompilationInfo;
// 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 Rewriter { class Rewriter {
public: public:
static bool Process(FunctionLiteral* function); // Rewrite top-level code (ECMA 262 "programs") so as to conservatively
static bool Optimize(FunctionLiteral* function); // 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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -27,9 +27,12 @@
#include "v8.h" #include "v8.h"
#include "scopes.h"
#include "bootstrapper.h"
#include "compiler.h"
#include "prettyprinter.h" #include "prettyprinter.h"
#include "scopeinfo.h" #include "scopeinfo.h"
#include "scopes.h"
namespace v8 { namespace v8 {
namespace internal { 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) { void Scope::Initialize(bool inside_with) {
// Add this scope as a new inner scope of the outer scope. // Add this scope as a new inner scope of the outer scope.
if (outer_scope_ != NULL) { 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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -34,6 +34,9 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
class CompilationInfo;
// A hash map to support fast variable declaration and lookup. // A hash map to support fast variable declaration and lookup.
class VariableMap: public HashMap { class VariableMap: public HashMap {
public: public:
@ -96,6 +99,11 @@ class Scope: public ZoneObject {
virtual ~Scope() { } 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. // The scope name is only used for printing/debugging.
void SetScopeName(Handle<String> scope_name) { scope_name_ = scope_name; } 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') && if (%_ObjectEquals(cache.type, 'split') &&
%_IsRegExpEquivalent(cache.regExp, separator) && %_IsRegExpEquivalent(cache.regExp, separator) &&
%_ObjectEquals(cache.subject, subject) && %_ObjectEquals(cache.subject, subject) &&
%_ObjectEquals(cache.lastIndex, limit)) { %_ObjectEquals(cache.splitLimit, limit)) {
if (cache.answerSaved) { if (cache.answerSaved) {
return CloneDenseArray(cache.answer); return CloneDenseArray(cache.answer);
} else { } else {
@ -622,8 +622,7 @@ function StringSplit(separator, limit) {
cache.type = 'split'; cache.type = 'split';
cache.regExp = separator; cache.regExp = separator;
cache.subject = subject; cache.subject = subject;
// Reuse lastIndex field for split limit when type is "split". cache.splitLimit = limit;
cache.lastIndex = limit;
%_Log('regexp', 'regexp-split,%0S,%1r', [subject, separator]); %_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> column_key = Factory::LookupAsciiSymbol("column");
Handle<String> line_key = Factory::LookupAsciiSymbol("lineNumber"); Handle<String> line_key = Factory::LookupAsciiSymbol("lineNumber");
Handle<String> script_key = Factory::LookupAsciiSymbol("scriptName"); 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> function_key = Factory::LookupAsciiSymbol("functionName");
Handle<String> eval_key = Factory::LookupAsciiSymbol("isEval"); Handle<String> eval_key = Factory::LookupAsciiSymbol("isEval");
Handle<String> constructor_key = Factory::LookupAsciiSymbol("isConstructor"); Handle<String> constructor_key = Factory::LookupAsciiSymbol("isConstructor");
@ -355,13 +359,13 @@ Handle<JSArray> Top::CaptureCurrentStackTrace(
Handle<JSObject> stackFrame = Factory::NewJSObject(object_function()); Handle<JSObject> stackFrame = Factory::NewJSObject(object_function());
JavaScriptFrame* frame = it.frame(); JavaScriptFrame* frame = it.frame();
JSFunction* fun(JSFunction::cast(frame->function())); Handle<JSFunction> fun(JSFunction::cast(frame->function()));
Script* script = Script::cast(fun->shared()->script()); Handle<Script> script(Script::cast(fun->shared()->script()));
if (options & StackTrace::kLineNumber) { if (options & StackTrace::kLineNumber) {
int script_line_offset = script->line_offset()->value(); int script_line_offset = script->line_offset()->value();
int position = frame->code()->SourcePosition(frame->pc()); 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. // line_number is already shifted by the script_line_offset.
int relative_line_number = line_number - script_line_offset; int relative_line_number = line_number - script_line_offset;
if (options & StackTrace::kColumnOffset && relative_line_number >= 0) { if (options & StackTrace::kColumnOffset && relative_line_number >= 0) {
@ -385,6 +389,22 @@ Handle<JSArray> Top::CaptureCurrentStackTrace(
SetProperty(stackFrame, script_key, script_name, NONE); 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) { if (options & StackTrace::kFunctionName) {
Handle<Object> fun_name(fun->shared()->name()); Handle<Object> fun_name(fun->shared()->name());
if (fun_name->ToBoolean()->IsFalse()) { 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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -45,14 +45,7 @@ namespace internal {
/* Total compilation times. */ \ /* Total compilation times. */ \
HT(compile, V8.Compile) \ HT(compile, V8.Compile) \
HT(compile_eval, V8.CompileEval) \ HT(compile_eval, V8.CompileEval) \
HT(compile_lazy, V8.CompileLazy) \ 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)
// WARNING: STATS_COUNTER_LIST_* is a very large macro that is causing MSVC // 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(); OS::Setup();
// Initialize other runtime facilities // 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(); ::assembler::arm::Simulator::Initialize();
#endif #endif

4
deps/v8/src/version.cc

@ -33,8 +33,8 @@
// NOTE these macros are used by the SCons build script so their names // NOTE these macros are used by the SCons build script so their names
// cannot be changed without changing the SCons build script. // cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 2 #define MAJOR_VERSION 2
#define MINOR_VERSION 4 #define MINOR_VERSION 5
#define BUILD_NUMBER 8 #define BUILD_NUMBER 0
#define PATCH_LEVEL 0 #define PATCH_LEVEL 0
#define CANDIDATE_VERSION false #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); __ j(equal, &done);
} }
__ SmiNeg(rax, rax, &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. // Try floating point case.
__ bind(&try_float); __ bind(&try_float);
} else if (FLAG_debug_code) { } 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. // Adjust for function-level loop nesting.
ASSERT_EQ(0, 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); 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); CodeGenState state(this);
// Entry: // Entry:
// Stack: receiver, arguments, return address. // Stack: receiver, arguments, return address.
// rbp: caller's frame pointer // rbp: caller's frame pointer
@ -202,6 +192,14 @@ void CodeGenerator::Generate(CompilationInfo* info) {
// rsi: callee's context // rsi: callee's context
allocator_->Initialize(); allocator_->Initialize();
#ifdef DEBUG
if (strlen(FLAG_stop_at) > 0 &&
info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
frame_->SpillAll();
__ int3();
}
#endif
frame_->Enter(); frame_->Enter();
// Allocate space for locals and initialize them. // Allocate space for locals and initialize them.
@ -356,7 +354,7 @@ void CodeGenerator::Generate(CompilationInfo* info) {
} }
// Adjust for function-level loop nesting. // 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; loop_nesting_ = 0;
// Code generation state must be reset. // Code generation state must be reset.
@ -367,7 +365,6 @@ void CodeGenerator::Generate(CompilationInfo* info) {
// Process any deferred code using the register allocator. // Process any deferred code using the register allocator.
if (!HasStackOverflow()) { if (!HasStackOverflow()) {
HistogramTimerScope deferred_timer(&Counters::deferred_code_generation);
JumpTarget::set_compiling_deferred_code(true); JumpTarget::set_compiling_deferred_code(true);
ProcessDeferred(); ProcessDeferred();
JumpTarget::set_compiling_deferred_code(false); JumpTarget::set_compiling_deferred_code(false);
@ -4276,9 +4273,12 @@ void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
// Build the function info and instantiate it. // Build the function info and instantiate it.
Handle<SharedFunctionInfo> function_info = Handle<SharedFunctionInfo> function_info =
Compiler::BuildFunctionInfo(node, script(), this); Compiler::BuildFunctionInfo(node, script());
// Check for stack-overflow exception. // Check for stack-overflow exception.
if (HasStackOverflow()) return; if (function_info.is_null()) {
SetStackOverflow();
return;
}
InstantiateFunction(function_info); InstantiateFunction(function_info);
} }

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

@ -298,9 +298,7 @@ enum ArgumentsAllocationMode {
class CodeGenerator: public AstVisitor { class CodeGenerator: public AstVisitor {
public: public:
// Takes a function literal, generates code for it. This function should only static bool MakeCode(CompilationInfo* info);
// be called by compiler.cc.
static Handle<Code> MakeCode(CompilationInfo* info);
// Printing of AST, etc. as requested by flags. // Printing of AST, etc. as requested by flags.
static void MakeCodePrologue(CompilationInfo* info); static void MakeCodePrologue(CompilationInfo* info);
@ -586,9 +584,6 @@ class CodeGenerator: public AstVisitor {
void CheckStack(); void CheckStack();
static InlineFunctionGenerator FindInlineFunctionGenerator(
Runtime::FunctionId function_id);
bool CheckForInlineRuntimeCall(CallRuntime* node); bool CheckForInlineRuntimeCall(CallRuntime* node);
void ProcessDeclarations(ZoneList<Declaration*>* declarations); 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()); SetFunctionPosition(function());
Comment cmnt(masm_, "[ function compiled by full code generator"); 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. __ push(rbp); // Caller's frame pointer.
__ movq(rbp, rsp); __ movq(rbp, rsp);
__ push(rsi); // Callee's context. __ push(rsi); // Callee's context.

1
deps/v8/test/cctest/SConscript

@ -70,6 +70,7 @@ SOURCES = {
'test-sockets.cc', 'test-sockets.cc',
'test-spaces.cc', 'test-spaces.cc',
'test-strings.cc', 'test-strings.cc',
'test-strtod.cc',
'test-thread-termination.cc', 'test-thread-termination.cc',
'test-threads.cc', 'test-threads.cc',
'test-type-info.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(); return args.This();
} }
static v8::Handle<Value> Return239(Local<String> name, const AccessorInfo&) {
ApiTestFuzzer::Fuzz();
return v8_num(239);
}
THREADED_TEST(FunctionTemplate) { THREADED_TEST(FunctionTemplate) {
v8::HandleScope scope; v8::HandleScope scope;
LocalContext env; LocalContext env;
@ -792,6 +798,7 @@ THREADED_TEST(FunctionTemplate) {
Local<v8::FunctionTemplate> fun_templ = Local<v8::FunctionTemplate> fun_templ =
v8::FunctionTemplate::New(construct_call); v8::FunctionTemplate::New(construct_call);
fun_templ->SetClassName(v8_str("funky")); fun_templ->SetClassName(v8_str("funky"));
fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), Return239);
Local<Function> fun = fun_templ->GetFunction(); Local<Function> fun = fun_templ->GetFunction();
env->Global()->Set(v8_str("obj"), fun); env->Global()->Set(v8_str("obj"), fun);
Local<Script> script = v8_compile("var s = new obj(); s.x"); 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(); Local<Value> result = v8_compile("(new obj()).toString()")->Run();
CHECK_EQ(v8_str("[object funky]"), result); 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, static void SetOnThis(Local<String> name,
Local<Value> value, Local<Value> value,
const AccessorInfo& info) { 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. // Test that idle notification can be handled and eventually returns true.
THREADED_TEST(IdleNotification) { THREADED_TEST(IdleNotification) {
bool rv = false; bool rv = false;
@ -11619,3 +11662,96 @@ TEST(GlobalLoadICGC) {
CheckSurvivingGlobalObjectsCount(1); 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)); 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) { TEST(ExponentNumberStr) {
CHECK_EQ(1e1, StringToDouble("1e1", NO_FLAGS)); 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; using i::RetainerHeapProfile;
static void CompileAndRunScript(const char *src) {
v8::Script::Compile(v8::String::New(src))->Run();
}
namespace { namespace {
class ConstructorHeapProfileTestHelper : public i::ConstructorHeapProfile { class ConstructorHeapProfileTestHelper : public i::ConstructorHeapProfile {
@ -58,7 +53,7 @@ TEST(ConstructorProfile) {
v8::HandleScope scope; v8::HandleScope scope;
LocalContext env; LocalContext env;
CompileAndRunScript( CompileRun(
"function F() {} // A constructor\n" "function F() {} // A constructor\n"
"var f1 = new F();\n" "var f1 = new F();\n"
"var f2 = new F();\n"); "var f2 = new F();\n");
@ -359,7 +354,7 @@ TEST(RetainerProfile) {
v8::HandleScope scope; v8::HandleScope scope;
LocalContext env; LocalContext env;
CompileAndRunScript( CompileRun(
"function A() {}\n" "function A() {}\n"
"function B(x) { this.x = x; }\n" "function B(x) { this.x = x; }\n"
"function C(x) { this.x1 = x; this.x2 = x; }\n" "function C(x) { this.x1 = x; this.x2 = x; }\n"
@ -473,7 +468,7 @@ TEST(HeapSnapshot) {
LocalContext env1; LocalContext env1;
env1->SetSecurityToken(token1); env1->SetSecurityToken(token1);
CompileAndRunScript( CompileRun(
"function A1() {}\n" "function A1() {}\n"
"function B1(x) { this.x = x; }\n" "function B1(x) { this.x = x; }\n"
"function C1(x) { this.x1 = x; this.x2 = x; }\n" "function C1(x) { this.x1 = x; this.x2 = x; }\n"
@ -485,7 +480,7 @@ TEST(HeapSnapshot) {
LocalContext env2; LocalContext env2;
env2->SetSecurityToken(token2); env2->SetSecurityToken(token2);
CompileAndRunScript( CompileRun(
"function A2() {}\n" "function A2() {}\n"
"function B2(x) { return function() { return typeof x; }; }\n" "function B2(x) { return function() { return typeof x; }; }\n"
"function C2(x) { this.x1 = x; this.x2 = x; this[1] = x; }\n" "function C2(x) { this.x1 = x; this.x2 = x; this[1] = x; }\n"
@ -583,7 +578,7 @@ TEST(HeapSnapshotObjectSizes) {
// -a-> X1 --a // -a-> X1 --a
// x -b-> X2 <-| // x -b-> X2 <-|
CompileAndRunScript( CompileRun(
"function X(a, b) { this.a = a; this.b = b; }\n" "function X(a, b) { this.a = a; this.b = b; }\n"
"x = new X(new X(), new X());\n" "x = new X(new X(), new X());\n"
"x.a.a = x.b;"); "x.a.a = x.b;");
@ -594,7 +589,7 @@ TEST(HeapSnapshotObjectSizes) {
GetProperty(global, v8::HeapGraphEdge::kProperty, "x"); GetProperty(global, v8::HeapGraphEdge::kProperty, "x");
CHECK_NE(NULL, x); CHECK_NE(NULL, x);
const v8::HeapGraphNode* x_prototype = const v8::HeapGraphNode* x_prototype =
GetProperty(x, v8::HeapGraphEdge::kProperty, "prototype"); GetProperty(x, v8::HeapGraphEdge::kProperty, "__proto__");
CHECK_NE(NULL, x_prototype); CHECK_NE(NULL, x_prototype);
const v8::HeapGraphNode* x1 = const v8::HeapGraphNode* x1 =
GetProperty(x, v8::HeapGraphEdge::kProperty, "a"); GetProperty(x, v8::HeapGraphEdge::kProperty, "a");
@ -606,7 +601,7 @@ TEST(HeapSnapshotObjectSizes) {
x->GetSelfSize() * 3, x->GetSelfSize() * 3,
x->GetReachableSize() - x_prototype->GetReachableSize()); x->GetReachableSize() - x_prototype->GetReachableSize());
CHECK_EQ( CHECK_EQ(
x->GetSelfSize() * 3 + x_prototype->GetSelfSize(), x->GetRetainedSize()); x->GetSelfSize() * 3, x->GetRetainedSize());
CHECK_EQ( CHECK_EQ(
x1->GetSelfSize() * 2, x1->GetSelfSize() * 2,
x1->GetReachableSize() - x_prototype->GetReachableSize()); x1->GetReachableSize() - x_prototype->GetReachableSize());
@ -624,7 +619,7 @@ TEST(HeapSnapshotEntryChildren) {
v8::HandleScope scope; v8::HandleScope scope;
LocalContext env; LocalContext env;
CompileAndRunScript( CompileRun(
"function A() { }\n" "function A() { }\n"
"a = new A;"); "a = new A;");
const v8::HeapSnapshot* snapshot = const v8::HeapSnapshot* snapshot =
@ -648,10 +643,9 @@ TEST(HeapSnapshotCodeObjects) {
v8::HandleScope scope; v8::HandleScope scope;
LocalContext env; LocalContext env;
CompileAndRunScript( CompileRun(
"function lazy(x) { return x - 1; }\n" "function lazy(x) { return x - 1; }\n"
"function compiled(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" "var anonymous = (function() { return function() { return 0; } })();\n"
"compiled(1)"); "compiled(1)");
const v8::HeapSnapshot* snapshot = const v8::HeapSnapshot* snapshot =
@ -666,18 +660,12 @@ TEST(HeapSnapshotCodeObjects) {
GetProperty(global, v8::HeapGraphEdge::kProperty, "lazy"); GetProperty(global, v8::HeapGraphEdge::kProperty, "lazy");
CHECK_NE(NULL, lazy); CHECK_NE(NULL, lazy);
CHECK_EQ(v8::HeapGraphNode::kClosure, lazy->GetType()); 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 = const v8::HeapGraphNode* anonymous =
GetProperty(global, v8::HeapGraphEdge::kProperty, "anonymous"); GetProperty(global, v8::HeapGraphEdge::kProperty, "anonymous");
CHECK_NE(NULL, anonymous); CHECK_NE(NULL, anonymous);
CHECK_EQ(v8::HeapGraphNode::kClosure, anonymous->GetType()); CHECK_EQ(v8::HeapGraphNode::kClosure, anonymous->GetType());
v8::String::AsciiValue anonymous_name(anonymous->GetName()); v8::String::AsciiValue anonymous_name(anonymous->GetName());
CHECK_EQ("(anonymous function)", *anonymous_name); CHECK_EQ("", *anonymous_name);
// Find references to code. // Find references to code.
const v8::HeapGraphNode* compiled_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 // Trying to introduce a check helper for uint64_t causes many
// overloading ambiguities, so it seems easier just to cast // overloading ambiguities, so it seems easier just to cast
// them to a signed type. // them to a signed type.
@ -728,7 +754,7 @@ TEST(HeapEntryIdsAndGC) {
v8::HandleScope scope; v8::HandleScope scope;
LocalContext env; LocalContext env;
CompileAndRunScript( CompileRun(
"function A() {}\n" "function A() {}\n"
"function B(x) { this.x = x; }\n" "function B(x) { this.x = x; }\n"
"var a = new A();\n" "var a = new A();\n"
@ -784,7 +810,7 @@ TEST(HeapSnapshotsDiff) {
v8::HandleScope scope; v8::HandleScope scope;
LocalContext env; LocalContext env;
CompileAndRunScript( CompileRun(
"function A() {}\n" "function A() {}\n"
"function B(x) { this.x = x; }\n" "function B(x) { this.x = x; }\n"
"function A2(a) { for (var i = 0; i < a; ++i) this[i] = i; }\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 = const v8::HeapSnapshot* snapshot1 =
v8::HeapProfiler::TakeSnapshot(v8::String::New("s1")); v8::HeapProfiler::TakeSnapshot(v8::String::New("s1"));
CompileAndRunScript( CompileRun(
"delete a;\n" "delete a;\n"
"b.x = null;\n" "b.x = null;\n"
"var a = new A2(20);\n" "var a = new A2(20);\n"
@ -928,7 +954,7 @@ TEST(AggregatedHeapSnapshot) {
v8::HandleScope scope; v8::HandleScope scope;
LocalContext env; LocalContext env;
CompileAndRunScript( CompileRun(
"function A() {}\n" "function A() {}\n"
"function B(x) { this.x = x; }\n" "function B(x) { this.x = x; }\n"
"var a = new A();\n" "var a = new A();\n"
@ -1049,7 +1075,7 @@ TEST(HeapSnapshotJSONSerialization) {
#define STRING_LITERAL_FOR_TEST \ #define STRING_LITERAL_FOR_TEST \
"\"String \\n\\r\\u0008\\u0081\\u0101\\u0801\\u8001\"" "\"String \\n\\r\\u0008\\u0081\\u0101\\u0801\\u8001\""
CompileAndRunScript( CompileRun(
"function A(s) { this.s = s; }\n" "function A(s) { this.s = s; }\n"
"function B(x) { this.x = x; }\n" "function B(x) { this.x = x; }\n"
"var a = new A(" STRING_LITERAL_FOR_TEST ");\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"; res[3] = "Glopglyf";
assertEquals("Arglebargle", res.foobar); 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), "fiskhest2");
assertEquals(Infinity, one / (4 % 2), "fiskhest3"); assertEquals(Infinity, one / (4 % 2), "fiskhest3");
assertEquals(Infinity, one / (4 % -2), "fiskhest4"); 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.cc',
'../../src/builtins.h', '../../src/builtins.h',
'../../src/bytecodes-irregexp.h', '../../src/bytecodes-irregexp.h',
'../../src/cached-powers.cc',
'../../src/cached-powers.h', '../../src/cached-powers.h',
'../../src/char-predicates-inl.h', '../../src/char-predicates-inl.h',
'../../src/char-predicates.h', '../../src/char-predicates.h',
@ -402,7 +403,6 @@
'../../src/parser.cc', '../../src/parser.cc',
'../../src/parser.h', '../../src/parser.h',
'../../src/platform.h', '../../src/platform.h',
'../../src/powers-ten.h',
'../../src/prettyprinter.cc', '../../src/prettyprinter.cc',
'../../src/prettyprinter.h', '../../src/prettyprinter.h',
'../../src/property.cc', '../../src/property.cc',
@ -445,6 +445,8 @@
'../../src/string-search.h', '../../src/string-search.h',
'../../src/string-stream.cc', '../../src/string-stream.cc',
'../../src/string-stream.h', '../../src/string-stream.h',
'../../src/strtod.cc',
'../../src/strtod.h',
'../../src/stub-cache.cc', '../../src/stub-cache.cc',
'../../src/stub-cache.h', '../../src/stub-cache.h',
'../../src/token.cc', '../../src/token.cc',

Loading…
Cancel
Save