Browse Source

Upgrade v8 to 1.3.4

v0.7.4-release
Ryan 16 years ago
parent
commit
9dc621f83a
  1. 10
      deps/v8/ChangeLog
  2. 8
      deps/v8/include/v8.h
  3. 8
      deps/v8/src/api.cc
  4. 31
      deps/v8/src/compiler.cc
  5. 4
      deps/v8/src/compiler.h
  6. 20
      deps/v8/src/d8.cc
  7. 1
      deps/v8/src/d8.h
  8. 3
      deps/v8/src/flag-definitions.h
  9. 16
      deps/v8/src/heap.cc
  10. 6
      deps/v8/src/heap.h
  11. 129
      deps/v8/src/messages.js
  12. 15
      deps/v8/src/runtime.cc
  13. 42
      deps/v8/src/spaces.cc
  14. 24
      deps/v8/src/spaces.h
  15. 16
      deps/v8/src/uri.js
  16. 9
      deps/v8/src/v8.cc
  17. 3
      deps/v8/src/v8.h
  18. 2
      deps/v8/src/version.cc
  19. 60
      deps/v8/src/x64/codegen-x64.cc
  20. 3
      deps/v8/src/x64/disasm-x64.cc
  21. 10
      deps/v8/test/mjsunit/json.js

10
deps/v8/ChangeLog

@ -1,3 +1,13 @@
2009-08-13: Version 1.3.4
Added a readline() command to the d8 shell.
Fixed bug in json parsing.
Added idle notification to the API and reduced memory on idle
notifications.
2009-08-12: Version 1.3.3
Fix issue 417: incorrect %t placeholder expansion.

8
deps/v8/include/v8.h

@ -2201,6 +2201,14 @@ class V8EXPORT V8 {
*/
static bool Dispose();
/**
* Optional notification that the embedder is idle.
* V8 uses the notification to reduce memory footprint.
* \param is_high_priority tells whether the embedder is high priority.
*/
static void IdleNotification(bool is_high_priority);
private:
V8();

8
deps/v8/src/api.cc

@ -2558,6 +2558,10 @@ bool v8::V8::Dispose() {
}
void v8::V8::IdleNotification(bool is_high_priority) {
i::V8::IdleNotification(is_high_priority);
}
const char* v8::V8::GetVersion() {
static v8::internal::EmbeddedVector<char, 128> buffer;
v8::internal::Version::GetString(buffer);
@ -2589,12 +2593,8 @@ Persistent<Context> v8::Context::New(
i::Handle<i::Context> env;
{
ENTER_V8;
#if defined(ANDROID)
// On mobile devices, full GC is expensive.
#else
// Give the heap a chance to cleanup if we've disposed contexts.
i::Heap::CollectAllGarbageIfContextDisposed();
#endif
v8::Handle<ObjectTemplate> proxy_template = global_template;
i::Handle<i::FunctionTemplateInfo> proxy_constructor;
i::Handle<i::FunctionTemplateInfo> global_constructor;

31
deps/v8/src/compiler.cc

@ -102,7 +102,7 @@ static Handle<Code> MakeCode(FunctionLiteral* literal,
static bool IsValidJSON(FunctionLiteral* lit) {
if (!lit->body()->length() == 1)
if (lit->body()->length() != 1)
return false;
Statement* stmt = lit->body()->at(0);
if (stmt->AsExpressionStatement() == NULL)
@ -114,7 +114,7 @@ static bool IsValidJSON(FunctionLiteral* lit) {
static Handle<JSFunction> MakeFunction(bool is_global,
bool is_eval,
bool is_json,
Compiler::ValidationState validate,
Handle<Script> script,
Handle<Context> context,
v8::Extension* extension,
@ -129,6 +129,7 @@ static Handle<JSFunction> MakeFunction(bool is_global,
script->set_context_data((*i::Top::global_context())->data());
#ifdef ENABLE_DEBUGGER_SUPPORT
bool is_json = (validate == Compiler::VALIDATE_JSON);
if (is_eval || is_json) {
script->set_compilation_type(
is_json ? Smi::FromInt(Script::COMPILATION_TYPE_JSON) :
@ -162,7 +163,7 @@ static Handle<JSFunction> MakeFunction(bool is_global,
// When parsing JSON we do an ordinary parse and then afterwards
// check the AST to ensure it was well-formed. If not we give a
// syntax error.
if (is_json && !IsValidJSON(lit)) {
if (validate == Compiler::VALIDATE_JSON && !IsValidJSON(lit)) {
HandleScope scope;
Handle<JSArray> args = Factory::NewJSArray(1);
Handle<Object> source(script->source());
@ -282,7 +283,7 @@ Handle<JSFunction> Compiler::Compile(Handle<String> source,
// Compile the function and add it to the cache.
result = MakeFunction(true,
false,
false,
DONT_VALIDATE_JSON,
script,
Handle<Context>::null(),
extension,
@ -305,7 +306,11 @@ Handle<JSFunction> Compiler::Compile(Handle<String> source,
Handle<JSFunction> Compiler::CompileEval(Handle<String> source,
Handle<Context> context,
bool is_global,
bool is_json) {
ValidationState validate) {
// Note that if validation is required then no path through this
// function is allowed to return a value without validating that
// the input is legal json.
int source_length = source->length();
Counters::total_eval_size.Increment(source_length);
Counters::total_compile_size.Increment(source_length);
@ -314,20 +319,26 @@ Handle<JSFunction> Compiler::CompileEval(Handle<String> source,
VMState state(COMPILER);
// Do a lookup in the compilation cache; if the entry is not there,
// invoke the compiler and add the result to the cache.
Handle<JSFunction> result =
CompilationCache::LookupEval(source, context, is_global);
// invoke the compiler and add the result to the cache. If we're
// evaluating json we bypass the cache since we can't be sure a
// potential value in the cache has been validated.
Handle<JSFunction> result;
if (validate == DONT_VALIDATE_JSON)
result = CompilationCache::LookupEval(source, context, is_global);
if (result.is_null()) {
// Create a script object describing the script to be compiled.
Handle<Script> script = Factory::NewScript(source);
result = MakeFunction(is_global,
true,
is_json,
validate,
script,
context,
NULL,
NULL);
if (!result.is_null()) {
if (!result.is_null() && validate != VALIDATE_JSON) {
// For json it's unlikely that we'll ever see exactly the same
// string again so we don't use the compilation cache.
CompilationCache::PutEval(source, context, is_global, result);
}
}

4
deps/v8/src/compiler.h

@ -48,6 +48,8 @@ namespace internal {
class Compiler : public AllStatic {
public:
enum ValidationState { VALIDATE_JSON, DONT_VALIDATE_JSON };
// All routines return a JSFunction.
// If an error occurs an exception is raised and
// the return handle contains NULL.
@ -63,7 +65,7 @@ class Compiler : public AllStatic {
static Handle<JSFunction> CompileEval(Handle<String> source,
Handle<Context> context,
bool is_global,
bool is_json);
ValidationState validation);
// Compile from function info (used for lazy compilation). Returns
// true on success and false if the compilation resulted in a stack

20
deps/v8/src/d8.cc

@ -167,9 +167,6 @@ Handle<Value> Shell::Write(const Arguments& args) {
Handle<Value> Shell::Read(const Arguments& args) {
if (args.Length() != 1) {
return ThrowException(String::New("Bad parameters"));
}
String::Utf8Value file(args[0]);
if (*file == NULL) {
return ThrowException(String::New("Error loading file"));
@ -182,6 +179,19 @@ Handle<Value> Shell::Read(const Arguments& args) {
}
Handle<Value> Shell::ReadLine(const Arguments& args) {
char line_buf[256];
if (fgets(line_buf, sizeof(line_buf), stdin) == NULL) {
return ThrowException(String::New("Error reading line"));
}
int len = strlen(line_buf);
if (line_buf[len - 1] == '\n') {
--len;
}
return String::New(line_buf, len);
}
Handle<Value> Shell::Load(const Arguments& args) {
for (int i = 0; i < args.Length(); i++) {
HandleScope handle_scope;
@ -404,6 +414,8 @@ void Shell::Initialize() {
global_template->Set(String::New("print"), FunctionTemplate::New(Print));
global_template->Set(String::New("write"), FunctionTemplate::New(Write));
global_template->Set(String::New("read"), FunctionTemplate::New(Read));
global_template->Set(String::New("readline"),
FunctionTemplate::New(ReadLine));
global_template->Set(String::New("load"), FunctionTemplate::New(Load));
global_template->Set(String::New("quit"), FunctionTemplate::New(Quit));
global_template->Set(String::New("version"), FunctionTemplate::New(Version));
@ -596,6 +608,8 @@ void ShellThread::Run() {
FunctionTemplate::New(Shell::Write));
global_template->Set(String::New("read"),
FunctionTemplate::New(Shell::Read));
global_template->Set(String::New("readline"),
FunctionTemplate::New(Shell::ReadLine));
global_template->Set(String::New("load"),
FunctionTemplate::New(Shell::Load));
global_template->Set(String::New("yield"),

1
deps/v8/src/d8.h

@ -143,6 +143,7 @@ class Shell: public i::AllStatic {
static Handle<Value> Quit(const Arguments& args);
static Handle<Value> Version(const Arguments& args);
static Handle<Value> Read(const Arguments& args);
static Handle<Value> ReadLine(const Arguments& args);
static Handle<Value> Load(const Arguments& args);
// The OS object on the global object contains methods for performing
// operating system calls:

3
deps/v8/src/flag-definitions.h

@ -161,6 +161,9 @@ DEFINE_bool(trace_gc_verbose, false,
DEFINE_bool(collect_maps, true,
"garbage collect maps from which no objects can be reached")
// v8.cc
DEFINE_bool(use_idle_notification, true,
"Use idle notification to reduce memory footprint.")
// ic.cc
DEFINE_bool(use_ic, true, "use inline caching")

16
deps/v8/src/heap.cc

@ -425,6 +425,20 @@ static void VerifySymbolTable() {
}
void Heap::EnsureFromSpaceIsCommitted() {
if (new_space_.CommitFromSpaceIfNeeded()) return;
// Committing memory to from space failed.
// Try shrinking and try again.
Shrink();
if (new_space_.CommitFromSpaceIfNeeded()) return;
// Committing memory to from space failed again.
// Memory is exhausted and we will die.
V8::FatalProcessOutOfMemory("Committing semi space failed.");
}
void Heap::PerformGarbageCollection(AllocationSpace space,
GarbageCollector collector,
GCTracer* tracer) {
@ -433,7 +447,7 @@ void Heap::PerformGarbageCollection(AllocationSpace space,
ASSERT(!allocation_allowed_);
global_gc_prologue_callback_();
}
EnsureFromSpaceIsCommitted();
if (collector == MARK_COMPACTOR) {
MarkCompact(tracer);

6
deps/v8/src/heap.h

@ -280,6 +280,9 @@ class Heap : public AllStatic {
return new_space_.allocation_limit_address();
}
// Uncommit unused semi space.
static bool UncommitFromSpace() { return new_space_.UncommitFromSpace(); }
#ifdef ENABLE_HEAP_PROTECTION
// Protect/unprotect the heap by marking all spaces read-only/writable.
static void Protect();
@ -794,6 +797,9 @@ class Heap : public AllStatic {
// Rebuild remembered set in old and map spaces.
static void RebuildRSets();
// Commits from space if it is uncommitted.
static void EnsureFromSpaceIsCommitted();
//
// Support for the API.
//

129
deps/v8/src/messages.js

@ -28,30 +28,89 @@
// -------------------------------------------------------------------
const kVowelSounds = {a: true, e: true, i: true, o: true, u: true, y: true};
const kCapitalVowelSounds = {a: true, e: true, i: true, o: true, u: true,
h: true, f: true, l: true, m: true, n: true, r: true, s: true, x: true,
y: true};
// Lazily initialized.
var kVowelSounds = 0;
var kCapitalVowelSounds = 0;
function GetInstanceName(cons) {
if (cons.length == 0) {
return "";
}
var first = %StringToLowerCase(StringCharAt.call(cons, 0));
var mapping = kVowelSounds;
if (kVowelSounds === 0) {
kVowelSounds = {a: true, e: true, i: true, o: true, u: true, y: true};
kCapitalVowelSounds = {a: true, e: true, i: true, o: true, u: true, h: true,
f: true, l: true, m: true, n: true, r: true, s: true, x: true, y: true};
}
var vowel_mapping = kVowelSounds;
if (cons.length > 1 && (StringCharAt.call(cons, 0) != first)) {
// First char is upper case
var second = %StringToLowerCase(StringCharAt.call(cons, 1));
// Second char is upper case
if (StringCharAt.call(cons, 1) != second)
mapping = kCapitalVowelSounds;
if (StringCharAt.call(cons, 1) != second) {
vowel_mapping = kCapitalVowelSounds;
}
var s = mapping[first] ? "an " : "a ";
}
var s = vowel_mapping[first] ? "an " : "a ";
return s + cons;
}
const kMessages = {
var kMessages = 0;
function FormatString(format, args) {
var result = format;
for (var i = 0; i < args.length; i++) {
var str;
try { str = ToDetailString(args[i]); }
catch (e) { str = "#<error>"; }
result = ArrayJoin.call(StringSplit.call(result, "%" + i), str);
}
return result;
}
function ToDetailString(obj) {
if (obj != null && IS_OBJECT(obj) && obj.toString === $Object.prototype.toString) {
var constructor = obj.constructor;
if (!constructor) return ToString(obj);
var constructorName = constructor.name;
if (!constructorName) return ToString(obj);
return "#<" + GetInstanceName(constructorName) + ">";
} else {
return ToString(obj);
}
}
function MakeGenericError(constructor, type, args) {
if (IS_UNDEFINED(args)) {
args = [];
}
var e = new constructor(kAddMessageAccessorsMarker);
e.type = type;
e.arguments = args;
return e;
}
/**
* Setup the Script function and constructor.
*/
%FunctionSetInstanceClassName(Script, 'Script');
%SetProperty(Script.prototype, 'constructor', Script, DONT_ENUM);
%SetCode(Script, function(x) {
// Script objects can only be created by the VM.
throw new $Error("Not supported");
});
// Helper functions; called from the runtime system.
function FormatMessage(message) {
if (kMessages === 0) {
kMessages = {
// Error
cyclic_proto: "Cyclic __proto__ value",
// TypeError
@ -109,58 +168,8 @@ const kMessages = {
result_not_primitive: "Result of %0 must be a primitive, was %1",
invalid_json: "String '%0' is not valid JSON",
circular_structure: "Converting circular structure to JSON"
};
function FormatString(format, args) {
var result = format;
for (var i = 0; i < args.length; i++) {
var str;
try { str = ToDetailString(args[i]); }
catch (e) { str = "#<error>"; }
result = ArrayJoin.call(StringSplit.call(result, "%" + i), str);
}
return result;
}
function ToDetailString(obj) {
if (obj != null && IS_OBJECT(obj) && obj.toString === $Object.prototype.toString) {
var constructor = obj.constructor;
if (!constructor) return ToString(obj);
var constructorName = constructor.name;
if (!constructorName) return ToString(obj);
return "#<" + GetInstanceName(constructorName) + ">";
} else {
return ToString(obj);
}
}
function MakeGenericError(constructor, type, args) {
if (IS_UNDEFINED(args)) {
args = [];
};
}
var e = new constructor(kAddMessageAccessorsMarker);
e.type = type;
e.arguments = args;
return e;
}
/**
* Setup the Script function and constructor.
*/
%FunctionSetInstanceClassName(Script, 'Script');
%SetProperty(Script.prototype, 'constructor', Script, DONT_ENUM);
%SetCode(Script, function(x) {
// Script objects can only be created by the VM.
throw new $Error("Not supported");
});
// Helper functions; called from the runtime system.
function FormatMessage(message) {
var format = kMessages[message.type];
if (!format) return "<unknown message " + message.type + ">";
return FormatString(format, message.args);

15
deps/v8/src/runtime.cc

@ -4973,10 +4973,12 @@ static Object* Runtime_CompileString(Arguments args) {
// Compile source string in the global context.
Handle<Context> context(Top::context()->global_context());
Compiler::ValidationState validate = (is_json->IsTrue())
? Compiler::VALIDATE_JSON : Compiler::DONT_VALIDATE_JSON;
Handle<JSFunction> boilerplate = Compiler::CompileEval(source,
context,
true,
is_json->IsTrue());
validate);
if (boilerplate.is_null()) return Failure::Exception();
Handle<JSFunction> fun =
Factory::NewFunctionFromBoilerplate(boilerplate, context);
@ -5000,8 +5002,11 @@ static Object* CompileDirectEval(Handle<String> source) {
bool is_global = context->IsGlobalContext();
// Compile source string in the current context.
Handle<JSFunction> boilerplate =
Compiler::CompileEval(source, context, is_global, false);
Handle<JSFunction> boilerplate = Compiler::CompileEval(
source,
context,
is_global,
Compiler::DONT_VALIDATE_JSON);
if (boilerplate.is_null()) return Failure::Exception();
Handle<JSFunction> fun =
Factory::NewFunctionFromBoilerplate(boilerplate, context);
@ -7043,7 +7048,7 @@ static Object* Runtime_DebugEvaluate(Arguments args) {
Compiler::CompileEval(function_source,
context,
context->IsGlobalContext(),
false);
Compiler::DONT_VALIDATE_JSON);
if (boilerplate.is_null()) return Failure::Exception();
Handle<JSFunction> compiled_function =
Factory::NewFunctionFromBoilerplate(boilerplate, context);
@ -7111,7 +7116,7 @@ static Object* Runtime_DebugEvaluateGlobal(Arguments args) {
Handle<JSFunction>(Compiler::CompileEval(source,
context,
true,
false));
Compiler::DONT_VALIDATE_JSON));
if (boilerplate.is_null()) return Failure::Exception();
Handle<JSFunction> compiled_function =
Handle<JSFunction>(Factory::NewFunctionFromBoilerplate(boilerplate,

42
deps/v8/src/spaces.cc

@ -340,6 +340,17 @@ bool MemoryAllocator::CommitBlock(Address start,
return true;
}
bool MemoryAllocator::UncommitBlock(Address start, size_t size) {
ASSERT(start != NULL);
ASSERT(size > 0);
ASSERT(initial_chunk_ != NULL);
ASSERT(InInitialChunk(start));
ASSERT(InInitialChunk(start + size - 1));
if (!initial_chunk_->Uncommit(start, size)) return false;
Counters::memory_allocated.Decrement(size);
return true;
}
Page* MemoryAllocator::InitializePagesInChunk(int chunk_id, int pages_in_chunk,
PagedSpace* owner) {
@ -1039,6 +1050,26 @@ void NewSpace::Verify() {
#endif
bool SemiSpace::Commit() {
ASSERT(!is_committed());
if (!MemoryAllocator::CommitBlock(start_, capacity_, executable())) {
return false;
}
committed_ = true;
return true;
}
bool SemiSpace::Uncommit() {
ASSERT(is_committed());
if (!MemoryAllocator::UncommitBlock(start_, capacity_)) {
return false;
}
committed_ = false;
return true;
}
// -----------------------------------------------------------------------------
// SemiSpace implementation
@ -1053,18 +1084,15 @@ bool SemiSpace::Setup(Address start,
// addresses.
capacity_ = initial_capacity;
maximum_capacity_ = maximum_capacity;
if (!MemoryAllocator::CommitBlock(start, capacity_, executable())) {
return false;
}
committed_ = false;
start_ = start;
address_mask_ = ~(maximum_capacity - 1);
object_mask_ = address_mask_ | kHeapObjectTag;
object_expected_ = reinterpret_cast<uintptr_t>(start) | kHeapObjectTag;
age_mark_ = start_;
return true;
return Commit();
}
@ -1076,7 +1104,7 @@ void SemiSpace::TearDown() {
bool SemiSpace::Grow() {
// Commit 50% extra space but only up to maximum capacity.
int extra = capacity_/2;
int extra = RoundUp(capacity_ / 2, OS::AllocateAlignment());
if (capacity_ + extra > maximum_capacity_) {
extra = maximum_capacity_ - capacity_;
}

24
deps/v8/src/spaces.h

@ -367,6 +367,13 @@ class MemoryAllocator : public AllStatic {
// and false otherwise.
static bool CommitBlock(Address start, size_t size, Executability executable);
// Uncommit a contiguous block of memory [start..(start+size)[.
// start is not NULL, the size is greater than zero, and the
// block is contained in the initial chunk. Returns true if it succeeded
// and false otherwise.
static bool UncommitBlock(Address start, size_t size);
// Attempts to allocate the requested (non-zero) number of pages from the
// OS. Fewer pages might be allocated than requested. If it fails to
// allocate memory for the OS or cannot allocate a single page, this
@ -1035,6 +1042,10 @@ class SemiSpace : public Space {
return 0;
}
bool is_committed() { return committed_; }
bool Commit();
bool Uncommit();
#ifdef DEBUG
virtual void Print();
virtual void Verify();
@ -1058,6 +1069,8 @@ class SemiSpace : public Space {
uintptr_t object_mask_;
uintptr_t object_expected_;
bool committed_;
public:
TRACK_MEMORY("SemiSpace")
};
@ -1250,6 +1263,17 @@ class NewSpace : public Space {
void RecordPromotion(HeapObject* obj);
#endif
// Return whether the operation succeded.
bool CommitFromSpaceIfNeeded() {
if (from_space_.is_committed()) return true;
return from_space_.Commit();
}
bool UncommitFromSpace() {
if (!from_space_.is_committed()) return true;
return from_space_.Uncommit();
}
private:
// The current and maximum capacities of a semispace.
int capacity_;

16
deps/v8/src/uri.js

@ -39,6 +39,10 @@ function URIAddEncodedOctetToBuffer(octet, result, index) {
function URIEncodeOctets(octets, result, index) {
if (hexCharCodeArray === 0) {
hexCharCodeArray = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
65, 66, 67, 68, 69, 70];
}
index = URIAddEncodedOctetToBuffer(octets[0], result, index);
if (octets[1]) index = URIAddEncodedOctetToBuffer(octets[1], result, index);
if (octets[2]) index = URIAddEncodedOctetToBuffer(octets[2], result, index);
@ -316,11 +320,9 @@ function URIEncodeComponent(component) {
}
const hexCharArray = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
"A", "B", "C", "D", "E", "F"];
const hexCharCodeArray = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
65, 66, 67, 68, 69, 70];
// Lazily initialized.
var hexCharArray = 0;
var hexCharCodeArray = 0;
function HexValueOf(c) {
@ -341,6 +343,10 @@ function HexValueOf(c) {
// 64 -> 0040, 62234 -> F31A.
function CharCodeToHex4Str(cc) {
var r = "";
if (hexCharArray === 0) {
hexCharArray = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
"A", "B", "C", "D", "E", "F"];
}
for (var i = 0; i < 4; ++i) {
var c = hexCharArray[cc & 0x0F];
r = c + r;

9
deps/v8/src/v8.cc

@ -156,6 +156,15 @@ uint32_t V8::Random() {
return (hi << 16) + (lo & 0xFFFF);
}
void V8::IdleNotification(bool is_high_priority) {
if (!FLAG_use_idle_notification) return;
// Ignore high priority instances of V8.
if (is_high_priority) return;
// Uncommit unused memory in new space.
Heap::UncommitFromSpace();
}
Smi* V8::RandomPositiveSmi() {
uint32_t random = Random();

3
deps/v8/src/v8.h

@ -99,6 +99,9 @@ class V8 : public AllStatic {
static uint32_t Random();
static Smi* RandomPositiveSmi();
// Idle notification directly from the API.
static void IdleNotification(bool is_high_priority);
private:
// True if engine is currently running
static bool is_running_;

2
deps/v8/src/version.cc

@ -34,7 +34,7 @@
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 1
#define MINOR_VERSION 3
#define BUILD_NUMBER 3
#define BUILD_NUMBER 4
#define PATCH_LEVEL 0
#define CANDIDATE_VERSION false

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

@ -5258,6 +5258,58 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
}
break;
case Token::SHL:
if (reversed) {
Result constant_operand(value);
LikelySmiBinaryOperation(op, &constant_operand, operand,
overwrite_mode);
} else {
// Only the least significant 5 bits of the shift value are used.
// In the slow case, this masking is done inside the runtime call.
int shift_value = int_value & 0x1f;
operand->ToRegister();
if (shift_value == 0) {
// Spill operand so it can be overwritten in the slow case.
frame_->Spill(operand->reg());
DeferredInlineSmiOperation* deferred =
new DeferredInlineSmiOperation(op,
operand->reg(),
operand->reg(),
smi_value,
overwrite_mode);
__ testl(operand->reg(), Immediate(kSmiTagMask));
deferred->Branch(not_zero);
deferred->BindExit();
frame_->Push(operand);
} else {
// Use a fresh temporary for nonzero shift values.
Result answer = allocator()->Allocate();
ASSERT(answer.is_valid());
DeferredInlineSmiOperation* deferred =
new DeferredInlineSmiOperation(op,
answer.reg(),
operand->reg(),
smi_value,
overwrite_mode);
__ testl(operand->reg(), Immediate(kSmiTagMask));
deferred->Branch(not_zero);
__ movl(answer.reg(), operand->reg());
ASSERT(kSmiTag == 0); // adjust code if not the case
// We do no shifts, only the Smi conversion, if shift_value is 1.
if (shift_value > 1) {
__ shll(answer.reg(), Immediate(shift_value - 1));
}
// Convert int result to Smi, checking that it is in int range.
ASSERT(kSmiTagSize == 1); // adjust code if not the case
__ addl(answer.reg(), answer.reg());
deferred->Branch(overflow);
deferred->BindExit();
operand->Unuse();
frame_->Push(&answer);
}
}
break;
case Token::BIT_OR:
case Token::BIT_XOR:
case Token::BIT_AND: {
@ -6013,6 +6065,8 @@ void Reference::SetValue(InitState init_state) {
__ testl(key.reg(),
Immediate(static_cast<uint32_t>(kSmiTagMask | 0x80000000U)));
deferred->Branch(not_zero);
// Ensure that the smi is zero-extended. This is not guaranteed.
__ movl(key.reg(), key.reg());
// Check that the receiver is not a smi.
__ testl(receiver.reg(), Immediate(kSmiTagMask));
@ -7172,14 +7226,14 @@ void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm) {
__ jmp(&done);
__ bind(&load_smi_1);
__ sar(kScratchRegister, Immediate(kSmiTagSize));
__ sarl(kScratchRegister, Immediate(kSmiTagSize));
__ push(kScratchRegister);
__ fild_s(Operand(rsp, 0));
__ pop(kScratchRegister);
__ jmp(&done_load_1);
__ bind(&load_smi_2);
__ sar(kScratchRegister, Immediate(kSmiTagSize));
__ sarl(kScratchRegister, Immediate(kSmiTagSize));
__ push(kScratchRegister);
__ fild_s(Operand(rsp, 0));
__ pop(kScratchRegister);
@ -7534,7 +7588,7 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
__ j(negative, &non_smi_result);
}
// Tag smi result and return.
ASSERT(kSmiTagSize == times_2); // adjust code if not the case
ASSERT(kSmiTagSize == 1); // adjust code if not the case
__ lea(rax, Operand(rax, rax, times_1, kSmiTag));
__ ret(2 * kPointerSize);

3
deps/v8/src/x64/disasm-x64.cc

@ -105,7 +105,6 @@ static ByteMnemonic two_operands_instr[] = {
static ByteMnemonic zero_operands_instr[] = {
{ 0xC3, UNSET_OP_ORDER, "ret" },
{ 0xC9, UNSET_OP_ORDER, "leave" },
{ 0x90, UNSET_OP_ORDER, "nop" },
{ 0xF4, UNSET_OP_ORDER, "hlt" },
{ 0xCC, UNSET_OP_ORDER, "int3" },
{ 0x60, UNSET_OP_ORDER, "pushad" },
@ -1425,7 +1424,7 @@ int DisassemblerX64::InstructionDecode(v8::internal::Vector<char> out_buffer,
default:
UNREACHABLE();
}
AppendToBuffer("test%c rax,0x%"V8_PTR_PREFIX"ux",
AppendToBuffer("test%c rax,0x%"V8_PTR_PREFIX"x",
operand_size_code(),
value);
break;

10
deps/v8/test/mjsunit/json.js

@ -195,3 +195,13 @@ assertEquals('{"y":6,"x":5}', JSON.stringify({x:5,y:6}, ['y', 'x']));
assertEquals(undefined, JSON.stringify(undefined));
assertEquals(undefined, JSON.stringify(function () { }));
function checkIllegal(str) {
assertThrows(function () { JSON.parse(str); }, SyntaxError);
}
checkIllegal('1); throw "foo"; (1');
var x = 0;
eval("(1); x++; (1)");
checkIllegal('1); x++; (1');

Loading…
Cancel
Save