Browse Source

Upgrade V8 to 2.1.2

v0.7.4-release
Ryan Dahl 15 years ago
parent
commit
b80bdda14e
  1. 8
      deps/v8/ChangeLog
  2. 1
      deps/v8/SConstruct
  3. 4
      deps/v8/src/SConscript
  4. 29
      deps/v8/src/arm/codegen-arm.cc
  5. 12
      deps/v8/src/arm/codegen-arm.h
  6. 35
      deps/v8/src/arm/fast-codegen-arm.cc
  7. 11
      deps/v8/src/ast.h
  8. 3
      deps/v8/src/codegen.cc
  9. 6
      deps/v8/src/codegen.h
  10. 53
      deps/v8/src/compiler.h
  11. 15
      deps/v8/src/debug-delay.js
  12. 3
      deps/v8/src/fast-codegen.cc
  13. 9
      deps/v8/src/fast-codegen.h
  14. 5
      deps/v8/src/frame-element.h
  15. 2
      deps/v8/src/heap.cc
  16. 4
      deps/v8/src/heap.h
  17. 123
      deps/v8/src/ia32/codegen-ia32.cc
  18. 17
      deps/v8/src/ia32/codegen-ia32.h
  19. 748
      deps/v8/src/ia32/fast-codegen-ia32.cc
  20. 155
      deps/v8/src/ia32/fast-codegen-ia32.h
  21. 76
      deps/v8/src/ia32/virtual-frame-ia32.cc
  22. 12
      deps/v8/src/ia32/virtual-frame-ia32.h
  23. 2
      deps/v8/src/jump-target-inl.h
  24. 2
      deps/v8/src/jump-target.cc
  25. 14
      deps/v8/src/macros.py
  26. 11
      deps/v8/src/mips/codegen-mips.cc
  27. 4
      deps/v8/src/mips/codegen-mips.h
  28. 33
      deps/v8/src/mirror-delay.js
  29. 2
      deps/v8/src/objects.h
  30. 2
      deps/v8/src/register-allocator.h
  31. 128
      deps/v8/src/runtime.cc
  32. 7
      deps/v8/src/runtime.js
  33. 2
      deps/v8/src/scopeinfo.cc
  34. 4
      deps/v8/src/serialize.cc
  35. 2
      deps/v8/src/spaces-inl.h
  36. 120
      deps/v8/src/string.js
  37. 14
      deps/v8/src/stub-cache.cc
  38. 6
      deps/v8/src/utils.h
  39. 4
      deps/v8/src/version.cc
  40. 40
      deps/v8/src/x64/assembler-x64.cc
  41. 94
      deps/v8/src/x64/assembler-x64.h
  42. 26
      deps/v8/src/x64/codegen-x64.cc
  43. 12
      deps/v8/src/x64/codegen-x64.h
  44. 38
      deps/v8/src/x64/fast-codegen-x64.cc
  45. 2
      deps/v8/src/x64/macro-assembler-x64.h
  46. 62
      deps/v8/test/mjsunit/bugs/bug-619.js
  47. 37
      deps/v8/test/mjsunit/debug-evaluate.js
  48. 4
      deps/v8/tools/gyp/v8.gyp
  49. 2
      deps/v8/tools/visual_studio/v8_base.vcproj

8
deps/v8/ChangeLog

@ -1,3 +1,11 @@
2010-02-23: Version 2.1.2
Fix a crash bug caused by wrong assert.
Fix a bug with register names on 64-bit V8 (issue 615).
Performance improvements on all platforms.
2010-02-19: Version 2.1.1
[ES5] Implemented Object.defineProperty.

1
deps/v8/SConstruct

@ -267,6 +267,7 @@ V8_EXTRA_FLAGS = {
'gcc': {
'all': {
'WARNINGFLAGS': ['-Wall',
'-Werror',
'-W',
'-Wno-unused-parameter',
'-Wnon-virtual-dtor']

4
deps/v8/src/SConscript

@ -57,7 +57,6 @@ SOURCES = {
disassembler.cc
execution.cc
factory.cc
fast-codegen.cc
flags.cc
frame-element.cc
frames.cc
@ -109,6 +108,7 @@ SOURCES = {
zone.cc
"""),
'arch:arm': Split("""
fast-codegen.cc
arm/builtins-arm.cc
arm/codegen-arm.cc
arm/constants-arm.cc
@ -133,6 +133,7 @@ SOURCES = {
arm/assembler-thumb2.cc
"""),
'arch:mips': Split("""
fast-codegen.cc
mips/assembler-mips.cc
mips/builtins-mips.cc
mips/codegen-mips.cc
@ -169,6 +170,7 @@ SOURCES = {
ia32/virtual-frame-ia32.cc
"""),
'arch:x64': Split("""
fast-codegen.cc
x64/assembler-x64.cc
x64/builtins-x64.cc
x64/codegen-x64.cc

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

@ -142,7 +142,7 @@ Scope* CodeGenerator::scope() { return info_->function()->scope(); }
// r1: called JS function
// cp: callee's context
void CodeGenerator::Generate(CompilationInfo* info, Mode mode) {
void CodeGenerator::Generate(CompilationInfo* info) {
// Record the position for debugging purposes.
CodeForFunctionPosition(info->function());
@ -174,7 +174,7 @@ void CodeGenerator::Generate(CompilationInfo* info, Mode mode) {
}
#endif
if (mode == PRIMARY) {
if (info->mode() == CompilationInfo::PRIMARY) {
frame_->Enter();
// tos: code slot
@ -277,6 +277,12 @@ void CodeGenerator::Generate(CompilationInfo* info, Mode mode) {
frame_->Adjust(4);
allocator_->Unuse(r1);
allocator_->Unuse(lr);
// Bind all the bailout labels to the beginning of the function.
List<CompilationInfo::Bailout*>* bailouts = info->bailouts();
for (int i = 0; i < bailouts->length(); i++) {
__ bind(bailouts->at(i)->label());
}
}
// Initialize the function return target after the locals are set
@ -3420,6 +3426,25 @@ void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
}
void CodeGenerator::GenerateIsRegExp(ZoneList<Expression*>* args) {
VirtualFrame::SpilledScope spilled_scope;
ASSERT(args->length() == 1);
LoadAndSpill(args->at(0));
JumpTarget answer;
// We need the CC bits to come out as not_equal in the case where the
// object is a smi. This can't be done with the usual test opcode so
// we use XOR to get the right CC bits.
frame_->EmitPop(r0);
__ and_(r1, r0, Operand(kSmiTagMask));
__ eor(r1, r1, Operand(kSmiTagMask), SetCC);
answer.Branch(ne);
// It is a heap object - get the map. Check if the object is a regexp.
__ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE);
answer.Bind();
cc_reg_ = eq;
}
void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) {
// This generates a fast version of:
// (typeof(arg) === 'object' || %_ClassOf(arg) == 'RegExp')

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

@ -150,15 +150,6 @@ class CodeGenState BASE_EMBEDDED {
class CodeGenerator: public AstVisitor {
public:
// Compilation mode. Either the compiler is used as the primary
// compiler and needs to setup everything or the compiler is used as
// the secondary compiler for split compilation and has to handle
// bailouts.
enum Mode {
PRIMARY,
SECONDARY
};
// Takes a function literal, generates code for it. This function should only
// be called by compiler.cc.
static Handle<Code> MakeCode(CompilationInfo* info);
@ -244,7 +235,7 @@ class CodeGenerator: public AstVisitor {
inline void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
// Main code generation function
void Generate(CompilationInfo* info, Mode mode);
void Generate(CompilationInfo* info);
// The following are used by class Reference.
void LoadReference(Reference* ref);
@ -359,6 +350,7 @@ class CodeGenerator: public AstVisitor {
void GenerateIsSmi(ZoneList<Expression*>* args);
void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args);
void GenerateIsArray(ZoneList<Expression*>* args);
void GenerateIsRegExp(ZoneList<Expression*>* args);
void GenerateIsObject(ZoneList<Expression*>* args);
void GenerateIsFunction(ZoneList<Expression*>* args);
void GenerateIsUndetectableObject(ZoneList<Expression*>* args);

35
deps/v8/src/arm/fast-codegen-arm.cc

@ -148,17 +148,25 @@ void FastCodeGenerator::EmitBitOr() {
if (!destination().is(no_reg)) {
__ orr(destination(), accumulator1(), Operand(accumulator0()));
}
} else if (destination().is(no_reg)) {
// Result is not needed but do not clobber the operands in case of
// bailout.
__ orr(scratch0(), accumulator1(), Operand(accumulator0()));
__ BranchOnNotSmi(scratch0(), bailout());
} else {
// Preserve the destination operand in a scratch register in case of
// bailout.
__ mov(scratch0(), destination());
__ orr(destination(), accumulator1(), Operand(accumulator0()));
__ BranchOnNotSmi(destination(), bailout());
// Left is in accumulator1, right in accumulator0.
if (destination().is(accumulator0())) {
__ mov(scratch0(), accumulator0());
__ orr(destination(), accumulator1(), Operand(accumulator1()));
Label* bailout =
info()->AddBailout(accumulator1(), scratch0()); // Left, right.
__ BranchOnNotSmi(destination(), bailout);
} else if (destination().is(accumulator1())) {
__ mov(scratch0(), accumulator1());
__ orr(destination(), accumulator1(), Operand(accumulator0()));
Label* bailout = info()->AddBailout(scratch0(), accumulator0());
__ BranchOnNotSmi(destination(), bailout);
} else {
ASSERT(destination().is(no_reg));
__ orr(scratch0(), accumulator1(), Operand(accumulator0()));
Label* bailout = info()->AddBailout(accumulator1(), accumulator0());
__ BranchOnNotSmi(scratch0(), bailout);
}
}
// If we didn't bailout, the result (in fact, both inputs too) is known to
@ -179,6 +187,7 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) {
// Note that we keep a live register reference to cp (context) at
// this point.
Label* bailout_to_beginning = info()->AddBailout();
// Receiver (this) is allocated to a fixed register.
if (info()->has_this_properties()) {
Comment cmnt(masm(), ";; MapCheck(this)");
@ -189,7 +198,7 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) {
Handle<HeapObject> object = Handle<HeapObject>::cast(info()->receiver());
Handle<Map> map(object->map());
EmitLoadReceiver();
__ CheckMap(receiver_reg(), scratch0(), map, bailout(), false);
__ CheckMap(receiver_reg(), scratch0(), map, bailout_to_beginning, false);
}
// If there is a global variable access check if the global object is the
@ -202,7 +211,7 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) {
ASSERT(info()->has_global_object());
Handle<Map> map(info()->global_object()->map());
__ ldr(scratch0(), CodeGenerator::GlobalObject());
__ CheckMap(scratch0(), scratch1(), map, bailout(), true);
__ CheckMap(scratch0(), scratch1(), map, bailout_to_beginning, true);
}
VisitStatements(function()->body());
@ -217,8 +226,6 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) {
int32_t sp_delta = (scope()->num_parameters() + 1) * kPointerSize;
__ add(sp, sp, Operand(sp_delta));
__ Jump(lr);
__ bind(&bailout_);
}

11
deps/v8/src/ast.h

@ -1,4 +1,4 @@
// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@ -199,6 +199,10 @@ class Expression: public AstNode {
// evaluated.
virtual bool IsLeaf() { return false; }
// True if the expression has no side effects and is safe to
// evaluate out of order.
virtual bool IsTrivial() { return false; }
// Mark the expression as being compiled as an expression
// statement. This is used to transform postfix increments to
// (faster) prefix increments.
@ -738,6 +742,7 @@ class Literal: public Expression {
}
virtual bool IsLeaf() { return true; }
virtual bool IsTrivial() { return true; }
// Identity testers.
bool IsNull() const { return handle_.is_identical_to(Factory::null_value()); }
@ -926,6 +931,10 @@ class VariableProxy: public Expression {
return var()->is_global() || var()->rewrite()->IsLeaf();
}
// Reading from a mutable variable is a side effect, but 'this' is
// immutable.
virtual bool IsTrivial() { return is_this(); }
bool IsVariable(Handle<String> n) {
return !is_this() && name().is_identical_to(n);
}

3
deps/v8/src/codegen.cc

@ -248,7 +248,7 @@ Handle<Code> CodeGenerator::MakeCode(CompilationInfo* info) {
CodeGenerator cgen(&masm);
CodeGeneratorScope scope(&cgen);
live_edit_tracker.RecordFunctionScope(info->function()->scope());
cgen.Generate(info, PRIMARY);
cgen.Generate(info);
if (cgen.HasStackOverflow()) {
ASSERT(!Top::has_pending_exception());
return Handle<Code>::null();
@ -360,6 +360,7 @@ CodeGenerator::InlineRuntimeLUT CodeGenerator::kInlineRuntimeLUT[] = {
{&CodeGenerator::GenerateIsSmi, "_IsSmi"},
{&CodeGenerator::GenerateIsNonNegativeSmi, "_IsNonNegativeSmi"},
{&CodeGenerator::GenerateIsArray, "_IsArray"},
{&CodeGenerator::GenerateIsRegExp, "_IsRegExp"},
{&CodeGenerator::GenerateIsConstructCall, "_IsConstructCall"},
{&CodeGenerator::GenerateArgumentsLength, "_ArgumentsLength"},
{&CodeGenerator::GenerateArgumentsAccess, "_Arguments"},

6
deps/v8/src/codegen.h

@ -518,14 +518,14 @@ class CallFunctionStub: public CodeStub {
}
#endif
// Minor key encoding in 31 bits AAAAAAAAAAAAAAAAAAAAAFI A(rgs)F(lag)I(nloop).
// Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
class InLoopBits: public BitField<InLoopFlag, 0, 1> {};
class FlagBits: public BitField<CallFunctionFlags, 1, 1> {};
class ArgcBits: public BitField<int, 2, 29> {};
class ArgcBits: public BitField<int, 2, 32 - 2> {};
Major MajorKey() { return CallFunction; }
int MinorKey() {
// Encode the parameters in a unique 31 bit value.
// Encode the parameters in a unique 32 bit value.
return InLoopBits::encode(in_loop_)
| FlagBits::encode(flags_)
| ArgcBits::encode(argc_);

53
deps/v8/src/compiler.h

@ -41,6 +41,37 @@ namespace internal {
// is constructed based on the resources available at compile-time.
class CompilationInfo BASE_EMBEDDED {
public:
// Compilation mode. Either the compiler is used as the primary
// compiler and needs to setup everything or the compiler is used as
// the secondary compiler for split compilation and has to handle
// bailouts.
enum Mode {
PRIMARY,
SECONDARY
};
// A description of the compilation state at a bailout to the secondary
// code generator.
//
// The state is currently simple: there are no parameters or local
// variables to worry about ('this' can be found in the stack frame).
// There are at most two live values.
//
// There is a label that should be bound to the beginning of the bailout
// stub code.
class Bailout : public ZoneObject {
public:
Bailout(Register left, Register right) : left_(left), right_(right) {}
Label* label() { return &label_; }
private:
Register left_;
Register right_;
Label label_;
};
// Lazy compilation of a JSFunction.
CompilationInfo(Handle<JSFunction> closure,
int loop_nesting,
@ -117,9 +148,13 @@ class CompilationInfo BASE_EMBEDDED {
int loop_nesting() { return loop_nesting_; }
bool has_receiver() { return !receiver_.is_null(); }
Handle<Object> receiver() { return receiver_; }
List<Bailout*>* bailouts() { return &bailouts_; }
// Accessors for mutable fields, possibly set by analysis passes with
// Accessors for mutable fields (possibly set by analysis passes) with
// default values given by Initialize.
Mode mode() { return mode_; }
void set_mode(Mode mode) { mode_ = mode; }
bool has_this_properties() { return has_this_properties_; }
void set_has_this_properties(bool flag) { has_this_properties_ = flag; }
@ -137,8 +172,19 @@ class CompilationInfo BASE_EMBEDDED {
// Derived accessors.
Scope* scope() { return function()->scope(); }
// Add a bailout with two live values.
Label* AddBailout(Register left, Register right) {
Bailout* bailout = new Bailout(left, right);
bailouts_.Add(bailout);
return bailout->label();
}
// Add a bailout with no live values.
Label* AddBailout() { return AddBailout(no_reg, no_reg); }
private:
void Initialize() {
mode_ = PRIMARY;
has_this_properties_ = false;
has_globals_ = false;
}
@ -148,6 +194,7 @@ class CompilationInfo BASE_EMBEDDED {
Handle<Script> script_;
FunctionLiteral* function_;
Mode mode_;
bool is_eval_;
int loop_nesting_;
@ -157,6 +204,10 @@ class CompilationInfo BASE_EMBEDDED {
bool has_this_properties_;
bool has_globals_;
// An ordered list of bailout points encountered during fast-path
// compilation.
List<Bailout*> bailouts_;
DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
};

15
deps/v8/src/debug-delay.js

@ -1202,11 +1202,16 @@ DebugCommandProcessor.prototype.processDebugJSONRequest = function(json_request)
throw new Error('Command not specified');
}
// TODO(yurys): remove request.arguments.compactFormat check once
// ChromeDevTools are switched to 'inlineRefs'
if (request.arguments && (request.arguments.inlineRefs ||
request.arguments.compactFormat)) {
response.setOption('inlineRefs', true);
if (request.arguments) {
var args = request.arguments;
// TODO(yurys): remove request.arguments.compactFormat check once
// ChromeDevTools are switched to 'inlineRefs'
if (args.inlineRefs || args.compactFormat) {
response.setOption('inlineRefs', true);
}
if (!IS_UNDEFINED(args.maxStringLength)) {
response.setOption('maxStringLength', args.maxStringLength);
}
}
if (request.command == 'continue') {

3
deps/v8/src/fast-codegen.cc

@ -456,7 +456,8 @@ Handle<Code> FastCodeGenerator::MakeCode(CompilationInfo* info) {
// macro assembler.
CodeGenerator cgen(&masm);
CodeGeneratorScope scope(&cgen);
cgen.Generate(info, CodeGenerator::SECONDARY);
info->set_mode(CompilationInfo::SECONDARY);
cgen.Generate(info);
if (cgen.HasStackOverflow()) {
ASSERT(!Top::has_pending_exception());
return Handle<Code>::null();

9
deps/v8/src/fast-codegen.h

@ -28,10 +28,15 @@
#ifndef V8_FAST_CODEGEN_H_
#define V8_FAST_CODEGEN_H_
#if V8_TARGET_ARCH_IA32
#include "ia32/fast-codegen-ia32.h"
#else
#include "v8.h"
#include "ast.h"
#include "compiler.h"
#include "list.h"
namespace v8 {
namespace internal {
@ -76,7 +81,6 @@ class FastCodeGenerator: public AstVisitor {
private:
MacroAssembler* masm() { return masm_; }
CompilationInfo* info() { return info_; }
Label* bailout() { return &bailout_; }
Register destination() { return destination_; }
void set_destination(Register reg) { destination_ = reg; }
@ -142,7 +146,6 @@ class FastCodeGenerator: public AstVisitor {
MacroAssembler* masm_;
CompilationInfo* info_;
Label bailout_;
Register destination_;
uint32_t smi_bits_;
@ -152,4 +155,6 @@ class FastCodeGenerator: public AstVisitor {
} } // namespace v8::internal
#endif // V8_TARGET_ARCH_IA32
#endif // V8_FAST_CODEGEN_H_

5
deps/v8/src/frame-element.h

@ -65,6 +65,9 @@ class FrameElement BASE_EMBEDDED {
}
inline void set_number_info(NumberInfo::Type info) {
// Copied elements do not have number info. Instead
// we have to inspect their backing element in the frame.
ASSERT(!is_copy());
value_ = value_ & ~NumberInfoField::mask();
value_ = value_ | NumberInfoField::encode(info);
}
@ -250,7 +253,7 @@ class FrameElement BASE_EMBEDDED {
class CopiedField: public BitField<bool, 3, 1> {};
class SyncedField: public BitField<bool, 4, 1> {};
class NumberInfoField: public BitField<NumberInfo::Type, 5, 3> {};
class DataField: public BitField<uint32_t, 8, 32 - 9> {};
class DataField: public BitField<uint32_t, 8, 32 - 8> {};
friend class VirtualFrame;
};

2
deps/v8/src/heap.cc

@ -4111,7 +4111,7 @@ int KeyedLookupCache::Hash(Map* map, String* name) {
// Uses only lower 32 bits if pointers are larger.
uintptr_t addr_hash =
static_cast<uint32_t>(reinterpret_cast<uintptr_t>(map)) >> kMapHashShift;
return (addr_hash ^ name->Hash()) & kCapacityMask;
return static_cast<uint32_t>((addr_hash ^ name->Hash()) & kCapacityMask);
}

4
deps/v8/src/heap.h

@ -1383,9 +1383,9 @@ class DescriptorLookupCache {
private:
static int Hash(DescriptorArray* array, String* name) {
// Uses only lower 32 bits if pointers are larger.
uintptr_t array_hash =
uint32_t array_hash =
static_cast<uint32_t>(reinterpret_cast<uintptr_t>(array)) >> 2;
uintptr_t name_hash =
uint32_t name_hash =
static_cast<uint32_t>(reinterpret_cast<uintptr_t>(name)) >> 2;
return (array_hash ^ name_hash) % kLength;
}

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

@ -125,7 +125,7 @@ Scope* CodeGenerator::scope() { return info_->function()->scope(); }
// edi: called JS function
// esi: callee's context
void CodeGenerator::Generate(CompilationInfo* info, Mode mode) {
void CodeGenerator::Generate(CompilationInfo* info) {
// Record the position for debugging purposes.
CodeForFunctionPosition(info->function());
@ -164,7 +164,7 @@ void CodeGenerator::Generate(CompilationInfo* info, Mode mode) {
// esi: callee's context
allocator_->Initialize();
if (mode == PRIMARY) {
if (info->mode() == CompilationInfo::PRIMARY) {
frame_->Enter();
// Allocate space for locals and initialize them.
@ -255,6 +255,12 @@ void CodeGenerator::Generate(CompilationInfo* info, Mode mode) {
// frame to match this state.
frame_->Adjust(3);
allocator_->Unuse(edi);
// Bind all the bailout labels to the beginning of the function.
List<CompilationInfo::Bailout*>* bailouts = info->bailouts();
for (int i = 0; i < bailouts->length(); i++) {
__ bind(bailouts->at(i)->label());
}
}
// Initialize the function return target after the locals are set
@ -689,6 +695,11 @@ void CodeGenerator::LoadReference(Reference* ref) {
// The expression is a variable proxy that does not rewrite to a
// property. Global variables are treated as named property references.
if (var->is_global()) {
// If eax is free, the register allocator prefers it. Thus the code
// generator will load the global object into eax, which is where
// LoadIC wants it. Most uses of Reference call LoadIC directly
// after the reference is created.
frame_->Spill(eax);
LoadGlobal();
ref->set_type(Reference::NAMED);
} else {
@ -4307,6 +4318,10 @@ Result CodeGenerator::LoadFromGlobalSlotCheckExtensions(
// All extension objects were empty and it is safe to use a global
// load IC call.
// The register allocator prefers eax if it is free, so the code generator
// will load the global object directly into eax, which is where the LoadIC
// expects it.
frame_->Spill(eax);
LoadGlobal();
frame_->Push(slot->var()->name());
RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
@ -4592,8 +4607,8 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
// Duplicate the object as the IC receiver.
frame_->Dup();
Load(property->value());
frame_->Push(key);
Result ignored = frame_->CallStoreIC();
Result dummy = frame_->CallStoreIC(Handle<String>::cast(key), false);
dummy.Unuse();
break;
}
// Fall through
@ -4762,26 +4777,33 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
Property* prop = node->target()->AsProperty();
ASSERT(var == NULL || (prop == NULL && var->is_global()));
// Initialize name and evaluate the receiver subexpression.
// Initialize name and evaluate the receiver subexpression if necessary.
Handle<String> name;
bool is_trivial_receiver = false;
if (var != NULL) {
name = var->name();
LoadGlobal();
} else {
Literal* lit = prop->key()->AsLiteral();
ASSERT(lit != NULL);
ASSERT_NOT_NULL(lit);
name = Handle<String>::cast(lit->handle());
Load(prop->obj());
// Do not materialize the receiver on the frame if it is trivial.
is_trivial_receiver = prop->obj()->IsTrivial();
if (!is_trivial_receiver) Load(prop->obj());
}
if (node->starts_initialization_block()) {
ASSERT_EQ(NULL, var);
// Change to slow case in the beginning of an initialization block to
// avoid the quadratic behavior of repeatedly adding fast properties.
frame()->Dup();
if (is_trivial_receiver) {
frame()->Push(prop->obj());
} else {
frame()->Dup();
}
Result ignored = frame()->CallRuntime(Runtime::kToSlowProperties, 1);
}
if (node->ends_initialization_block()) {
if (node->ends_initialization_block() && !is_trivial_receiver) {
// Add an extra copy of the receiver to the frame, so that it can be
// converted back to fast case after the assignment.
frame()->Dup();
@ -4789,7 +4811,16 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
// Evaluate the right-hand side.
if (node->is_compound()) {
frame()->Dup();
if (is_trivial_receiver) {
frame()->Push(prop->obj());
} else if (var != NULL) {
// The LoadIC stub expects the object in eax.
// Freeing eax causes the code generator to load the global into it.
frame_->Spill(eax);
LoadGlobal();
} else {
frame()->Dup();
}
Result value = EmitNamedLoad(name, var != NULL);
frame()->Push(&value);
Load(node->value());
@ -4806,23 +4837,34 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
// Perform the assignment. It is safe to ignore constants here.
ASSERT(var == NULL || var->mode() != Variable::CONST);
ASSERT(node->op() != Token::INIT_CONST);
ASSERT_NE(Token::INIT_CONST, node->op());
if (is_trivial_receiver) {
Result value = frame()->Pop();
frame()->Push(prop->obj());
frame()->Push(&value);
}
CodeForSourcePosition(node->position());
Result answer = EmitNamedStore(name);
bool is_contextual = (var != NULL);
Result answer = EmitNamedStore(name, is_contextual);
frame()->Push(&answer);
if (node->ends_initialization_block()) {
// The argument to the runtime call is the extra copy of the receiver,
// which is below the value of the assignment. Swap the receiver and
// the value of the assignment expression.
Result result = frame()->Pop();
Result receiver = frame()->Pop();
frame()->Push(&result);
frame()->Push(&receiver);
ASSERT_EQ(NULL, var);
// The argument to the runtime call is the receiver.
if (is_trivial_receiver) {
frame()->Push(prop->obj());
} else {
// A copy of the receiver is below the value of the assignment. Swap
// the receiver and the value of the assignment expression.
Result result = frame()->Pop();
Result receiver = frame()->Pop();
frame()->Push(&result);
frame()->Push(&receiver);
}
Result ignored = frame_->CallRuntime(Runtime::kToFastProperties, 1);
}
ASSERT(frame()->height() == original_height + 1);
ASSERT_EQ(frame()->height(), original_height + 1);
}
@ -4832,7 +4874,7 @@ void CodeGenerator::EmitKeyedPropertyAssignment(Assignment* node) {
#endif
Comment cmnt(masm_, "[ Named Property Assignment");
Property* prop = node->target()->AsProperty();
ASSERT(prop != NULL);
ASSERT_NOT_NULL(prop);
// Evaluate the receiver subexpression.
Load(prop->obj());
@ -5399,6 +5441,25 @@ void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
}
void CodeGenerator::GenerateIsRegExp(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
Load(args->at(0));
Result value = frame_->Pop();
value.ToRegister();
ASSERT(value.is_valid());
__ test(value.reg(), Immediate(kSmiTagMask));
destination()->false_target()->Branch(equal);
// It is a heap object - get map.
Result temp = allocator()->Allocate();
ASSERT(temp.is_valid());
// Check if the object is a regexp.
__ CmpObjectType(value.reg(), JS_REGEXP_TYPE, temp.reg());
value.Unuse();
temp.Unuse();
destination()->Split(equal);
}
void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) {
// This generates a fast version of:
// (typeof(arg) === 'object' || %_ClassOf(arg) == 'RegExp')
@ -6347,13 +6408,10 @@ void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
__ movzx_b(temp.reg(), FieldOperand(temp.reg(), Map::kBitFieldOffset));
__ test(temp.reg(), Immediate(1 << Map::kIsUndetectable));
destination()->false_target()->Branch(not_zero);
__ mov(temp.reg(), FieldOperand(answer.reg(), HeapObject::kMapOffset));
__ movzx_b(temp.reg(),
FieldOperand(temp.reg(), Map::kInstanceTypeOffset));
__ cmp(temp.reg(), FIRST_NONSTRING_TYPE);
__ CmpObjectType(answer.reg(), FIRST_NONSTRING_TYPE, temp.reg());
temp.Unuse();
answer.Unuse();
destination()->Split(less);
destination()->Split(below);
} else if (check->Equals(Heap::boolean_symbol())) {
__ cmp(answer.reg(), Factory::true_value());
@ -6734,14 +6792,13 @@ Result CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) {
}
Result CodeGenerator::EmitNamedStore(Handle<String> name) {
Result CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) {
#ifdef DEBUG
int original_height = frame()->height();
int expected_height = frame()->height() - (is_contextual ? 1 : 2);
#endif
frame()->Push(name);
Result result = frame()->CallStoreIC();
Result result = frame()->CallStoreIC(name, is_contextual);
ASSERT(frame()->height() == original_height - 2);
ASSERT_EQ(expected_height, frame()->height());
return result;
}
@ -7058,7 +7115,7 @@ void Reference::SetValue(InitState init_state) {
case NAMED: {
Comment cmnt(masm, "[ Store to named Property");
Result answer = cgen_->EmitNamedStore(GetName());
Result answer = cgen_->EmitNamedStore(GetName(), false);
cgen_->frame()->Push(&answer);
set_unloaded();
break;

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

@ -294,15 +294,6 @@ enum ArgumentsAllocationMode {
class CodeGenerator: public AstVisitor {
public:
// Compilation mode. Either the compiler is used as the primary
// compiler and needs to setup everything or the compiler is used as
// the secondary compiler for split compilation and has to handle
// bailouts.
enum Mode {
PRIMARY,
SECONDARY
};
// Takes a function literal, generates code for it. This function should only
// be called by compiler.cc.
static Handle<Code> MakeCode(CompilationInfo* info);
@ -384,7 +375,7 @@ class CodeGenerator: public AstVisitor {
void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
// Main code generation function
void Generate(CompilationInfo* info, Mode mode);
void Generate(CompilationInfo* info);
// Generate the return sequence code. Should be called no more than
// once per compiled function, immediately after binding the return
@ -447,8 +438,9 @@ class CodeGenerator: public AstVisitor {
// Receiver is passed on the frame and consumed.
Result EmitNamedLoad(Handle<String> name, bool is_contextual);
// Reciever and value are passed on the frame and consumed.
Result EmitNamedStore(Handle<String> name);
// If the store is contextual, value is passed on the frame and consumed.
// Otherwise, receiver and value are passed on the frame and consumed.
Result EmitNamedStore(Handle<String> name, bool is_contextual);
// Receiver and key are passed on the frame and consumed.
Result EmitKeyedLoad();
@ -551,6 +543,7 @@ class CodeGenerator: public AstVisitor {
void GenerateIsSmi(ZoneList<Expression*>* args);
void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args);
void GenerateIsArray(ZoneList<Expression*>* args);
void GenerateIsRegExp(ZoneList<Expression*>* args);
void GenerateIsObject(ZoneList<Expression*>* args);
void GenerateIsFunction(ZoneList<Expression*>* args);
void GenerateIsUndetectableObject(ZoneList<Expression*>* args);

748
deps/v8/src/ia32/fast-codegen-ia32.cc

@ -29,12 +29,445 @@
#include "codegen-inl.h"
#include "fast-codegen.h"
#include "data-flow.h"
#include "scopes.h"
namespace v8 {
namespace internal {
#define BAILOUT(reason) \
do { \
if (FLAG_trace_bailout) { \
PrintF("%s\n", reason); \
} \
has_supported_syntax_ = false; \
return; \
} while (false)
#define CHECK_BAILOUT \
do { \
if (!has_supported_syntax_) return; \
} while (false)
void FastCodeGenSyntaxChecker::Check(CompilationInfo* info) {
info_ = info;
// We do not specialize if we do not have a receiver or if it is not a
// JS object with fast mode properties.
if (!info->has_receiver()) BAILOUT("No receiver");
if (!info->receiver()->IsJSObject()) BAILOUT("Receiver is not an object");
Handle<JSObject> object = Handle<JSObject>::cast(info->receiver());
if (!object->HasFastProperties()) BAILOUT("Receiver is in dictionary mode");
// We do not support stack or heap slots (both of which require
// allocation).
Scope* scope = info->scope();
if (scope->num_stack_slots() > 0) {
BAILOUT("Function has stack-allocated locals");
}
if (scope->num_heap_slots() > 0) {
BAILOUT("Function has context-allocated locals");
}
VisitDeclarations(scope->declarations());
CHECK_BAILOUT;
// We do not support empty function bodies.
if (info->function()->body()->is_empty()) {
BAILOUT("Function has an empty body");
}
VisitStatements(info->function()->body());
}
void FastCodeGenSyntaxChecker::VisitDeclarations(
ZoneList<Declaration*>* decls) {
if (!decls->is_empty()) BAILOUT("Function has declarations");
}
void FastCodeGenSyntaxChecker::VisitStatements(ZoneList<Statement*>* stmts) {
if (stmts->length() != 1) {
BAILOUT("Function body is not a singleton statement.");
}
Visit(stmts->at(0));
}
void FastCodeGenSyntaxChecker::VisitDeclaration(Declaration* decl) {
UNREACHABLE();
}
void FastCodeGenSyntaxChecker::VisitBlock(Block* stmt) {
VisitStatements(stmt->statements());
}
void FastCodeGenSyntaxChecker::VisitExpressionStatement(
ExpressionStatement* stmt) {
Visit(stmt->expression());
}
void FastCodeGenSyntaxChecker::VisitEmptyStatement(EmptyStatement* stmt) {
// Supported.
}
void FastCodeGenSyntaxChecker::VisitIfStatement(IfStatement* stmt) {
BAILOUT("IfStatement");
}
void FastCodeGenSyntaxChecker::VisitContinueStatement(ContinueStatement* stmt) {
BAILOUT("Continuestatement");
}
void FastCodeGenSyntaxChecker::VisitBreakStatement(BreakStatement* stmt) {
BAILOUT("BreakStatement");
}
void FastCodeGenSyntaxChecker::VisitReturnStatement(ReturnStatement* stmt) {
BAILOUT("ReturnStatement");
}
void FastCodeGenSyntaxChecker::VisitWithEnterStatement(
WithEnterStatement* stmt) {
BAILOUT("WithEnterStatement");
}
void FastCodeGenSyntaxChecker::VisitWithExitStatement(WithExitStatement* stmt) {
BAILOUT("WithExitStatement");
}
void FastCodeGenSyntaxChecker::VisitSwitchStatement(SwitchStatement* stmt) {
BAILOUT("SwitchStatement");
}
void FastCodeGenSyntaxChecker::VisitDoWhileStatement(DoWhileStatement* stmt) {
BAILOUT("DoWhileStatement");
}
void FastCodeGenSyntaxChecker::VisitWhileStatement(WhileStatement* stmt) {
BAILOUT("WhileStatement");
}
void FastCodeGenSyntaxChecker::VisitForStatement(ForStatement* stmt) {
BAILOUT("ForStatement");
}
void FastCodeGenSyntaxChecker::VisitForInStatement(ForInStatement* stmt) {
BAILOUT("ForInStatement");
}
void FastCodeGenSyntaxChecker::VisitTryCatchStatement(TryCatchStatement* stmt) {
BAILOUT("TryCatchStatement");
}
void FastCodeGenSyntaxChecker::VisitTryFinallyStatement(
TryFinallyStatement* stmt) {
BAILOUT("TryFinallyStatement");
}
void FastCodeGenSyntaxChecker::VisitDebuggerStatement(
DebuggerStatement* stmt) {
BAILOUT("DebuggerStatement");
}
void FastCodeGenSyntaxChecker::VisitFunctionLiteral(FunctionLiteral* expr) {
BAILOUT("FunctionLiteral");
}
void FastCodeGenSyntaxChecker::VisitFunctionBoilerplateLiteral(
FunctionBoilerplateLiteral* expr) {
BAILOUT("FunctionBoilerplateLiteral");
}
void FastCodeGenSyntaxChecker::VisitConditional(Conditional* expr) {
BAILOUT("Conditional");
}
void FastCodeGenSyntaxChecker::VisitSlot(Slot* expr) {
UNREACHABLE();
}
void FastCodeGenSyntaxChecker::VisitVariableProxy(VariableProxy* expr) {
// Only global variable references are supported.
Variable* var = expr->var();
if (!var->is_global() || var->is_this()) BAILOUT("Non-global variable");
// Check if the global variable is existing and non-deletable.
if (info()->has_global_object()) {
LookupResult lookup;
info()->global_object()->Lookup(*expr->name(), &lookup);
if (!lookup.IsProperty()) {
BAILOUT("Non-existing global variable");
}
// We do not handle global variables with accessors or interceptors.
if (lookup.type() != NORMAL) {
BAILOUT("Global variable with accessors or interceptors.");
}
// We do not handle deletable global variables.
if (!lookup.IsDontDelete()) {
BAILOUT("Deletable global variable");
}
}
}
void FastCodeGenSyntaxChecker::VisitLiteral(Literal* expr) {
BAILOUT("Literal");
}
void FastCodeGenSyntaxChecker::VisitRegExpLiteral(RegExpLiteral* expr) {
BAILOUT("RegExpLiteral");
}
void FastCodeGenSyntaxChecker::VisitObjectLiteral(ObjectLiteral* expr) {
BAILOUT("ObjectLiteral");
}
void FastCodeGenSyntaxChecker::VisitArrayLiteral(ArrayLiteral* expr) {
BAILOUT("ArrayLiteral");
}
void FastCodeGenSyntaxChecker::VisitCatchExtensionObject(
CatchExtensionObject* expr) {
BAILOUT("CatchExtensionObject");
}
void FastCodeGenSyntaxChecker::VisitAssignment(Assignment* expr) {
// Simple assignments to (named) this properties are supported.
if (expr->op() != Token::ASSIGN) BAILOUT("Non-simple assignment");
Property* prop = expr->target()->AsProperty();
if (prop == NULL) BAILOUT("Non-property assignment");
VariableProxy* proxy = prop->obj()->AsVariableProxy();
if (proxy == NULL || !proxy->var()->is_this()) {
BAILOUT("Non-this-property assignment");
}
if (!prop->key()->IsPropertyName()) {
BAILOUT("Non-named-property assignment");
}
// We will only specialize for fields on the object itself.
// Expression::IsPropertyName implies that the name is a literal
// symbol but we do not assume that.
Literal* key = prop->key()->AsLiteral();
if (key != NULL && key->handle()->IsString()) {
Handle<Object> receiver = info()->receiver();
Handle<String> name = Handle<String>::cast(key->handle());
LookupResult lookup;
receiver->Lookup(*name, &lookup);
if (!lookup.IsProperty()) {
BAILOUT("Assigned property not found at compile time");
}
if (lookup.holder() != *receiver) BAILOUT("Non-own property assignment");
if (!lookup.type() == FIELD) BAILOUT("Non-field property assignment");
} else {
UNREACHABLE();
BAILOUT("Unexpected non-string-literal property key");
}
Visit(expr->value());
}
void FastCodeGenSyntaxChecker::VisitThrow(Throw* expr) {
BAILOUT("Throw");
}
void FastCodeGenSyntaxChecker::VisitProperty(Property* expr) {
// We support named this property references.
VariableProxy* proxy = expr->obj()->AsVariableProxy();
if (proxy == NULL || !proxy->var()->is_this()) {
BAILOUT("Non-this-property reference");
}
if (!expr->key()->IsPropertyName()) {
BAILOUT("Non-named-property reference");
}
// We will only specialize for fields on the object itself.
// Expression::IsPropertyName implies that the name is a literal
// symbol but we do not assume that.
Literal* key = expr->key()->AsLiteral();
if (key != NULL && key->handle()->IsString()) {
Handle<Object> receiver = info()->receiver();
Handle<String> name = Handle<String>::cast(key->handle());
LookupResult lookup;
receiver->Lookup(*name, &lookup);
if (!lookup.IsProperty()) {
BAILOUT("Referenced property not found at compile time");
}
if (lookup.holder() != *receiver) BAILOUT("Non-own property reference");
if (!lookup.type() == FIELD) BAILOUT("Non-field property reference");
} else {
UNREACHABLE();
BAILOUT("Unexpected non-string-literal property key");
}
}
void FastCodeGenSyntaxChecker::VisitCall(Call* expr) {
BAILOUT("Call");
}
void FastCodeGenSyntaxChecker::VisitCallNew(CallNew* expr) {
BAILOUT("CallNew");
}
void FastCodeGenSyntaxChecker::VisitCallRuntime(CallRuntime* expr) {
BAILOUT("CallRuntime");
}
void FastCodeGenSyntaxChecker::VisitUnaryOperation(UnaryOperation* expr) {
BAILOUT("UnaryOperation");
}
void FastCodeGenSyntaxChecker::VisitCountOperation(CountOperation* expr) {
BAILOUT("CountOperation");
}
void FastCodeGenSyntaxChecker::VisitBinaryOperation(BinaryOperation* expr) {
// We support bitwise OR.
switch (expr->op()) {
case Token::COMMA:
BAILOUT("BinaryOperation COMMA");
case Token::OR:
BAILOUT("BinaryOperation OR");
case Token::AND:
BAILOUT("BinaryOperation AND");
case Token::BIT_OR:
// We support expressions nested on the left because they only require
// a pair of registers to keep all intermediate values in registers
// (i.e., the expression stack has height no more than two).
if (!expr->right()->IsLeaf()) BAILOUT("expression nested on right");
// We do not allow subexpressions with side effects because we
// (currently) bail out to the beginning of the full function. The
// only expressions with side effects that we would otherwise handle
// are assignments.
if (expr->left()->AsAssignment() != NULL ||
expr->right()->AsAssignment() != NULL) {
BAILOUT("subexpression of binary operation has side effects");
}
Visit(expr->left());
CHECK_BAILOUT;
Visit(expr->right());
break;
case Token::BIT_XOR:
BAILOUT("BinaryOperation BIT_XOR");
case Token::BIT_AND:
BAILOUT("BinaryOperation BIT_AND");
case Token::SHL:
BAILOUT("BinaryOperation SHL");
case Token::SAR:
BAILOUT("BinaryOperation SAR");
case Token::SHR:
BAILOUT("BinaryOperation SHR");
case Token::ADD:
BAILOUT("BinaryOperation ADD");
case Token::SUB:
BAILOUT("BinaryOperation SUB");
case Token::MUL:
BAILOUT("BinaryOperation MUL");
case Token::DIV:
BAILOUT("BinaryOperation DIV");
case Token::MOD:
BAILOUT("BinaryOperation MOD");
default:
UNREACHABLE();
}
}
void FastCodeGenSyntaxChecker::VisitCompareOperation(CompareOperation* expr) {
BAILOUT("CompareOperation");
}
void FastCodeGenSyntaxChecker::VisitThisFunction(ThisFunction* expr) {
BAILOUT("ThisFunction");
}
#undef BAILOUT
#undef CHECK_BAILOUT
#define __ ACCESS_MASM(masm())
Handle<Code> FastCodeGenerator::MakeCode(CompilationInfo* info) {
// Label the AST before calling MakeCodePrologue, so AST node numbers are
// printed with the AST.
AstLabeler labeler;
labeler.Label(info);
LivenessAnalyzer analyzer;
analyzer.Analyze(info->function());
CodeGenerator::MakeCodePrologue(info);
const int kInitialBufferSize = 4 * KB;
MacroAssembler masm(NULL, kInitialBufferSize);
// Generate the fast-path code.
FastCodeGenerator fast_cgen(&masm);
fast_cgen.Generate(info);
if (fast_cgen.HasStackOverflow()) {
ASSERT(!Top::has_pending_exception());
return Handle<Code>::null();
}
// Generate the full code for the function in bailout mode, using the same
// macro assembler.
CodeGenerator cgen(&masm);
CodeGeneratorScope scope(&cgen);
info->set_mode(CompilationInfo::SECONDARY);
cgen.Generate(info);
if (cgen.HasStackOverflow()) {
ASSERT(!Top::has_pending_exception());
return Handle<Code>::null();
}
Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, NOT_IN_LOOP);
return CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
}
Register FastCodeGenerator::accumulator0() { return eax; }
Register FastCodeGenerator::accumulator1() { return edx; }
Register FastCodeGenerator::scratch0() { return ecx; }
@ -155,20 +588,27 @@ void FastCodeGenerator::EmitBitOr() {
// commutative.
__ or_(destination(), Operand(other_accumulator(destination())));
}
} else if (destination().is(no_reg)) {
// Result is not needed but do not clobber the operands in case of
// bailout.
__ mov(scratch0(), accumulator1());
__ or_(scratch0(), Operand(accumulator0()));
__ test(scratch0(), Immediate(kSmiTagMask));
__ j(not_zero, bailout(), not_taken);
} else {
// Preserve the destination operand in a scratch register in case of
// bailout.
__ mov(scratch0(), destination());
__ or_(destination(), Operand(other_accumulator(destination())));
__ test(destination(), Immediate(kSmiTagMask));
__ j(not_zero, bailout(), not_taken);
// Left is in accumulator1, right in accumulator0.
Label* bailout = NULL;
if (destination().is(accumulator0())) {
__ mov(scratch0(), accumulator0());
__ or_(destination(), Operand(accumulator1())); // Or is commutative.
__ test(destination(), Immediate(kSmiTagMask));
bailout = info()->AddBailout(accumulator1(), scratch0()); // Left, right.
} else if (destination().is(accumulator1())) {
__ mov(scratch0(), accumulator1());
__ or_(destination(), Operand(accumulator0()));
__ test(destination(), Immediate(kSmiTagMask));
bailout = info()->AddBailout(scratch0(), accumulator0());
} else {
ASSERT(destination().is(no_reg));
__ mov(scratch0(), accumulator1());
__ or_(scratch0(), Operand(accumulator0()));
__ test(scratch0(), Immediate(kSmiTagMask));
bailout = info()->AddBailout(accumulator1(), accumulator0());
}
__ j(not_zero, bailout, not_taken);
}
// If we didn't bailout, the result (in fact, both inputs too) is known to
@ -191,6 +631,7 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) {
// Note that we keep a live register reference to esi (context) at this
// point.
Label* bailout_to_beginning = info()->AddBailout();
// Receiver (this) is allocated to a fixed register.
if (info()->has_this_properties()) {
Comment cmnt(masm(), ";; MapCheck(this)");
@ -201,7 +642,7 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) {
Handle<HeapObject> object = Handle<HeapObject>::cast(info()->receiver());
Handle<Map> map(object->map());
EmitLoadReceiver();
__ CheckMap(receiver_reg(), map, bailout(), false);
__ CheckMap(receiver_reg(), map, bailout_to_beginning, false);
}
// If there is a global variable access check if the global object is the
@ -214,7 +655,7 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) {
ASSERT(info()->has_global_object());
Handle<Map> map(info()->global_object()->map());
__ mov(scratch0(), CodeGenerator::GlobalObject());
__ CheckMap(scratch0(), map, bailout(), true);
__ CheckMap(scratch0(), map, bailout_to_beginning, true);
}
VisitStatements(function()->body());
@ -227,11 +668,286 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) {
__ mov(esp, ebp);
__ pop(ebp);
__ ret((scope()->num_parameters() + 1) * kPointerSize);
}
void FastCodeGenerator::VisitDeclaration(Declaration* decl) {
UNREACHABLE();
}
void FastCodeGenerator::VisitBlock(Block* stmt) {
VisitStatements(stmt->statements());
}
void FastCodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
Visit(stmt->expression());
}
void FastCodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
// Nothing to do.
}
void FastCodeGenerator::VisitIfStatement(IfStatement* stmt) {
UNREACHABLE();
}
void FastCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
UNREACHABLE();
}
void FastCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
UNREACHABLE();
}
void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
UNREACHABLE();
}
void FastCodeGenerator::VisitWithEnterStatement(WithEnterStatement* stmt) {
UNREACHABLE();
}
void FastCodeGenerator::VisitWithExitStatement(WithExitStatement* stmt) {
UNREACHABLE();
}
void FastCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
UNREACHABLE();
}
void FastCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
UNREACHABLE();
}
void FastCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
UNREACHABLE();
}
void FastCodeGenerator::VisitForStatement(ForStatement* stmt) {
UNREACHABLE();
}
void FastCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
UNREACHABLE();
}
void FastCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
UNREACHABLE();
}
void FastCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
UNREACHABLE();
}
void FastCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
UNREACHABLE();
}
void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
UNREACHABLE();
}
__ bind(&bailout_);
void FastCodeGenerator::VisitFunctionBoilerplateLiteral(
FunctionBoilerplateLiteral* expr) {
UNREACHABLE();
}
void FastCodeGenerator::VisitConditional(Conditional* expr) {
UNREACHABLE();
}
void FastCodeGenerator::VisitSlot(Slot* expr) {
UNREACHABLE();
}
void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
ASSERT(expr->var()->is_global() && !expr->var()->is_this());
// Check if we can compile a global variable load directly from the cell.
ASSERT(info()->has_global_object());
LookupResult lookup;
info()->global_object()->Lookup(*expr->name(), &lookup);
// We only support normal (non-accessor/interceptor) DontDelete properties
// for now.
ASSERT(lookup.IsProperty());
ASSERT_EQ(NORMAL, lookup.type());
ASSERT(lookup.IsDontDelete());
Handle<Object> cell(info()->global_object()->GetPropertyCell(&lookup));
// Global variable lookups do not have side effects, so we do not need to
// emit code if we are in an effect context.
if (!destination().is(no_reg)) {
Comment cmnt(masm(), ";; Global");
if (FLAG_print_ir) {
SmartPointer<char> name = expr->name()->ToCString();
PrintF("%d: t%d = Global(%s) // last_use = %d\n", expr->num(),
expr->num(), *name, expr->var_def()->last_use()->num());
}
EmitGlobalVariableLoad(cell);
}
}
void FastCodeGenerator::VisitLiteral(Literal* expr) {
UNREACHABLE();
}
void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
UNREACHABLE();
}
void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
UNREACHABLE();
}
void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
UNREACHABLE();
}
void FastCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) {
UNREACHABLE();
}
void FastCodeGenerator::VisitAssignment(Assignment* expr) {
// Known to be a simple this property assignment. Effectively a unary
// operation.
{ Register my_destination = destination();
set_destination(accumulator0());
Visit(expr->value());
set_destination(my_destination);
}
Property* prop = expr->target()->AsProperty();
ASSERT_NOT_NULL(prop);
ASSERT_NOT_NULL(prop->obj()->AsVariableProxy());
ASSERT(prop->obj()->AsVariableProxy()->var()->is_this());
ASSERT(prop->key()->IsPropertyName());
Handle<String> name =
Handle<String>::cast(prop->key()->AsLiteral()->handle());
Comment cmnt(masm(), ";; Store to this");
if (FLAG_print_ir) {
SmartPointer<char> name_string = name->ToCString();
PrintF("%d: ", expr->num());
if (!destination().is(no_reg)) PrintF("t%d = ", expr->num());
PrintF("Store(this, \"%s\", t%d) // last_use(this) = %d\n", *name_string,
expr->value()->num(),
expr->var_def()->last_use()->num());
}
EmitThisPropertyStore(name);
}
void FastCodeGenerator::VisitThrow(Throw* expr) {
UNREACHABLE();
}
void FastCodeGenerator::VisitProperty(Property* expr) {
ASSERT_NOT_NULL(expr->obj()->AsVariableProxy());
ASSERT(expr->obj()->AsVariableProxy()->var()->is_this());
ASSERT(expr->key()->IsPropertyName());
if (!destination().is(no_reg)) {
Handle<String> name =
Handle<String>::cast(expr->key()->AsLiteral()->handle());
Comment cmnt(masm(), ";; Load from this");
if (FLAG_print_ir) {
SmartPointer<char> name_string = name->ToCString();
PrintF("%d: t%d = Load(this, \"%s\") // last_use(this) = %d\n",
expr->num(), expr->num(), *name_string,
expr->var_def()->last_use()->num());
}
EmitThisPropertyLoad(name);
}
}
void FastCodeGenerator::VisitCall(Call* expr) {
UNREACHABLE();
}
void FastCodeGenerator::VisitCallNew(CallNew* expr) {
UNREACHABLE();
}
void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
UNREACHABLE();
}
void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
UNREACHABLE();
}
void FastCodeGenerator::VisitCountOperation(CountOperation* expr) {
UNREACHABLE();
}
void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
// We support limited binary operations: bitwise OR only allowed to be
// nested on the left.
ASSERT(expr->op() == Token::BIT_OR);
ASSERT(expr->right()->IsLeaf());
{ Register my_destination = destination();
set_destination(accumulator1());
Visit(expr->left());
set_destination(accumulator0());
Visit(expr->right());
set_destination(my_destination);
}
Comment cmnt(masm(), ";; BIT_OR");
if (FLAG_print_ir) {
PrintF("%d: ", expr->num());
if (!destination().is(no_reg)) PrintF("t%d = ", expr->num());
PrintF("BIT_OR(t%d, t%d)\n", expr->left()->num(), expr->right()->num());
}
EmitBitOr();
}
void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
UNREACHABLE();
}
void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) {
UNREACHABLE();
}
#undef __

155
deps/v8/src/ia32/fast-codegen-ia32.h

@ -0,0 +1,155 @@
// 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_FAST_CODEGEN_IA32_H_
#define V8_FAST_CODEGEN_IA32_H_
#include "v8.h"
#include "ast.h"
#include "compiler.h"
#include "list.h"
namespace v8 {
namespace internal {
class FastCodeGenSyntaxChecker: public AstVisitor {
public:
explicit FastCodeGenSyntaxChecker()
: info_(NULL), has_supported_syntax_(true) {
}
void Check(CompilationInfo* info);
CompilationInfo* info() { return info_; }
bool has_supported_syntax() { return has_supported_syntax_; }
private:
void VisitDeclarations(ZoneList<Declaration*>* decls);
void VisitStatements(ZoneList<Statement*>* stmts);
// AST node visit functions.
#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
AST_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT
CompilationInfo* info_;
bool has_supported_syntax_;
DISALLOW_COPY_AND_ASSIGN(FastCodeGenSyntaxChecker);
};
class FastCodeGenerator: public AstVisitor {
public:
explicit FastCodeGenerator(MacroAssembler* masm)
: masm_(masm), info_(NULL), destination_(no_reg), smi_bits_(0) {
}
static Handle<Code> MakeCode(CompilationInfo* info);
void Generate(CompilationInfo* compilation_info);
private:
MacroAssembler* masm() { return masm_; }
CompilationInfo* info() { return info_; }
Register destination() { return destination_; }
void set_destination(Register reg) { destination_ = reg; }
FunctionLiteral* function() { return info_->function(); }
Scope* scope() { return info_->scope(); }
// Platform-specific fixed registers, all guaranteed distinct.
Register accumulator0();
Register accumulator1();
Register scratch0();
Register scratch1();
Register receiver_reg();
Register context_reg();
Register other_accumulator(Register reg) {
ASSERT(reg.is(accumulator0()) || reg.is(accumulator1()));
return (reg.is(accumulator0())) ? accumulator1() : accumulator0();
}
// Flags are true if the respective register is statically known to hold a
// smi. We do not track every register, only the accumulator registers.
bool is_smi(Register reg) {
ASSERT(!reg.is(no_reg));
return (smi_bits_ & reg.bit()) != 0;
}
void set_as_smi(Register reg) {
ASSERT(!reg.is(no_reg));
smi_bits_ = smi_bits_ | reg.bit();
}
void clear_as_smi(Register reg) {
ASSERT(!reg.is(no_reg));
smi_bits_ = smi_bits_ & ~reg.bit();
}
// AST node visit functions.
#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
AST_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT
// Emit code to load the receiver from the stack into receiver_reg.
void EmitLoadReceiver();
// Emit code to load a global variable directly from a global property
// cell into the destination register.
void EmitGlobalVariableLoad(Handle<Object> cell);
// Emit a store to an own property of this. The stored value is expected
// in accumulator0 and the receiver in receiver_reg. The receiver
// register is preserved and the result (the stored value) is left in the
// destination register.
void EmitThisPropertyStore(Handle<String> name);
// Emit a load from an own property of this. The receiver is expected in
// receiver_reg. The receiver register is preserved and the result is
// left in the destination register.
void EmitThisPropertyLoad(Handle<String> name);
// Emit a bitwise or operation. The left operand is in accumulator1 and
// the right is in accumulator0. The result should be left in the
// destination register.
void EmitBitOr();
MacroAssembler* masm_;
CompilationInfo* info_;
Register destination_;
uint32_t smi_bits_;
DISALLOW_COPY_AND_ASSIGN(FastCodeGenerator);
};
} } // namespace v8::internal
#endif // V8_FAST_CODEGEN_IA32_H_

76
deps/v8/src/ia32/virtual-frame-ia32.cc

@ -948,47 +948,38 @@ Result VirtualFrame::CallKeyedLoadIC(RelocInfo::Mode mode) {
}
Result VirtualFrame::CallStoreIC() {
// Name, value, and receiver are on top of the frame. The IC
// expects name in ecx, value in eax, and receiver in edx.
Result VirtualFrame::CallStoreIC(Handle<String> name, bool is_contextual) {
// Value and (if not contextual) receiver are on top of the frame.
// The IC expects name in ecx, value in eax, and receiver in edx.
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
Result name = Pop();
Result value = Pop();
Result receiver = Pop();
PrepareForCall(0, 0);
if (is_contextual) {
PrepareForCall(0, 0);
value.ToRegister(eax);
__ mov(edx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
__ mov(ecx, name);
} else {
Result receiver = Pop();
PrepareForCall(0, 0);
// Optimized for case in which name is a constant value.
if (name.is_register() && (name.reg().is(edx) || name.reg().is(eax))) {
if (!is_used(ecx)) {
name.ToRegister(ecx);
} else if (!is_used(ebx)) {
name.ToRegister(ebx);
} else {
ASSERT(!is_used(edi)); // Only three results are live, so edi is free.
name.ToRegister(edi);
}
}
// Now name is not in edx or eax, so we can fix them, then move name to ecx.
if (value.is_register() && value.reg().is(edx)) {
if (receiver.is_register() && receiver.reg().is(eax)) {
// Wrong registers.
__ xchg(eax, edx);
if (value.is_register() && value.reg().is(edx)) {
if (receiver.is_register() && receiver.reg().is(eax)) {
// Wrong registers.
__ xchg(eax, edx);
} else {
// Register eax is free for value, which frees edx for receiver.
value.ToRegister(eax);
receiver.ToRegister(edx);
}
} else {
// Register eax is free for value, which frees edx for receiver.
value.ToRegister(eax);
// Register edx is free for receiver, which guarantees eax is free for
// value.
receiver.ToRegister(edx);
value.ToRegister(eax);
}
} else {
// Register edx is free for receiver, which guarantees eax is free for
// value.
receiver.ToRegister(edx);
value.ToRegister(eax);
}
// Receiver and value are in the right place, so ecx is free for name.
name.ToRegister(ecx);
name.Unuse();
__ mov(ecx, name);
value.Unuse();
receiver.Unuse();
return RawCallCodeObject(ic, RelocInfo::CODE_TARGET);
}
@ -1175,6 +1166,25 @@ void VirtualFrame::EmitPush(Immediate immediate, NumberInfo::Type info) {
}
void VirtualFrame::Push(Expression* expr) {
ASSERT(expr->IsTrivial());
Literal* lit = expr->AsLiteral();
if (lit != NULL) {
Push(lit->handle());
return;
}
VariableProxy* proxy = expr->AsVariableProxy();
if (proxy != NULL && proxy->is_this()) {
PushParameterAt(-1);
return;
}
UNREACHABLE();
}
#undef __
} } // namespace v8::internal

12
deps/v8/src/ia32/virtual-frame-ia32.h

@ -339,12 +339,12 @@ class VirtualFrame: public ZoneObject {
Result CallLoadIC(RelocInfo::Mode mode);
// Call keyed load IC. Key and receiver are found on top of the
// frame. They are not dropped.
// frame. Both are dropped.
Result CallKeyedLoadIC(RelocInfo::Mode mode);
// Call store IC. Name, value, and receiver are found on top of the
// frame. Receiver is not dropped.
Result CallStoreIC();
// Call store IC. If the load is contextual, value is found on top of the
// frame. If not, value and receiver are on the frame. Both are dropped.
Result CallStoreIC(Handle<String> name, bool is_contextual);
// Call keyed store IC. Value, key, and receiver are found on top
// of the frame. Key and receiver are not dropped.
@ -415,6 +415,10 @@ class VirtualFrame: public ZoneObject {
result->Unuse();
}
// Pushing an expression expects that the expression is trivial (according
// to Expression::IsTrivial).
void Push(Expression* expr);
// Nip removes zero or more elements from immediately below the top
// of the frame, leaving the previous top-of-frame value on top of
// the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x).

2
deps/v8/src/jump-target-inl.h

@ -42,7 +42,7 @@ void JumpTarget::InitializeEntryElement(int index, FrameElement* target) {
} else if (target->is_copy()) {
entry_frame_->elements_[target->index()].set_copied();
}
if (direction_ == BIDIRECTIONAL) {
if (direction_ == BIDIRECTIONAL && !target->is_copy()) {
entry_frame_->elements_[index].set_number_info(NumberInfo::kUnknown);
}
}

2
deps/v8/src/jump-target.cc

@ -105,7 +105,6 @@ void JumpTarget::ComputeEntryFrame() {
FrameElement* other = &reaching_frames_[j]->elements_[i];
if (element != NULL && !element->is_copy()) {
ASSERT(other != NULL);
ASSERT(!other->is_copy());
// We overwrite the number information of one of the incoming frames.
// This is safe because we only use the frame for emitting merge code.
// The number information of incoming frames is not used anymore.
@ -128,7 +127,6 @@ void JumpTarget::ComputeEntryFrame() {
// elements as copied exactly when they have a copy. Undetermined
// elements are initially recorded as if in memory.
if (target != NULL) {
ASSERT(!target->is_copy()); // These initial elements are never copies.
entry_frame_->elements_[index] = *target;
InitializeEntryElement(index, target);
}

14
deps/v8/src/macros.py

@ -74,6 +74,10 @@ const kYearShift = 9;
const kMonthShift = 5;
# Type query macros.
#
# Note: We have special support for typeof(foo) === 'bar' in the compiler.
# It will *not* generate a runtime typeof call for the most important
# values of 'bar'.
macro IS_NULL(arg) = (arg === null);
macro IS_NULL_OR_UNDEFINED(arg) = (arg == null);
macro IS_UNDEFINED(arg) = (typeof(arg) === 'undefined');
@ -83,7 +87,7 @@ macro IS_BOOLEAN(arg) = (typeof(arg) === 'boolean');
macro IS_OBJECT(arg) = (%_IsObject(arg));
macro IS_ARRAY(arg) = (%_IsArray(arg));
macro IS_FUNCTION(arg) = (%_IsFunction(arg));
macro IS_REGEXP(arg) = (%_ClassOf(arg) === 'RegExp');
macro IS_REGEXP(arg) = (%_IsRegExp(arg));
macro IS_DATE(arg) = (%_ClassOf(arg) === 'Date');
macro IS_NUMBER_WRAPPER(arg) = (%_ClassOf(arg) === 'Number');
macro IS_STRING_WRAPPER(arg) = (%_ClassOf(arg) === 'String');
@ -97,9 +101,11 @@ macro FLOOR(arg) = $floor(arg);
# Inline macros. Use %IS_VAR to make sure arg is evaluated only once.
macro NUMBER_IS_NAN(arg) = (!%_IsSmi(%IS_VAR(arg)) && !(arg == arg));
macro TO_INTEGER(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : ToInteger(arg));
macro TO_INT32(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : (arg >> 0));
macro TO_UINT32(arg) = (arg >>> 0);
macro TO_INTEGER(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : ToInteger(arg));
macro TO_INT32(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : (arg >> 0));
macro TO_UINT32(arg) = (arg >>> 0);
macro TO_STRING_INLINE(arg) = (IS_STRING(%IS_VAR(arg)) ? arg : NonStringToString(arg));
# Macros implemented in Python.
python macro CHAR_CODE(str) = ord(str[1]);

11
deps/v8/src/mips/codegen-mips.cc

@ -305,6 +305,11 @@ void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
}
void CodeGenerator::GenerateIsRegExp(ZoneList<Expression*>* args) {
UNIMPLEMENTED_MIPS();
}
void CodeGenerator::GenerateIsConstructCall(ZoneList<Expression*>* args) {
UNIMPLEMENTED_MIPS();
}
@ -365,6 +370,11 @@ void CodeGenerator::GenerateRegExpExec(ZoneList<Expression*>* args) {
}
void CodeGenerator::GenerateNumberToString(ZoneList<Expression*>* args) {
UNIMPLEMENTED_MIPS();
}
void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
UNIMPLEMENTED_MIPS();
}
@ -498,4 +508,3 @@ int CompareStub::MinorKey() {
#undef __
} } // namespace v8::internal

4
deps/v8/src/mips/codegen-mips.h

@ -210,6 +210,7 @@ class CodeGenerator: public AstVisitor {
void GenerateIsSmi(ZoneList<Expression*>* args);
void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args);
void GenerateIsArray(ZoneList<Expression*>* args);
void GenerateIsRegExp(ZoneList<Expression*>* args);
// Support for construct call checks.
void GenerateIsConstructCall(ZoneList<Expression*>* args);
@ -241,6 +242,8 @@ class CodeGenerator: public AstVisitor {
void GenerateSubString(ZoneList<Expression*>* args);
void GenerateStringCompare(ZoneList<Expression*>* args);
void GenerateRegExpExec(ZoneList<Expression*>* args);
void GenerateNumberToString(ZoneList<Expression*>* args);
// Fast support for Math.sin and Math.cos.
inline void GenerateMathSin(ZoneList<Expression*>* args);
@ -308,4 +311,3 @@ class CodeGenerator: public AstVisitor {
} } // namespace v8::internal
#endif // V8_MIPS_CODEGEN_MIPS_H_

33
deps/v8/src/mirror-delay.js

@ -553,14 +553,16 @@ StringMirror.prototype.length = function() {
return this.value_.length;
};
StringMirror.prototype.toText = function() {
if (this.length() > kMaxProtocolStringLength) {
return this.value_.substring(0, kMaxProtocolStringLength) +
StringMirror.prototype.getTruncatedValue = function(maxLength) {
if (maxLength != -1 && this.length() > maxLength) {
return this.value_.substring(0, maxLength) +
'... (length: ' + this.length() + ')';
} else {
return this.value_;
}
return this.value_;
}
StringMirror.prototype.toText = function() {
return this.getTruncatedValue(kMaxProtocolStringLength);
}
@ -1955,6 +1957,15 @@ JSONProtocolSerializer.prototype.inlineRefs_ = function() {
}
JSONProtocolSerializer.prototype.maxStringLength_ = function() {
if (IS_UNDEFINED(this.options_) ||
IS_UNDEFINED(this.options_.maxStringLength)) {
return kMaxProtocolStringLength;
}
return this.options_.maxStringLength;
}
JSONProtocolSerializer.prototype.add_ = function(mirror) {
// If this mirror is already in the list just return.
for (var i = 0; i < this.mirrors_.length; i++) {
@ -1987,8 +1998,7 @@ JSONProtocolSerializer.prototype.serializeReferenceWithDisplayData_ =
o.value = mirror.value();
break;
case STRING_TYPE:
// Limit string length.
o.value = mirror.toText();
o.value = mirror.getTruncatedValue(this.maxStringLength_());
break;
case FUNCTION_TYPE:
o.name = mirror.name();
@ -2052,11 +2062,12 @@ JSONProtocolSerializer.prototype.serialize_ = function(mirror, reference,
case STRING_TYPE:
// String values might have their value cropped to keep down size.
if (mirror.length() > kMaxProtocolStringLength) {
var str = mirror.value().substring(0, kMaxProtocolStringLength);
if (this.maxStringLength_() != -1 &&
mirror.length() > this.maxStringLength_()) {
var str = mirror.getTruncatedValue(this.maxStringLength_());
content.value = str;
content.fromIndex = 0;
content.toIndex = kMaxProtocolStringLength;
content.toIndex = this.maxStringLength_();
} else {
content.value = mirror.value();
}

2
deps/v8/src/objects.h

@ -179,7 +179,7 @@ class PropertyDetails BASE_EMBEDDED {
class TypeField: public BitField<PropertyType, 0, 3> {};
class AttributesField: public BitField<PropertyAttributes, 3, 3> {};
class DeletedField: public BitField<uint32_t, 6, 1> {};
class IndexField: public BitField<uint32_t, 7, 31-7> {};
class IndexField: public BitField<uint32_t, 7, 32-7> {};
static const int kInitialIndex = 1;
private:

2
deps/v8/src/register-allocator.h

@ -141,7 +141,7 @@ class Result BASE_EMBEDDED {
class TypeField: public BitField<Type, 0, 2> {};
class NumberInfoField : public BitField<NumberInfo::Type, 2, 3> {};
class DataField: public BitField<uint32_t, 5, 32 - 6> {};
class DataField: public BitField<uint32_t, 5, 32 - 5> {};
inline void CopyTo(Result* destination) const;

128
deps/v8/src/runtime.cc

@ -2276,6 +2276,20 @@ static int SingleCharIndexOf(Vector<const schar> string,
return -1;
}
template <typename schar>
static int SingleCharLastIndexOf(Vector<const schar> string,
schar pattern_char,
int start_index) {
for (int i = start_index; i >= 0; i--) {
if (pattern_char == string[i]) {
return i;
}
}
return -1;
}
// Trivial string search for shorter strings.
// On return, if "complete" is set to true, the return value is the
// final result of searching for the patter in the subject.
@ -2352,7 +2366,7 @@ static int StringMatchStrategy(Vector<const schar> sub,
// We have an ASCII haystack and a non-ASCII needle. Check if there
// really is a non-ASCII character in the needle and bail out if there
// is.
if (sizeof(pchar) > 1 && sizeof(schar) == 1) {
if (sizeof(schar) == 1 && sizeof(pchar) > 1) {
for (int i = 0; i < pat.length(); i++) {
uc16 c = pat[i];
if (c > String::kMaxAsciiCharCode) {
@ -2455,39 +2469,115 @@ static Object* Runtime_StringIndexOf(Arguments args) {
}
template <typename schar, typename pchar>
static int StringMatchBackwards(Vector<const schar> sub,
Vector<const pchar> pat,
int idx) {
ASSERT(pat.length() >= 1);
ASSERT(idx + pat.length() <= sub.length());
if (sizeof(schar) == 1 && sizeof(pchar) > 1) {
for (int i = 0; i < pat.length(); i++) {
uc16 c = pat[i];
if (c > String::kMaxAsciiCharCode) {
return -1;
}
}
}
pchar pattern_first_char = pat[0];
for (int i = idx; i >= 0; i--) {
if (sub[i] != pattern_first_char) continue;
int j = 1;
while (j < pat.length()) {
if (pat[j] != sub[i+j]) {
break;
}
j++;
}
if (j == pat.length()) {
return i;
}
}
return -1;
}
static Object* Runtime_StringLastIndexOf(Arguments args) {
NoHandleAllocation ha;
HandleScope scope; // create a new handle scope
ASSERT(args.length() == 3);
CONVERT_CHECKED(String, sub, args[0]);
CONVERT_CHECKED(String, pat, args[1]);
Object* index = args[2];
sub->TryFlattenIfNotFlat();
pat->TryFlattenIfNotFlat();
CONVERT_ARG_CHECKED(String, sub, 0);
CONVERT_ARG_CHECKED(String, pat, 1);
Object* index = args[2];
uint32_t start_index;
if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1);
uint32_t pattern_length = pat->length();
uint32_t pat_length = pat->length();
uint32_t sub_length = sub->length();
if (start_index + pattern_length > sub_length) {
start_index = sub_length - pattern_length;
if (start_index + pat_length > sub_length) {
start_index = sub_length - pat_length;
}
for (int i = start_index; i >= 0; i--) {
bool found = true;
for (uint32_t j = 0; j < pattern_length; j++) {
if (sub->Get(i + j) != pat->Get(j)) {
found = false;
break;
if (pat_length == 0) {
return Smi::FromInt(start_index);
}
if (!sub->IsFlat()) {
FlattenString(sub);
}
if (pat_length == 1) {
AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
if (sub->IsAsciiRepresentation()) {
uc16 pchar = pat->Get(0);
if (pchar > String::kMaxAsciiCharCode) {
return Smi::FromInt(-1);
}
return Smi::FromInt(SingleCharLastIndexOf(sub->ToAsciiVector(),
static_cast<char>(pat->Get(0)),
start_index));
} else {
return Smi::FromInt(SingleCharLastIndexOf(sub->ToUC16Vector(),
pat->Get(0),
start_index));
}
if (found) return Smi::FromInt(i);
}
return Smi::FromInt(-1);
if (!pat->IsFlat()) {
FlattenString(pat);
}
AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
int position = -1;
if (pat->IsAsciiRepresentation()) {
Vector<const char> pat_vector = pat->ToAsciiVector();
if (sub->IsAsciiRepresentation()) {
position = StringMatchBackwards(sub->ToAsciiVector(),
pat_vector,
start_index);
} else {
position = StringMatchBackwards(sub->ToUC16Vector(),
pat_vector,
start_index);
}
} else {
Vector<const uc16> pat_vector = pat->ToUC16Vector();
if (sub->IsAsciiRepresentation()) {
position = StringMatchBackwards(sub->ToAsciiVector(),
pat_vector,
start_index);
} else {
position = StringMatchBackwards(sub->ToUC16Vector(),
pat_vector,
start_index);
}
}
return Smi::FromInt(position);
}

7
deps/v8/src/runtime.js

@ -529,6 +529,13 @@ function ToString(x) {
return (IS_NULL(x)) ? 'null' : %ToString(%DefaultString(x));
}
function NonStringToString(x) {
if (IS_NUMBER(x)) return %NumberToString(x);
if (IS_BOOLEAN(x)) return x ? 'true' : 'false';
if (IS_UNDEFINED(x)) return 'undefined';
return (IS_NULL(x)) ? 'null' : %ToString(%DefaultString(x));
}
// ECMA-262, section 9.9, page 36.
function ToObject(x) {

2
deps/v8/src/scopeinfo.cc

@ -536,7 +536,7 @@ int ContextSlotCache::Hash(Code* code, String* name) {
// Uses only lower 32 bits if pointers are larger.
uintptr_t addr_hash =
static_cast<uint32_t>(reinterpret_cast<uintptr_t>(code)) >> 2;
return (addr_hash ^ name->Hash()) % kLength;
return static_cast<int>((addr_hash ^ name->Hash()) % kLength);
}

4
deps/v8/src/serialize.cc

@ -852,10 +852,10 @@ void SnapshotByteSink::PutInt(uintptr_t integer, const char* description) {
const int max_shift = ((kPointerSize * kBitsPerByte) / 7) * 7;
for (int shift = max_shift; shift > 0; shift -= 7) {
if (integer >= static_cast<uintptr_t>(1u) << shift) {
Put(((integer >> shift) & 0x7f) | 0x80, "IntPart");
Put((static_cast<int>((integer >> shift)) & 0x7f) | 0x80, "IntPart");
}
}
PutSection(integer & 0x7f, "IntLastPart");
PutSection(static_cast<int>(integer & 0x7f), "IntLastPart");
}
#ifdef DEBUG

2
deps/v8/src/spaces-inl.h

@ -183,7 +183,7 @@ Page* MemoryAllocator::GetNextPage(Page* p) {
int MemoryAllocator::GetChunkId(Page* p) {
ASSERT(p->is_valid());
return p->opaque_header & Page::kPageAlignmentMask;
return static_cast<int>(p->opaque_header & Page::kPageAlignmentMask);
}

120
deps/v8/src/string.js

@ -34,7 +34,7 @@
// Set the String function and constructor.
%SetCode($String, function(x) {
var value = %_ArgumentsLength() == 0 ? '' : ToString(x);
var value = %_ArgumentsLength() == 0 ? '' : TO_STRING_INLINE(x);
if (%_IsConstructCall()) {
%_SetValueOf(this, value);
} else {
@ -64,7 +64,7 @@ function StringValueOf() {
function StringCharAt(pos) {
var char_code = %_FastCharCodeAt(this, pos);
if (!%_IsSmi(char_code)) {
var subject = ToString(this);
var subject = TO_STRING_INLINE(this);
var index = TO_INTEGER(pos);
if (index >= subject.length || index < 0) return "";
char_code = %StringCharCodeAt(subject, index);
@ -79,7 +79,7 @@ function StringCharCodeAt(pos) {
if (%_IsSmi(fast_answer)) {
return fast_answer;
}
var subject = ToString(this);
var subject = TO_STRING_INLINE(this);
var index = TO_INTEGER(pos);
return %StringCharCodeAt(subject, index);
}
@ -88,7 +88,7 @@ function StringCharCodeAt(pos) {
// ECMA-262, section 15.5.4.6
function StringConcat() {
var len = %_ArgumentsLength();
var this_as_string = IS_STRING(this) ? this : ToString(this);
var this_as_string = TO_STRING_INLINE(this);
if (len === 1) {
return this_as_string + %_Arguments(0);
}
@ -96,7 +96,7 @@ function StringConcat() {
parts[0] = this_as_string;
for (var i = 0; i < len; i++) {
var part = %_Arguments(i);
parts[i + 1] = IS_STRING(part) ? part : ToString(part);
parts[i + 1] = TO_STRING_INLINE(part);
}
return %StringBuilderConcat(parts, len + 1, "");
}
@ -107,8 +107,8 @@ function StringConcat() {
// ECMA-262 section 15.5.4.7
function StringIndexOf(searchString /* position */) { // length == 1
var subject_str = ToString(this);
var pattern_str = ToString(searchString);
var subject_str = TO_STRING_INLINE(this);
var pattern_str = TO_STRING_INLINE(searchString);
var subject_str_len = subject_str.length;
var pattern_str_len = pattern_str.length;
var index = 0;
@ -125,9 +125,9 @@ function StringIndexOf(searchString /* position */) { // length == 1
// ECMA-262 section 15.5.4.8
function StringLastIndexOf(searchString /* position */) { // length == 1
var sub = ToString(this);
var sub = TO_STRING_INLINE(this);
var subLength = sub.length;
var pat = ToString(searchString);
var pat = TO_STRING_INLINE(searchString);
var patLength = pat.length;
var index = subLength - patLength;
if (%_ArgumentsLength() > 1) {
@ -156,8 +156,8 @@ function StringLastIndexOf(searchString /* position */) { // length == 1
function StringLocaleCompare(other) {
if (%_ArgumentsLength() === 0) return 0;
var this_str = ToString(this);
var other_str = ToString(other);
var this_str = TO_STRING_INLINE(this);
var other_str = TO_STRING_INLINE(other);
return %StringLocaleCompare(this_str, other_str);
}
@ -165,7 +165,7 @@ function StringLocaleCompare(other) {
// ECMA-262 section 15.5.4.10
function StringMatch(regexp) {
if (!IS_REGEXP(regexp)) regexp = new ORIGINAL_REGEXP(regexp);
var subject = ToString(this);
var subject = TO_STRING_INLINE(this);
if (!regexp.global) return regexp.exec(subject);
%_Log('regexp', 'regexp-match,%0S,%1r', [subject, regexp]);
@ -200,7 +200,7 @@ var reusableMatchInfo = [2, "", "", -1, -1];
// ECMA-262, section 15.5.4.11
function StringReplace(search, replace) {
var subject = IS_STRING(this) ? this : ToString(this);
var subject = TO_STRING_INLINE(this);
// Delegate to one of the regular expression variants if necessary.
if (IS_REGEXP(search)) {
@ -213,7 +213,7 @@ function StringReplace(search, replace) {
}
// Convert the search argument to a string and search for it.
search = IS_STRING(search) ? search : ToString(search);
search = TO_STRING_INLINE(search);
var start = %StringIndexOf(subject, search, 0);
if (start < 0) return subject;
var end = start + search.length;
@ -228,7 +228,7 @@ function StringReplace(search, replace) {
} else {
reusableMatchInfo[CAPTURE0] = start;
reusableMatchInfo[CAPTURE1] = end;
if (!IS_STRING(replace)) replace = ToString(replace);
replace = TO_STRING_INLINE(replace);
ExpandReplacement(replace, subject, reusableMatchInfo, builder);
}
@ -241,7 +241,7 @@ function StringReplace(search, replace) {
// Helper function for regular expressions in String.prototype.replace.
function StringReplaceRegExp(subject, regexp, replace) {
replace = ToString(replace);
replace = TO_STRING_INLINE(replace);
return %StringReplaceRegExpWithString(subject,
regexp,
replace,
@ -462,7 +462,7 @@ function ApplyReplacementFunction(replace, matchInfo, subject) {
// ECMA-262 section 15.5.4.12
function StringSearch(re) {
var regexp = new ORIGINAL_REGEXP(re);
var s = ToString(this);
var s = TO_STRING_INLINE(this);
var last_idx = regexp.lastIndex; // keep old lastIndex
regexp.lastIndex = 0; // ignore re.global property
var result = regexp.exec(s);
@ -476,7 +476,7 @@ function StringSearch(re) {
// ECMA-262 section 15.5.4.13
function StringSlice(start, end) {
var s = ToString(this);
var s = TO_STRING_INLINE(this);
var s_len = s.length;
var start_i = TO_INTEGER(start);
var end_i = s_len;
@ -511,7 +511,7 @@ function StringSlice(start, end) {
// ECMA-262 section 15.5.4.14
function StringSplit(separator, limit) {
var subject = ToString(this);
var subject = TO_STRING_INLINE(this);
limit = (IS_UNDEFINED(limit)) ? 0xffffffff : TO_UINT32(limit);
if (limit === 0) return [];
@ -525,18 +525,35 @@ function StringSplit(separator, limit) {
}
var length = subject.length;
if (IS_REGEXP(separator)) {
%_Log('regexp', 'regexp-split,%0S,%1r', [subject, separator]);
} else {
separator = ToString(separator);
if (!IS_REGEXP(separator)) {
separator = TO_STRING_INLINE(separator);
var separator_length = separator.length;
// If the separator string is empty then return the elements in the subject.
if (separator.length == 0) {
if (separator_length === 0) {
var result = $Array(length);
for (var i = 0; i < length; i++) result[i] = subject[i];
return result;
}
var result = [];
var start_index = 0;
var index;
while (true) {
if (start_index + separator_length > length ||
(index = %StringIndexOf(subject, separator, start_index)) === -1) {
result.push(SubString(subject, start_index, length));
break;
}
if (result.push(SubString(subject, start_index, index)) === limit) break;
start_index = index + separator_length;
}
return result;
}
%_Log('regexp', 'regexp-split,%0S,%1r', [subject, separator]);
if (length === 0) {
if (splitMatch(separator, subject, 0, 0) != null) return [];
return [subject];
@ -571,7 +588,8 @@ function StringSplit(separator, limit) {
result[result.length] = SubString(subject, currentIndex, matchInfo[CAPTURE0]);
if (result.length === limit) return result;
for (var i = 2; i < NUMBER_OF_CAPTURES(matchInfo); i += 2) {
var num_captures = NUMBER_OF_CAPTURES(matchInfo);
for (var i = 2; i < num_captures; i += 2) {
var start = matchInfo[CAPTURE(i)];
var end = matchInfo[CAPTURE(i + 1)];
if (start != -1 && end != -1) {
@ -591,28 +609,18 @@ function StringSplit(separator, limit) {
// Helper function used by split. This version returns the matchInfo
// instead of allocating a new array with basically the same information.
function splitMatch(separator, subject, current_index, start_index) {
if (IS_REGEXP(separator)) {
var matchInfo = DoRegExpExec(separator, subject, start_index);
if (matchInfo == null) return null;
// Section 15.5.4.14 paragraph two says that we do not allow zero length
// matches at the end of the string.
if (matchInfo[CAPTURE0] === subject.length) return null;
return matchInfo;
}
var separatorIndex = subject.indexOf(separator, start_index);
if (separatorIndex === -1) return null;
reusableMatchInfo[CAPTURE0] = separatorIndex;
reusableMatchInfo[CAPTURE1] = separatorIndex + separator.length;
return reusableMatchInfo;
};
var matchInfo = DoRegExpExec(separator, subject, start_index);
if (matchInfo == null) return null;
// Section 15.5.4.14 paragraph two says that we do not allow zero length
// matches at the end of the string.
if (matchInfo[CAPTURE0] === subject.length) return null;
return matchInfo;
}
// ECMA-262 section 15.5.4.15
function StringSubstring(start, end) {
var s = this;
if (!IS_STRING(s)) s = ToString(s);
var s = TO_STRING_INLINE(this);
var s_len = s.length;
var start_i = TO_INTEGER(start);
@ -643,7 +651,7 @@ function StringSubstring(start, end) {
// This is not a part of ECMA-262.
function StringSubstr(start, n) {
var s = ToString(this);
var s = TO_STRING_INLINE(this);
var len;
// Correct n: If not given, set to string length; if explicitly
@ -681,38 +689,38 @@ function StringSubstr(start, n) {
// ECMA-262, 15.5.4.16
function StringToLowerCase() {
return %StringToLowerCase(ToString(this));
return %StringToLowerCase(TO_STRING_INLINE(this));
}
// ECMA-262, 15.5.4.17
function StringToLocaleLowerCase() {
return %StringToLowerCase(ToString(this));
return %StringToLowerCase(TO_STRING_INLINE(this));
}
// ECMA-262, 15.5.4.18
function StringToUpperCase() {
return %StringToUpperCase(ToString(this));
return %StringToUpperCase(TO_STRING_INLINE(this));
}
// ECMA-262, 15.5.4.19
function StringToLocaleUpperCase() {
return %StringToUpperCase(ToString(this));
return %StringToUpperCase(TO_STRING_INLINE(this));
}
// ES5, 15.5.4.20
function StringTrim() {
return %StringTrim(ToString(this), true, true);
return %StringTrim(TO_STRING_INLINE(this), true, true);
}
function StringTrimLeft() {
return %StringTrim(ToString(this), true, false);
return %StringTrim(TO_STRING_INLINE(this), true, false);
}
function StringTrimRight() {
return %StringTrim(ToString(this), false, true);
return %StringTrim(TO_STRING_INLINE(this), false, true);
}
// ECMA-262, section 15.5.3.2
@ -731,10 +739,10 @@ function StringFromCharCode(code) {
// Helper function for very basic XSS protection.
function HtmlEscape(str) {
return ToString(str).replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
return TO_STRING_INLINE(str).replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
};
@ -813,7 +821,7 @@ function ReplaceResultBuilder(str) {
ReplaceResultBuilder.prototype.add = function(str) {
if (!IS_STRING(str)) str = ToString(str);
str = TO_STRING_INLINE(str);
if (str.length > 0) {
var elements = this.elements;
elements[elements.length] = str;

14
deps/v8/src/stub-cache.cc

@ -105,7 +105,7 @@ Object* StubCache::ComputeLoadField(String* name,
if (code->IsFailure()) return code;
LOG(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
if (result->IsFailure()) return code;
if (result->IsFailure()) return result;
}
return Set(name, receiver->map(), Code::cast(code));
}
@ -124,7 +124,7 @@ Object* StubCache::ComputeLoadCallback(String* name,
if (code->IsFailure()) return code;
LOG(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
if (result->IsFailure()) return code;
if (result->IsFailure()) return result;
}
return Set(name, receiver->map(), Code::cast(code));
}
@ -143,7 +143,7 @@ Object* StubCache::ComputeLoadConstant(String* name,
if (code->IsFailure()) return code;
LOG(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
if (result->IsFailure()) return code;
if (result->IsFailure()) return result;
}
return Set(name, receiver->map(), Code::cast(code));
}
@ -160,7 +160,7 @@ Object* StubCache::ComputeLoadInterceptor(String* name,
if (code->IsFailure()) return code;
LOG(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
if (result->IsFailure()) return code;
if (result->IsFailure()) return result;
}
return Set(name, receiver->map(), Code::cast(code));
}
@ -189,7 +189,7 @@ Object* StubCache::ComputeLoadGlobal(String* name,
if (code->IsFailure()) return code;
LOG(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
if (result->IsFailure()) return code;
if (result->IsFailure()) return result;
}
return Set(name, receiver->map(), Code::cast(code));
}
@ -351,7 +351,7 @@ Object* StubCache::ComputeStoreGlobal(String* name,
if (code->IsFailure()) return code;
LOG(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name));
Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
if (result->IsFailure()) return code;
if (result->IsFailure()) return result;
}
return Set(name, receiver->map(), Code::cast(code));
}
@ -566,7 +566,7 @@ Object* StubCache::ComputeCallGlobal(int argc,
ASSERT_EQ(flags, Code::cast(code)->flags());
LOG(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name));
Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code));
if (result->IsFailure()) return code;
if (result->IsFailure()) return result;
}
return Set(name, receiver->map(), Code::cast(code));
}

6
deps/v8/src/utils.h

@ -157,7 +157,9 @@ class BitField {
// Returns a uint32_t mask of bit field.
static uint32_t mask() {
return (1U << (size + shift)) - (1U << shift);
// To use all bits of a uint32 in a bitfield without compiler warnings we
// have to compute 2^32 without using a shift count of 32.
return ((1U << shift) << size) - (1U << shift);
}
// Returns a uint32_t with the bit field value encoded.
@ -168,7 +170,7 @@ class BitField {
// Extracts the bit field from the value.
static T decode(uint32_t value) {
return static_cast<T>((value >> shift) & ((1U << (size)) - 1));
return static_cast<T>((value & mask()) >> shift);
}
};

4
deps/v8/src/version.cc

@ -34,8 +34,8 @@
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 2
#define MINOR_VERSION 1
#define BUILD_NUMBER 1
#define PATCH_LEVEL 1
#define BUILD_NUMBER 2
#define PATCH_LEVEL 0
#define CANDIDATE_VERSION false
// Define SONAME to have the SCons build the put a specific SONAME into the

40
deps/v8/src/x64/assembler-x64.cc

@ -33,46 +33,6 @@
namespace v8 {
namespace internal {
// -----------------------------------------------------------------------------
// Implementation of Register
Register rax = { 0 };
Register rcx = { 1 };
Register rdx = { 2 };
Register rbx = { 3 };
Register rsp = { 4 };
Register rbp = { 5 };
Register rsi = { 6 };
Register rdi = { 7 };
Register r8 = { 8 };
Register r9 = { 9 };
Register r10 = { 10 };
Register r11 = { 11 };
Register r12 = { 12 };
Register r13 = { 13 };
Register r14 = { 14 };
Register r15 = { 15 };
Register no_reg = { -1 };
XMMRegister xmm0 = { 0 };
XMMRegister xmm1 = { 1 };
XMMRegister xmm2 = { 2 };
XMMRegister xmm3 = { 3 };
XMMRegister xmm4 = { 4 };
XMMRegister xmm5 = { 5 };
XMMRegister xmm6 = { 6 };
XMMRegister xmm7 = { 7 };
XMMRegister xmm8 = { 8 };
XMMRegister xmm9 = { 9 };
XMMRegister xmm10 = { 10 };
XMMRegister xmm11 = { 11 };
XMMRegister xmm12 = { 12 };
XMMRegister xmm13 = { 13 };
XMMRegister xmm14 = { 14 };
XMMRegister xmm15 = { 15 };
// -----------------------------------------------------------------------------
// Implementation of CpuFeatures

94
deps/v8/src/x64/assembler-x64.h

@ -118,51 +118,23 @@ struct Register {
int code_;
};
extern Register rax;
extern Register rcx;
extern Register rdx;
extern Register rbx;
extern Register rsp;
extern Register rbp;
extern Register rsi;
extern Register rdi;
extern Register r8;
extern Register r9;
extern Register r10;
extern Register r11;
extern Register r12;
extern Register r13;
extern Register r14;
extern Register r15;
extern Register no_reg;
struct MMXRegister {
bool is_valid() const { return 0 <= code_ && code_ < 2; }
int code() const {
ASSERT(is_valid());
return code_;
}
int code_;
};
extern MMXRegister mm0;
extern MMXRegister mm1;
extern MMXRegister mm2;
extern MMXRegister mm3;
extern MMXRegister mm4;
extern MMXRegister mm5;
extern MMXRegister mm6;
extern MMXRegister mm7;
extern MMXRegister mm8;
extern MMXRegister mm9;
extern MMXRegister mm10;
extern MMXRegister mm11;
extern MMXRegister mm12;
extern MMXRegister mm13;
extern MMXRegister mm14;
extern MMXRegister mm15;
const Register rax = { 0 };
const Register rcx = { 1 };
const Register rdx = { 2 };
const Register rbx = { 3 };
const Register rsp = { 4 };
const Register rbp = { 5 };
const Register rsi = { 6 };
const Register rdi = { 7 };
const Register r8 = { 8 };
const Register r9 = { 9 };
const Register r10 = { 10 };
const Register r11 = { 11 };
const Register r12 = { 12 };
const Register r13 = { 13 };
const Register r14 = { 14 };
const Register r15 = { 15 };
const Register no_reg = { -1 };
struct XMMRegister {
@ -186,22 +158,22 @@ struct XMMRegister {
int code_;
};
extern XMMRegister xmm0;
extern XMMRegister xmm1;
extern XMMRegister xmm2;
extern XMMRegister xmm3;
extern XMMRegister xmm4;
extern XMMRegister xmm5;
extern XMMRegister xmm6;
extern XMMRegister xmm7;
extern XMMRegister xmm8;
extern XMMRegister xmm9;
extern XMMRegister xmm10;
extern XMMRegister xmm11;
extern XMMRegister xmm12;
extern XMMRegister xmm13;
extern XMMRegister xmm14;
extern XMMRegister xmm15;
const XMMRegister xmm0 = { 0 };
const XMMRegister xmm1 = { 1 };
const XMMRegister xmm2 = { 2 };
const XMMRegister xmm3 = { 3 };
const XMMRegister xmm4 = { 4 };
const XMMRegister xmm5 = { 5 };
const XMMRegister xmm6 = { 6 };
const XMMRegister xmm7 = { 7 };
const XMMRegister xmm8 = { 8 };
const XMMRegister xmm9 = { 9 };
const XMMRegister xmm10 = { 10 };
const XMMRegister xmm11 = { 11 };
const XMMRegister xmm12 = { 12 };
const XMMRegister xmm13 = { 13 };
const XMMRegister xmm14 = { 14 };
const XMMRegister xmm15 = { 15 };
enum Condition {
// any value < 0 is considered no_condition

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

@ -277,7 +277,7 @@ void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
}
void CodeGenerator::Generate(CompilationInfo* info, Mode mode) {
void CodeGenerator::Generate(CompilationInfo* info) {
// Record the position for debugging purposes.
CodeForFunctionPosition(info->function());
@ -316,7 +316,7 @@ void CodeGenerator::Generate(CompilationInfo* info, Mode mode) {
// rsi: callee's context
allocator_->Initialize();
if (mode == PRIMARY) {
if (info->mode() == CompilationInfo::PRIMARY) {
frame_->Enter();
// Allocate space for locals and initialize them.
@ -407,6 +407,12 @@ void CodeGenerator::Generate(CompilationInfo* info, Mode mode) {
// frame to match this state.
frame_->Adjust(3);
allocator_->Unuse(rdi);
// Bind all the bailout labels to the beginning of the function.
List<CompilationInfo::Bailout*>* bailouts = info->bailouts();
for (int i = 0; i < bailouts->length(); i++) {
__ bind(bailouts->at(i)->label());
}
}
// Initialize the function return target after the locals are set
@ -3627,6 +3633,22 @@ void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) {
}
void CodeGenerator::GenerateIsRegExp(ZoneList<Expression*>* args) {
ASSERT(args->length() == 1);
Load(args->at(0));
Result value = frame_->Pop();
value.ToRegister();
ASSERT(value.is_valid());
Condition is_smi = masm_->CheckSmi(value.reg());
destination()->false_target()->Branch(is_smi);
// It is a heap object - get map.
// Check if the object is a regexp.
__ CmpObjectType(value.reg(), JS_REGEXP_TYPE, kScratchRegister);
value.Unuse();
destination()->Split(equal);
}
void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) {
// This generates a fast version of:
// (typeof(arg) === 'object' || %_ClassOf(arg) == 'RegExp')

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

@ -294,15 +294,6 @@ enum ArgumentsAllocationMode {
class CodeGenerator: public AstVisitor {
public:
// Compilation mode. Either the compiler is used as the primary
// compiler and needs to setup everything or the compiler is used as
// the secondary compiler for split compilation and has to handle
// bailouts.
enum Mode {
PRIMARY,
SECONDARY
};
// Takes a function literal, generates code for it. This function should only
// be called by compiler.cc.
static Handle<Code> MakeCode(CompilationInfo* info);
@ -385,7 +376,7 @@ class CodeGenerator: public AstVisitor {
void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
// Main code generation function
void Generate(CompilationInfo* info, Mode mode);
void Generate(CompilationInfo* info);
// Generate the return sequence code. Should be called no more than
// once per compiled function, immediately after binding the return
@ -536,6 +527,7 @@ class CodeGenerator: public AstVisitor {
void GenerateIsSmi(ZoneList<Expression*>* args);
void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args);
void GenerateIsArray(ZoneList<Expression*>* args);
void GenerateIsRegExp(ZoneList<Expression*>* args);
void GenerateIsObject(ZoneList<Expression*>* args);
void GenerateIsFunction(ZoneList<Expression*>* args);
void GenerateIsUndetectableObject(ZoneList<Expression*>* args);

38
deps/v8/src/x64/fast-codegen-x64.cc

@ -156,21 +156,28 @@ void FastCodeGenerator::EmitBitOr() {
// commutative.
__ or_(destination(), other_accumulator(destination()));
}
} else if (destination().is(no_reg)) {
// Result is not needed but do not clobber the operands in case of
// bailout.
__ movq(scratch0(), accumulator1());
__ or_(scratch0(), accumulator0());
__ JumpIfNotSmi(scratch0(), bailout());
} else {
// Preserve the destination operand in a scratch register in case of
// bailout.
__ movq(scratch0(), destination());
__ or_(destination(), other_accumulator(destination()));
__ JumpIfNotSmi(destination(), bailout());
// Left is in accumulator1, right in accumulator0.
if (destination().is(accumulator0())) {
__ movq(scratch0(), accumulator0());
__ or_(destination(), accumulator1()); // Or is commutative.
Label* bailout =
info()->AddBailout(accumulator1(), scratch0()); // Left, right.
__ JumpIfNotSmi(destination(), bailout);
} else if (destination().is(accumulator1())) {
__ movq(scratch0(), accumulator1());
__ or_(destination(), accumulator0());
Label* bailout = info()->AddBailout(scratch0(), accumulator0());
__ JumpIfNotSmi(destination(), bailout);
} else {
ASSERT(destination().is(no_reg));
__ movq(scratch0(), accumulator1());
__ or_(scratch0(), accumulator0());
Label* bailout = info()->AddBailout(accumulator1(), accumulator0());
__ JumpIfNotSmi(scratch0(), bailout);
}
}
// If we didn't bailout, the result (in fact, both inputs too) is known to
// be a smi.
set_as_smi(accumulator0());
@ -191,6 +198,7 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) {
// Note that we keep a live register reference to esi (context) at this
// point.
Label* bailout_to_beginning = info()->AddBailout();
// Receiver (this) is allocated to a fixed register.
if (info()->has_this_properties()) {
Comment cmnt(masm(), ";; MapCheck(this)");
@ -201,7 +209,7 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) {
Handle<HeapObject> object = Handle<HeapObject>::cast(info()->receiver());
Handle<Map> map(object->map());
EmitLoadReceiver();
__ CheckMap(receiver_reg(), map, bailout(), false);
__ CheckMap(receiver_reg(), map, bailout_to_beginning, false);
}
// If there is a global variable access check if the global object is the
@ -214,7 +222,7 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) {
ASSERT(info()->has_global_object());
Handle<Map> map(info()->global_object()->map());
__ movq(scratch0(), CodeGenerator::GlobalObject());
__ CheckMap(scratch0(), map, bailout(), true);
__ CheckMap(scratch0(), map, bailout_to_beginning, true);
}
VisitStatements(info()->function()->body());
@ -227,8 +235,6 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) {
__ movq(rsp, rbp);
__ pop(rbp);
__ ret((scope()->num_parameters() + 1) * kPointerSize);
__ bind(&bailout_);
}

2
deps/v8/src/x64/macro-assembler-x64.h

@ -36,7 +36,7 @@ namespace internal {
// Default scratch register used by MacroAssembler (and other code that needs
// a spare register). The register isn't callee save, and not used by the
// function calling convention.
static const Register kScratchRegister = r10;
static const Register kScratchRegister = { 10 }; // r10.
// Convenience for platform-independent signatures.
typedef Operand MemOperand;

62
deps/v8/test/mjsunit/bugs/bug-619.js

@ -0,0 +1,62 @@
// 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.
// When this bug is corrected move to object-define-property and add
// additional tests for configurable in the same manner as existing tests
// there.
var obj = {};
obj[1] = 42;
assertEquals(42, obj[1]);
Object.defineProperty(obj, '1', {value:10, writable:false});
assertEquals(10, obj[1]);
// We should not be able to override obj[1].
obj[1] = 5;
assertEquals(10, obj[1]);
// Try on a range of numbers.
for(var i = 0; i < 1024; i++) {
obj[i] = 42;
}
for(var i = 0; i < 1024; i++) {
Object.defineProperty(obj, i, {value: i, writable:false});
}
for(var i = 0; i < 1024; i++) {
assertEquals(i, obj[i]);
}
for(var i = 0; i < 1024; i++) {
obj[1] = 5;
}
for(var i = 0; i < 1024; i++) {
assertEquals(i, obj[i]);
}

37
deps/v8/test/mjsunit/debug-evaluate.js

@ -87,6 +87,37 @@ function listener(event, exec_state, event_data, data) {
testRequest(dcp, '{"expression":"a","global":true}', true, 1);
testRequest(dcp, '{"expression":"this.a","global":true}', true, 1);
// Test that the whole string text is returned if maxStringLength
// parameter is passed.
testRequest(
dcp,
'{"expression":"this.longString","global":true,maxStringLength:-1}',
true,
longString);
testRequest(
dcp,
'{"expression":"this.longString","global":true,maxStringLength:' +
longString.length + '}',
true,
longString);
var truncatedStringSuffix = '... (length: ' + longString.length + ')';
testRequest(
dcp,
'{"expression":"this.longString","global":true,maxStringLength:0}',
true,
truncatedStringSuffix);
testRequest(
dcp,
'{"expression":"this.longString","global":true,maxStringLength:1}',
true,
longString.charAt(0) + truncatedStringSuffix);
// Test that by default string is truncated to first 80 chars.
testRequest(
dcp,
'{"expression":"this.longString","global":true}',
true,
longString.substring(0, 80) + truncatedStringSuffix);
// Indicate that all was processed.
listenerComplete = true;
}
@ -109,6 +140,12 @@ function g() {
a = 1;
// String which is longer than 80 chars.
var longString = "1234567890_";
for (var i = 0; i < 4; i++) {
longString += longString;
}
// Set a break point at return in f and invoke g to hit the breakpoint.
Debug.setBreakPoint(f, 2, 0);
g();

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

@ -269,7 +269,6 @@
'../../src/execution.h',
'../../src/factory.cc',
'../../src/factory.h',
'../../src/fast-codegen.cc',
'../../src/fast-codegen.h',
'../../src/flag-definitions.h',
'../../src/flags.cc',
@ -404,6 +403,7 @@
'../../src/arm',
],
'sources': [
'../../src/fast-codegen.cc',
'../../src/arm/assembler-arm-inl.h',
'../../src/arm/assembler-arm.cc',
'../../src/arm/assembler-arm.h',
@ -455,6 +455,7 @@
'../../src/ia32/debug-ia32.cc',
'../../src/ia32/disasm-ia32.cc',
'../../src/ia32/fast-codegen-ia32.cc',
'../../src/ia32/fast-codegen-ia32.h',
'../../src/ia32/frames-ia32.cc',
'../../src/ia32/frames-ia32.h',
'../../src/ia32/full-codegen-ia32.cc',
@ -475,6 +476,7 @@
'../../src/x64',
],
'sources': [
'../../src/fast-codegen.cc',
'../../src/x64/assembler-x64-inl.h',
'../../src/x64/assembler-x64.cc',
'../../src/x64/assembler-x64.h',

2
deps/v8/tools/visual_studio/v8_base.vcproj

@ -401,7 +401,7 @@
>
</File>
<File
RelativePath="..\..\src\fast-codegen.cc"
RelativePath="..\..\src\ia32\fast-codegen-ia32.h"
>
</File>
<File

Loading…
Cancel
Save