2015年5月1日 星期五

一些 SASS 的詭異編譯行為

最近在研究 SASS 的 Syntax 跟 Behaviour 發現相當多詭異的地方,根據這篇文章 All You Ever Need to Know About Sass Interpolation 探討 SASS 的 Interpolation:

其中像是:

width: calc(10px + 10px);

會被當成 string 編譯成:

width: calc(10px + 10px);

所以為了安插 Expression,就要寫成:

width: calc(#{ 10px + 10px });

而:

$some: 20px;
width: calc(100% - $some);

會變成

width: calc(100% - $some);

但:

 -webkit-transition: all 10s + 1s cubic-bezier(.1 + .1, .10, .25, .90);

Function 裏頭的 Expression 還是會照常編譯,變成:

-webkit-transition: all 11s cubic-bezier(0.2, 0.1, 0.25, 0.9);

根據該文 linear-gradient 也是把 function params 當成 string,但是在新版 SASS 行為卻又不同了;

background: linear-gradient( 10deg + 45deg, blue, #000000 + #010101);

直接編譯成:

background: linear-gradient(55deg, blue, #010101);

啥?

再來看一些例子.. SASS Reference 內提到 expression 之間如果有空白或者逗號就是 List 表示,那麼我假設下面這樣是 List:

>> abc blacc abc
("abc" "blacc" "abc")

這樣是沒錯的,那再來試試看別的:

>> abc blacc a#{test} abc
"abc blacc atest abc"

居然變成 String 了,好吧文件上寫說可以用圓括號將 List 括起來,那這樣呢?

>> (abc blacc a#{test} abc)
"abc blacc atest abc"

居然還是 String .... WTF?





2015年4月26日 星期日

SASS 開發團隊

SASS 一開始是 Hampton Litorn 所設計的,但他現在已經不負責這個專案,現在 SASS 專案的主要執行者是 Natalie Weizenbaum 小姐,據 Twitter 上的 Profile 知道是位 trans coder lady,目前在 Google 工作並參與 DART 專案。好強啊! 據說也是 HAML 專案的開發者之一,她應該也是 libsass 的幕後最主要的推手。

至於 Chris Eppstein 則是 Compass 的作者,Compass 是 SASS 的第一個 framework,而 Chris Eppstein 目前在 Linked-in 工作。

2015年4月20日 星期一

PHP - Deprecation notice

在開發函式庫時,免不了會修正 Class API 或是做一些重新命名, 重構等動作,接著做下一個版本的釋出。

Minor 版本的修正還好,但是 Major version 釋出時,如果你沒有先警告 User 哪些東西已經 deprecated 的話,是會遭到抱怨的。

這邊基本上有幾種做法:


  1. 針對 Critical Deprecation 的,可以 throw 出一個客製的 DeprecationException extends from LogicException
  2. 另外一種做法是比較 soft failure 的,使用 trigger_error,但把 message type 設定成 E_USER_DEPRECATED

以下是使用 trigger_error 的 snippet:


trigger_error("Deprecated class, please use MetadataRevisionSchema instead.", E_USER_DEPRECATED);


2015年3月31日 星期二

iOS 8 地雷地圖

最近為了做 PM2.5 監測用 App - 肺欲清,著手開始了 iOS 的開發,這兩個禮拜來大致上瞭解了 iOS development 如何不踩到地雷的大邏輯。


只要是 Apple 預先幫你用現有元件另外組好的元件都不要用,譬如說:

1. iOS 7 的時候提供了 UISearchDisplayController & Search Bar ,他基本上就是 Search Bar 加上一組隱藏好的 Search Display Controller 幫你處理一些隱藏邏輯,在 iOS 8 的時候 UISearchDisplayController 就被 deprecate 掉了, Apple 建議改用 UISearchController,該元件幫你處理好了 UISearchBar 跟 Search Logic 的部分。但其中自動產生的 SearchBar 如果用了 Scope,Layout 會整個爛掉... 所以這種情況下,倒不如自己手動用 UISearchBar 跟客製化的 Search Controller 會比 UISearchController 或 UISearchDisplayController 來得穩且透明。

2. UITableViewController 就是內建 UITableView 的 Controller,在 ExtendedEdge 會有 Bug .. TableView 會被畫在 StatusBar 底下...

另外建議新的東西如果沒有特別需要,盡量都不要用,舊的被 Deprecated 的反而可以盡量多留久一點,原因是: 舊的會比新的被建議的方式穩定 XD 俗話說 If it's not broken, don't fix it.

#iOSMineMap

2015年3月2日 星期一

Lars Bak 談 JavaScript V8 virtual machine 的設計

Lars Bak 談 JavaScript V8 virtual machine 的設計:
其中 Lars 有談到 V8 不使用 byte code,你能夠執行 JavaScript 唯一的方式就是透過 native code,所有的程式都是先編譯後執行,沒有解譯:
"There is no interpretation and no bytecode."
V8 不像其他 VM 是透過 bytecode 或是像 JVM 有 HotSpot 有多種方式執行程式,如在 interpreter 或 native code 之間切換。Lars Bak 開玩笑的說,Developer 在改 V8 compiler 的時候,他們看到這些 native code ... will be horrified.
直接在執行期間 compile 成 native code 執行的這個設計與一般 VM 大相逕庭,因為不管是 JVM, PHP, Python, Ruby, C# 都是透過 Byte code 做 interpretation,而這點引起了 Erik Meijer 不理解而提出質疑。
Lars Bak 解釋道 「若我們設計了 IR (Intermediate Representation) 中介表示,我們就必須對這些 IR 做驗證 (validation),然而驗證 IR 是非常複雜的,譬如驗證 Byte code 是否有 Violation 等等。 譬如說 JMP,你必須驗證 JMP 的位址是正確的,否則會有安全顧慮。 」
而我認為這是沒錯的,一般 Interpreter 儲存 op list 於 HEAP 中,只需 RW 權限即可竄改 op list,但 V8 是在用戶端執行的,你很難保證在用戶端的環境的安全性是足夠的,我猜這是 Lars Bak 過去在 Sun microsystem 做 JVM 以來的經驗。 Lars Bak 不僅為了高效能設計 V8 而也兼顧了安全性。
話說,翻了幾個 VM 的 source code,不管是 cpython, perl, cruby ,目前覺得還是 V8 的架構最優、workaround 最少、最簡潔,完全是不同等級的實作

同步刊載於 C9S 開源電台

2015年2月27日 星期五

asmjit 與 libjit

大略翻了 asmjit [1] 與 libjit [2] 的實作,大概簡介一下兩者差異:
asmjit 是針對 x86 平台所做的 just-in-time toolkit,可以在 runtime 進行組語編譯並執行,分成兩種 compilation method:
.
1. Assembler: 直接使用 x86 instruction 撰寫編譯,必須寫清楚 register, memory 等 operand。
2. Compiler: 使用抽象化語法進行編譯,不需自己管理暫存器。
.
其中抽象化語法可直接使用 Variable 並且由 Compiler 自行分配暫存器,超出的部分會自動使用 Stack 的空間。

而其語法其實就是 C++,通過調用 FunctionBuilder 來建置 Function ,最後丟給 Compiler 編譯後即可使用,但 Register Allocation 的部分分析能力不強,因此作者建議若有自己做 Analysis 的話,建議還是直接使用 Assembler。 由於是 C++ 實作,asmjit 語法簡潔有力。對 x86 機器的實作算很完整。

而 libjit 較為複雜些,libjit 使用 C 語言實作,編譯單元為 Function,用法類似 asmjit 定義 Function 的方式,但定義起來較為繁瑣。 除了抽象化 opcode 來達到跨平台的目的 (目前支援 arm, x86, x86-64),還實作了 data flow analysis, control flow analysis 來做優化,優化的部分則可以指定等級。

其中 CodeGen 的部分,居然自己定義了一套 DSL 的 parser 來產生類似 LLVM Instruction Table 的定義檔... 完全不容小覷。 據我與 Marttia Barbon 通信內容了解,libjit 產生的 machine code 並不太優。

libjit 中 x86 instruction assembler 的部分,是直接使用 C function 來達成 position independent instruction 的編譯:

    x86_mov_reg_reg(buf, X86_EBP, X86_ESP, 4);

要使用 libjit 來建置一套 language VM 應該是足夠的,只不過 libjit 最近較無積極開發,最近一年的 commit 幾乎都是修正。

2015年2月25日 星期三

CLIFramework - Table Generator

CLIFramework 現在內建 Table Generator,只要輸入 Array,可自動依照不同的 Style 產生 Console 用表格,甚至能輸出成 Markdown 格式表格 (使用 MarkdownStyleTable class)

此套件是參考 Symfony/Console 的 Table Helper 部分功能的重寫及加強,除了 Symfony/Console 現有功能之外:

還可透過指定格屬性 (Cell Attribute),針對單一格或一整列設定色彩、文字對齊或數字格式 (Currency, Number, Duration .. etc)

至於超出欄寬的文字,也可指定使用切斷 (clip), 省略符號 (ellipsis) 或換行 (wrap)

請見範例程式:
https://github.com/c9s/CLIFramework/blob/master/example/table.php


畫面:


2015年2月10日 星期二

閒暇時大致研究了幾個 JIT compiler 實作:

V8 當然不用說,不僅實作了好幾種 CPU 架構的 runtime assembler ,還做了 dynamic re-compilation (Crankshaft engine) 針對 hot code 做 re-compilation。

而 Steffen Müller (@tsee) 的 jit-experimental for Perl 則是將 Perl5 op tree 建構成 libjit 看得懂得 AST,接著丟改 libjit 翻譯回來拿到 machine code,細節沒有看很多,但我猜這個 runtime overhead 一定是很高...
其他使用的 libjit 的 project 則幾乎都是 experimental projects,沒有看到其他使用 libjit 成功的案例。

Reini Urban (@rurbanJit.pm 實作,是把固定幾個 x86 instruction 的 machine code 直接寫成 macro 來使用 (如: x86 prolog, epilog, call, jmp, pushl, popl 等等),然後在模組載入後,把 Perl 的 run op 函數指標 (function pointer) 換成 Jit.pm 自己的實作,接下來就是把一些簡單的 op code 換成預先準備好的 machine code 執行。 但 Jit.pm 一執行就 crash 了..... orz

不過 Jit.pm 也教我幾件事情:
1. memalign 要處理好,不然沒有辦法設置 memory protection
2. self-modifying code 需要呼叫 sys_mprotect 這個修改 page 的 flags ,才能在調用來的記憶體上執行 machine code。
3. Perl 5 有 ASYNC flag (看起來是做 JIT 特別難處理的地方)

現階段看起來,JIT 實作的最佳參考還是 V8
就這樣,有其他細節再繼續做整理...

(以前實在太弱,寫什麼 SIC/XE assembler... 現在覺得當時應該接著練習自幹 x86 assembler 比較實際...)

2015年2月8日 星期日

Getting Merged

昨天在 livehouse 的簡報。但有些內容是現場講的,沒報名到的朋友搜瑞了


libjit 的作者 Rhys Weatherley (dotGNU 的 member) 2009 年時寫到:
"LLVM seems to have been started as a "glorified" static compiler....which aims to (略).... It has been started in 2000, and as of today it is technologically outdated. "
哇....這不是睜眼說瞎話嗎? XD