Browse Source

Upgrade V8 to 3.6.6.14

v0.7.4-release
Ryan Dahl 13 years ago
parent
commit
de3c16afae
  1. 57
      deps/v8/src/api.cc
  2. 6
      deps/v8/src/arm/lithium-codegen-arm.cc
  3. 6
      deps/v8/src/ia32/lithium-codegen-ia32.cc
  4. 73
      deps/v8/src/mark-compact.cc
  5. 12
      deps/v8/src/mark-compact.h
  6. 28
      deps/v8/src/parser.cc
  7. 1
      deps/v8/src/preparser.cc
  8. 2
      deps/v8/src/v8threads.h
  9. 2
      deps/v8/src/version.cc
  10. 4
      deps/v8/src/x64/lithium-codegen-x64.cc
  11. 176
      deps/v8/test/cctest/test-parsing.cc
  12. 38
      deps/v8/test/mjsunit/compiler/regress-106351.js
  13. 50
      deps/v8/test/mjsunit/regress/regress-97116.js
  14. 7
      deps/v8/tools/gyp/v8.gyp

57
deps/v8/src/api.cc

@ -1456,31 +1456,35 @@ Local<Script> Script::New(v8::Handle<String> source,
ON_BAILOUT(isolate, "v8::Script::New()", return Local<Script>());
LOG_API(isolate, "Script::New");
ENTER_V8(isolate);
i::Handle<i::String> str = Utils::OpenHandle(*source);
i::Handle<i::Object> name_obj;
int line_offset = 0;
int column_offset = 0;
if (origin != NULL) {
if (!origin->ResourceName().IsEmpty()) {
name_obj = Utils::OpenHandle(*origin->ResourceName());
}
if (!origin->ResourceLineOffset().IsEmpty()) {
line_offset = static_cast<int>(origin->ResourceLineOffset()->Value());
i::SharedFunctionInfo* raw_result = NULL;
{ i::HandleScope scope(isolate);
i::Handle<i::String> str = Utils::OpenHandle(*source);
i::Handle<i::Object> name_obj;
int line_offset = 0;
int column_offset = 0;
if (origin != NULL) {
if (!origin->ResourceName().IsEmpty()) {
name_obj = Utils::OpenHandle(*origin->ResourceName());
}
if (!origin->ResourceLineOffset().IsEmpty()) {
line_offset = static_cast<int>(origin->ResourceLineOffset()->Value());
}
if (!origin->ResourceColumnOffset().IsEmpty()) {
column_offset =
static_cast<int>(origin->ResourceColumnOffset()->Value());
}
}
if (!origin->ResourceColumnOffset().IsEmpty()) {
column_offset = static_cast<int>(origin->ResourceColumnOffset()->Value());
EXCEPTION_PREAMBLE(isolate);
i::ScriptDataImpl* pre_data_impl =
static_cast<i::ScriptDataImpl*>(pre_data);
// We assert that the pre-data is sane, even though we can actually
// handle it if it turns out not to be in release mode.
ASSERT(pre_data_impl == NULL || pre_data_impl->SanityCheck());
// If the pre-data isn't sane we simply ignore it
if (pre_data_impl != NULL && !pre_data_impl->SanityCheck()) {
pre_data_impl = NULL;
}
}
EXCEPTION_PREAMBLE(isolate);
i::ScriptDataImpl* pre_data_impl = static_cast<i::ScriptDataImpl*>(pre_data);
// We assert that the pre-data is sane, even though we can actually
// handle it if it turns out not to be in release mode.
ASSERT(pre_data_impl == NULL || pre_data_impl->SanityCheck());
// If the pre-data isn't sane we simply ignore it
if (pre_data_impl != NULL && !pre_data_impl->SanityCheck()) {
pre_data_impl = NULL;
}
i::Handle<i::SharedFunctionInfo> result =
i::Handle<i::SharedFunctionInfo> result =
i::Compiler::Compile(str,
name_obj,
line_offset,
@ -1489,8 +1493,11 @@ Local<Script> Script::New(v8::Handle<String> source,
pre_data_impl,
Utils::OpenHandle(*script_data),
i::NOT_NATIVES_CODE);
has_pending_exception = result.is_null();
EXCEPTION_BAILOUT_CHECK(isolate, Local<Script>());
has_pending_exception = result.is_null();
EXCEPTION_BAILOUT_CHECK(isolate, Local<Script>());
raw_result = *result;
}
i::Handle<i::SharedFunctionInfo> result(raw_result, isolate);
return Local<Script>(ToApi<Script>(result));
}

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

@ -2992,11 +2992,11 @@ void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
__ and_(scratch, result, Operand(HeapNumber::kSignMask));
__ Vmov(double_scratch0(), 0.5);
__ vadd(input, input, double_scratch0());
__ vadd(double_scratch0(), input, double_scratch0());
// Check sign of the result: if the sign changed, the input
// value was in ]0.5, 0[ and the result should be -0.
__ vmov(result, input.high());
__ vmov(result, double_scratch0().high());
__ eor(result, result, Operand(scratch), SetCC);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(mi, instr->environment());
@ -3007,7 +3007,7 @@ void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
__ EmitVFPTruncate(kRoundToMinusInf,
double_scratch0().low(),
input,
double_scratch0(),
result,
scratch);
DeoptimizeIf(ne, instr->environment());

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

@ -2770,12 +2770,12 @@ void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
__ movdbl(xmm_scratch, Operand::StaticVariable(one_half));
__ ucomisd(xmm_scratch, input_reg);
__ j(above, &below_half);
// input = input + 0.5
__ addsd(input_reg, xmm_scratch);
// xmm_scratch = input + 0.5
__ addsd(xmm_scratch, input_reg);
// Compute Math.floor(value + 0.5).
// Use truncating instruction (OK because input is positive).
__ cvttsd2si(output_reg, Operand(input_reg));
__ cvttsd2si(output_reg, Operand(xmm_scratch));
// Overflow is signalled with minint.
__ cmp(output_reg, 0x80000000u);

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

@ -665,13 +665,19 @@ class StaticMarkingVisitor : public StaticVisitorBase {
}
// Only flush code for functions.
if (shared_info->code()->kind() != Code::FUNCTION) return false;
if (shared_info->code()->kind() != Code::FUNCTION) {
return false;
}
// Function must be lazy compilable.
if (!shared_info->allows_lazy_compilation()) return false;
if (!shared_info->allows_lazy_compilation()) {
return false;
}
// If this is a full script wrapped in a function we do no flush the code.
if (shared_info->is_toplevel()) return false;
if (shared_info->is_toplevel()) {
return false;
}
// Age this shared function info.
if (shared_info->code_age() < kCodeAgeThreshold) {
@ -864,21 +870,7 @@ class StaticMarkingVisitor : public StaticVisitorBase {
collector->MarkObject(jsfunction->unchecked_shared()->unchecked_code());
if (jsfunction->unchecked_code()->kind() == Code::OPTIMIZED_FUNCTION) {
// For optimized functions we should retain both non-optimized version
// of it's code and non-optimized version of all inlined functions.
// This is required to support bailing out from inlined code.
DeoptimizationInputData* data =
reinterpret_cast<DeoptimizationInputData*>(
jsfunction->unchecked_code()->unchecked_deoptimization_data());
FixedArray* literals = data->UncheckedLiteralArray();
for (int i = 0, count = data->InlinedFunctionCount()->value();
i < count;
i++) {
JSFunction* inlined = reinterpret_cast<JSFunction*>(literals->get(i));
collector->MarkObject(inlined->unchecked_shared()->unchecked_code());
}
collector->MarkInlinedFunctionsCode(jsfunction->unchecked_code());
}
}
@ -994,9 +986,7 @@ class CodeMarkingVisitor : public ThreadVisitor {
: collector_(collector) {}
void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) {
collector_->MarkObject(it.frame()->unchecked_code());
}
collector_->PrepareThreadForCodeFlushing(isolate, top);
}
private:
@ -1027,6 +1017,42 @@ class SharedFunctionInfoMarkingVisitor : public ObjectVisitor {
};
void MarkCompactCollector::MarkInlinedFunctionsCode(Code* code) {
// For optimized functions we should retain both non-optimized version
// of it's code and non-optimized version of all inlined functions.
// This is required to support bailing out from inlined code.
DeoptimizationInputData* data =
reinterpret_cast<DeoptimizationInputData*>(
code->unchecked_deoptimization_data());
FixedArray* literals = data->UncheckedLiteralArray();
for (int i = 0, count = data->InlinedFunctionCount()->value();
i < count;
i++) {
JSFunction* inlined = reinterpret_cast<JSFunction*>(literals->get(i));
MarkObject(inlined->unchecked_shared()->unchecked_code());
}
}
void MarkCompactCollector::PrepareThreadForCodeFlushing(Isolate* isolate,
ThreadLocalTop* top) {
for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) {
// Note: for the frame that has a pending lazy deoptimization
// StackFrame::unchecked_code will return a non-optimized code object for
// the outermost function and StackFrame::LookupCode will return
// actual optimized code object.
StackFrame* frame = it.frame();
Code* code = frame->unchecked_code();
MarkObject(code);
if (frame->is_optimized()) {
MarkInlinedFunctionsCode(frame->LookupCode());
}
}
}
void MarkCompactCollector::PrepareForCodeFlushing() {
ASSERT(heap() == Isolate::Current()->heap());
@ -1050,9 +1076,8 @@ void MarkCompactCollector::PrepareForCodeFlushing() {
// Make sure we are not referencing the code from the stack.
ASSERT(this == heap()->mark_compact_collector());
for (StackFrameIterator it; !it.done(); it.Advance()) {
MarkObject(it.frame()->unchecked_code());
}
PrepareThreadForCodeFlushing(heap()->isolate(),
heap()->isolate()->thread_local_top());
// Iterate the archived stacks in all threads to check if
// the code is referenced.

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

@ -96,6 +96,10 @@ class MarkingStack {
};
// Defined in isolate.h.
class ThreadLocalTop;
// -------------------------------------------------------------------------
// Mark-Compact collector
@ -253,6 +257,14 @@ class MarkCompactCollector {
friend class CodeMarkingVisitor;
friend class SharedFunctionInfoMarkingVisitor;
// Mark non-optimize code for functions inlined into the given optimized
// code. This will prevent it from being flushed.
void MarkInlinedFunctionsCode(Code* code);
// Mark code objects that are active on the stack to prevent them
// from being flushed.
void PrepareThreadForCodeFlushing(Isolate* isolate, ThreadLocalTop* top);
void PrepareForCodeFlushing();
// Marking operations for objects reachable from roots.

28
deps/v8/src/parser.cc

@ -2036,6 +2036,20 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
// reported (underlining).
Expect(Token::RETURN, CHECK_OK);
Token::Value tok = peek();
Statement* result;
if (scanner().HasAnyLineTerminatorBeforeNext() ||
tok == Token::SEMICOLON ||
tok == Token::RBRACE ||
tok == Token::EOS) {
ExpectSemicolon(CHECK_OK);
result = new(zone()) ReturnStatement(GetLiteralUndefined());
} else {
Expression* expr = ParseExpression(true, CHECK_OK);
ExpectSemicolon(CHECK_OK);
result = new(zone()) ReturnStatement(expr);
}
// An ECMAScript program is considered syntactically incorrect if it
// contains a return statement that is not within the body of a
// function. See ECMA-262, section 12.9, page 67.
@ -2048,19 +2062,7 @@ Statement* Parser::ParseReturnStatement(bool* ok) {
Expression* throw_error = NewThrowSyntaxError(type, Handle<Object>::null());
return new(zone()) ExpressionStatement(throw_error);
}
Token::Value tok = peek();
if (scanner().HasAnyLineTerminatorBeforeNext() ||
tok == Token::SEMICOLON ||
tok == Token::RBRACE ||
tok == Token::EOS) {
ExpectSemicolon(CHECK_OK);
return new(zone()) ReturnStatement(GetLiteralUndefined());
}
Expression* expr = ParseExpression(true, CHECK_OK);
ExpectSemicolon(CHECK_OK);
return new(zone()) ReturnStatement(expr);
return result;
}

1
deps/v8/src/preparser.cc

@ -540,6 +540,7 @@ PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) {
Expect(i::Token::LPAREN, CHECK_OK);
ParseExpression(true, CHECK_OK);
Expect(i::Token::RPAREN, ok);
if (peek() == i::Token::SEMICOLON) Consume(i::Token::SEMICOLON);
return Statement::Default();
}

2
deps/v8/src/v8threads.h

@ -72,7 +72,7 @@ class ThreadState {
};
// Defined in top.h
// Defined in isolate.h.
class ThreadLocalTop;

2
deps/v8/src/version.cc

@ -35,7 +35,7 @@
#define MAJOR_VERSION 3
#define MINOR_VERSION 6
#define BUILD_NUMBER 6
#define PATCH_LEVEL 11
#define PATCH_LEVEL 14
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
#define IS_CANDIDATE_VERSION 0

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

@ -2773,10 +2773,10 @@ void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
// This addition might give a result that isn't the correct for
// rounding, due to loss of precision, but only for a number that's
// so big that the conversion below will overflow anyway.
__ addsd(input_reg, xmm_scratch);
__ addsd(xmm_scratch, input_reg);
// Compute Math.floor(input).
// Use truncating instruction (OK because input is positive).
__ cvttsd2si(output_reg, input_reg);
__ cvttsd2si(output_reg, xmm_scratch);
// Overflow is signalled with minint.
__ cmpl(output_reg, Immediate(0x80000000));
DeoptimizeIf(equal, instr->environment());

176
deps/v8/test/cctest/test-parsing.cc

@ -706,3 +706,179 @@ TEST(RegExpScanning) {
TestScanRegExp("/=/", "=");
TestScanRegExp("/=?/", "=?");
}
void TestParserSync(i::Handle<i::String> source, bool allow_lazy) {
uintptr_t stack_limit = i::Isolate::Current()->stack_guard()->real_climit();
// Preparse the data.
i::CompleteParserRecorder log;
i::JavaScriptScanner scanner(i::Isolate::Current()->unicode_cache());
i::GenericStringUC16CharacterStream stream(source, 0, source->length());
scanner.Initialize(&stream);
v8::preparser::PreParser::PreParseResult result =
v8::preparser::PreParser::PreParseProgram(
&scanner, &log, allow_lazy, stack_limit);
CHECK_EQ(v8::preparser::PreParser::kPreParseSuccess, result);
i::ScriptDataImpl data(log.ExtractData());
// Parse the data
i::Handle<i::Script> script = FACTORY->NewScript(source);
i::Parser parser(script, false, NULL, NULL);
i::FunctionLiteral* function =
parser.ParseProgram(source, true, i::kNonStrictMode);
i::String* type_string = NULL;
if (function == NULL) {
// Extract exception from the parser.
i::Handle<i::String> type_symbol = FACTORY->LookupAsciiSymbol("type");
CHECK(i::Isolate::Current()->has_pending_exception());
i::MaybeObject* maybe_object = i::Isolate::Current()->pending_exception();
i::JSObject* exception = NULL;
CHECK(maybe_object->To(&exception));
// Get the type string.
maybe_object = exception->GetProperty(*type_symbol);
CHECK(maybe_object->To(&type_string));
}
// Check that preparsing fails iff parsing fails.
if (data.has_error() && function != NULL) {
i::OS::Print(
"Preparser failed on:\n"
"\t%s\n"
"with error:\n"
"\t%s\n"
"However, the parser succeeded",
*source->ToCString(), data.BuildMessage());
CHECK(false);
} else if (!data.has_error() && function == NULL) {
i::OS::Print(
"Parser failed on:\n"
"\t%s\n"
"with error:\n"
"\t%s\n"
"However, the preparser succeeded",
*source->ToCString(), *type_string->ToCString());
CHECK(false);
}
// Check that preparser and parser produce the same error.
if (function == NULL) {
if (!type_string->IsEqualTo(i::CStrVector(data.BuildMessage()))) {
i::OS::Print(
"Expected parser and preparser to produce the same error on:\n"
"\t%s\n"
"However, found the following error messages\n"
"\tparser: %s\n"
"\tpreparser: %s\n",
*source->ToCString(), *type_string->ToCString(), data.BuildMessage());
CHECK(false);
}
}
}
TEST(ParserSync) {
const char* context_data[][2] = {
{ "", "" },
{ "{", "}" },
{ "if (true) ", " else {}" },
{ "if (true) {} else ", "" },
{ "if (true) ", "" },
{ "do ", " while (false)" },
{ "while (false) ", "" },
{ "for (;;) ", "" },
{ "with ({})", "" },
{ "switch (12) { case 12: ", "}" },
{ "switch (12) { default: ", "}" },
{ "label2: ", "" },
{ NULL, NULL }
};
const char* statement_data[] = {
"{}",
"var x",
"var x = 1",
"const x",
"const x = 1",
";",
"12",
"if (false) {} else ;",
"if (false) {} else {}",
"if (false) {} else 12",
"if (false) ;"
"if (false) {}",
"if (false) 12",
"do {} while (false)",
"for (;;) ;",
"for (;;) {}",
"for (;;) 12",
"continue",
"continue label",
"continue\nlabel",
"break",
"break label",
"break\nlabel",
"return",
"return 12",
"return\n12",
"with ({}) ;",
"with ({}) {}",
"with ({}) 12",
"switch ({}) { default: }"
"label3: "
"throw",
"throw 12",
"throw\n12",
"try {} catch(e) {}",
"try {} finally {}",
"try {} catch(e) {} finally {}",
"debugger",
NULL
};
const char* termination_data[] = {
"",
";",
"\n",
";\n",
"\n;",
NULL
};
v8::HandleScope handles;
v8::Persistent<v8::Context> context = v8::Context::New();
v8::Context::Scope context_scope(context);
int marker;
i::Isolate::Current()->stack_guard()->SetStackLimit(
reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
for (int i = 0; context_data[i][0] != NULL; ++i) {
for (int j = 0; statement_data[j] != NULL; ++j) {
for (int k = 0; termination_data[k] != NULL; ++k) {
int kPrefixLen = i::StrLength(context_data[i][0]);
int kStatementLen = i::StrLength(statement_data[j]);
int kTerminationLen = i::StrLength(termination_data[k]);
int kSuffixLen = i::StrLength(context_data[i][1]);
int kProgramSize = kPrefixLen + kStatementLen + kTerminationLen
+ kSuffixLen + i::StrLength("label: for (;;) { }");
// Plug the source code pieces together.
i::Vector<char> program = i::Vector<char>::New(kProgramSize + 1);
int length = i::OS::SNPrintF(program,
"label: for (;;) { %s%s%s%s }",
context_data[i][0],
statement_data[j],
termination_data[k],
context_data[i][1]);
CHECK(length == kProgramSize);
i::Handle<i::String> source =
FACTORY->NewStringFromAscii(i::CStrVector(program.start()));
TestParserSync(source, true);
TestParserSync(source, false);
}
}
}
}

38
deps/v8/test/mjsunit/compiler/regress-106351.js

@ -0,0 +1,38 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax
// Test Math.round with the input reused in the same expression.
function test(x) {
var v = Math.round(x) - x;
assertEquals(0.5, v);
}
for (var i = 0; i < 5; ++i) test(0.5);
%OptimizeFunctionOnNextCall(test);
test(0.5);

50
deps/v8/test/mjsunit/regress/regress-97116.js

@ -0,0 +1,50 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --expose-gc --allow-natives-syntax
// Check that we are not flushing code for inlined functions that
// have a pending lazy deoptimization on the stack.
function deopt() {
try { } catch (e) { } // Avoid inlining.
%DeoptimizeFunction(outer);
for (var i = 0; i < 10; i++) gc(); // Force code flushing.
}
function outer(should_deopt) {
inner(should_deopt);
}
function inner(should_deopt) {
if (should_deopt) deopt();
}
outer(false);
outer(false);
%OptimizeFunctionOnNextCall(outer);
outer(true);

7
deps/v8/tools/gyp/v8.gyp

@ -641,13 +641,6 @@
],
}
],
['OS=="solaris"', {
'sources': [
'../../src/platform-solaris.cc',
'../../src/platform-posix.cc'
],
}
],
['OS=="mac"', {
'sources': [
'../../src/platform-macos.cc',

Loading…
Cancel
Save